KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > accounting > payment > GiftCertificateServices


1 /*
2  * $Id: GiftCertificateServices.java 7318 2006-04-17 22:15:43Z sichen $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */

25 package org.ofbiz.accounting.payment;
26
27 import java.math.BigDecimal JavaDoc;
28 import java.sql.Timestamp JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Locale JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Random JavaDoc;
35
36 import org.ofbiz.base.util.Debug;
37 import org.ofbiz.base.util.GeneralException;
38 import org.ofbiz.base.util.UtilDateTime;
39 import org.ofbiz.base.util.UtilMisc;
40 import org.ofbiz.base.util.UtilProperties;
41 import org.ofbiz.base.util.UtilValidate;
42 import org.ofbiz.base.util.collections.ResourceBundleMapWrapper;
43 import org.ofbiz.entity.GenericDelegator;
44 import org.ofbiz.entity.GenericEntityException;
45 import org.ofbiz.entity.GenericValue;
46 import org.ofbiz.entity.util.EntityUtil;
47 import org.ofbiz.order.finaccount.FinAccountHelper;
48 import org.ofbiz.order.order.OrderReadHelper;
49 import org.ofbiz.product.store.ProductStoreWorker;
50 import org.ofbiz.service.DispatchContext;
51 import org.ofbiz.service.GenericServiceException;
52 import org.ofbiz.service.LocalDispatcher;
53 import org.ofbiz.service.ServiceUtil;
54
55 /**
56  *
57  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
58  * @author <a HREF="mailto:sichen@opensourcestrategies.com">Si Chen</a>
59  * @version $Rev: 7318 $
60  * @since 3.3
61  */

62 public class GiftCertificateServices {
63
64     public static final String JavaDoc module = GiftCertificateServices.class.getName();
65     // These are default settings, in case ProductStoreFinActSetting does not have them
66
public static final int CARD_NUMBER_LENGTH = 14;
67     public static final int PIN_NUMBER_LENGTH = 6;
68
69     public static BigDecimal JavaDoc ZERO = new BigDecimal JavaDoc("0.00");
70     
71     // Base Gift Certificate Services
72
public static Map JavaDoc createGiftCertificate(DispatchContext dctx, Map JavaDoc context) {
73         LocalDispatcher dispatcher = dctx.getDispatcher();
74         GenericDelegator delegator = dctx.getDelegator();
75
76         GenericValue userLogin = (GenericValue) context.get("userLogin");
77         String JavaDoc productStoreId = (String JavaDoc) context.get("productStoreId");
78         Double JavaDoc initialAmount = (Double JavaDoc) context.get("initialAmount");
79
80         String JavaDoc partyId = (String JavaDoc) context.get("partyId");
81         if (UtilValidate.isEmpty(partyId)) {
82             partyId = "_NA_";
83         }
84         String JavaDoc currencyUom = (String JavaDoc) context.get("currency");
85         if (UtilValidate.isEmpty(currencyUom)) {
86             currencyUom = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
87         }
88
89         String JavaDoc cardNumber = null;
90         String JavaDoc pinNumber = null;
91         String JavaDoc refNum = null;
92         String JavaDoc finAccountId = null;
93         try {
94             final String JavaDoc accountName = "Gift Certificate Account";
95             final String JavaDoc deposit = "DEPOSIT";
96
97             GenericValue giftCertSettings = delegator.findByPrimaryKeyCache("ProductStoreFinActSetting", UtilMisc.toMap("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId));
98             Map JavaDoc acctResult = null;
99             
100             if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
101                 // TODO: move this code to createFinAccountForStore as well
102
int cardNumberLength = CARD_NUMBER_LENGTH;
103                 int pinNumberLength = PIN_NUMBER_LENGTH;
104                 if (giftCertSettings.getLong("accountCodeLength") != null) {
105                     cardNumberLength = giftCertSettings.getLong("accountCodeLength").intValue();
106                 }
107                 if (giftCertSettings.getLong("pinCodeLength") != null) {
108                     pinNumberLength = giftCertSettings.getLong("pinCodeLength").intValue();
109                 }
110                 cardNumber = generateNumber(delegator, cardNumberLength, true);
111                 pinNumber = generateNumber(delegator, pinNumberLength, false);
112
113                 // in this case, the card number is the finAccountId
114
finAccountId = cardNumber;
115                 
116                 // create the FinAccount
117
Map JavaDoc acctCtx = UtilMisc.toMap("finAccountId", finAccountId);
118                 acctCtx.put("finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId);
119                 acctCtx.put("finAccountName", accountName);
120                 acctCtx.put("finAccountCode", pinNumber);
121                 acctCtx.put("userLogin", userLogin);
122                 acctResult = dispatcher.runSync("createFinAccount", acctCtx);
123             } else {
124                 acctResult = dispatcher.runSync("createFinAccountForStore", UtilMisc.toMap("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId, "userLogin", userLogin));
125                 if (acctResult.get("finAccountId") != null) {
126                     cardNumber = (String JavaDoc) acctResult.get("finAccountId");
127                 }
128                 if (acctResult.get("finAccountCode") != null) {
129                     cardNumber = (String JavaDoc) acctResult.get("finAccountCode");
130                 }
131             }
132             
133             if (ServiceUtil.isError(acctResult)) {
134                 String JavaDoc error = ServiceUtil.getErrorMessage(acctResult);
135                 return ServiceUtil.returnError(error);
136             }
137             
138             // create the initial (deposit) transaction
139
refNum = GiftCertificateServices.createTransaction(delegator, dispatcher, userLogin, initialAmount,
140                     productStoreId, partyId, currencyUom, deposit, finAccountId);
141
142         } catch (GenericEntityException e) {
143             Debug.logError(e, module);
144             return ServiceUtil.returnError("Unable to create gift certificate number.");
145         } catch (GenericServiceException e) {
146             Debug.logError(e, module);
147             return ServiceUtil.returnError("Unable to create gift certificate.");
148         } catch (GeneralException e) {
149             Debug.logError(e, module);
150             return ServiceUtil.returnError(e.getMessage());
151         }
152
153         Map JavaDoc result = ServiceUtil.returnSuccess();
154         result.put("cardNumber", cardNumber);
155         result.put("pinNumber", pinNumber);
156         result.put("initialAmount", initialAmount);
157         result.put("processResult", Boolean.TRUE);
158         result.put("responseCode", "1");
159         result.put("referenceNum", refNum);
160         Debug.log("Create GC Result - " + result, module);
161         return result;
162     }
163
164     public static Map JavaDoc addFundsToGiftCertificate(DispatchContext dctx, Map JavaDoc context) {
165         LocalDispatcher dispatcher = dctx.getDispatcher();
166         GenericDelegator delegator = dctx.getDelegator();
167         final String JavaDoc deposit = "DEPOSIT";
168
169         GenericValue userLogin = (GenericValue) context.get("userLogin");
170         String JavaDoc productStoreId = (String JavaDoc) context.get("productStoreId");
171         String JavaDoc cardNumber = (String JavaDoc) context.get("cardNumber");
172         String JavaDoc pinNumber = (String JavaDoc) context.get("pinNumber");
173         Double JavaDoc amount = (Double JavaDoc) context.get("amount");
174
175         String JavaDoc partyId = (String JavaDoc) context.get("partyId");
176         if (UtilValidate.isEmpty(partyId)) {
177             partyId = "_NA_";
178         }
179         String JavaDoc currencyUom = (String JavaDoc) context.get("currency");
180         if (UtilValidate.isEmpty(currencyUom)) {
181             currencyUom = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
182         }
183
184         String JavaDoc finAccountId = null;
185          // validate the pin if the store requires it and figure out the finAccountId from card number
186
try {
187             GenericValue giftCertSettings = delegator.findByPrimaryKeyCache("ProductStoreFinActSetting", UtilMisc.toMap("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId));
188              if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
189         if (!validatePin(delegator, cardNumber, pinNumber)) {
190             return ServiceUtil.returnError("PIN number is not valid!");
191         }
192                  finAccountId = cardNumber;
193              } else {
194                  GenericValue finAccount = FinAccountHelper.getFinAccountFromCode(cardNumber, delegator);
195                  if (finAccount != null) {
196                      finAccountId = finAccount.getString("finAccountId");
197                  }
198              }
199         } catch (GenericEntityException ex) {
200             return ServiceUtil.returnError("Cannot get store fin account settings " + ex.getMessage());
201         }
202
203         if (finAccountId == null) {
204             return ServiceUtil.returnError("Cannot get fin account for adding to balance");
205         }
206
207         // get the previous balance
208
BigDecimal JavaDoc previousBalance = ZERO;
209         try {
210             previousBalance = FinAccountHelper.getAvailableBalance(cardNumber, currencyUom, delegator);
211         } catch (GeneralException e) {
212             Debug.logError(e, module);
213             return ServiceUtil.returnError(e.getMessage());
214         }
215
216         // create the transaction
217
BigDecimal JavaDoc balance = ZERO;
218         String JavaDoc refNum = null;
219         try {
220             refNum = GiftCertificateServices.createTransaction(delegator, dispatcher, userLogin, amount,
221                     productStoreId, partyId, currencyUom, deposit, finAccountId);
222             balance = FinAccountHelper.getAvailableBalance(cardNumber, currencyUom, delegator);
223         } catch (GeneralException e) {
224             Debug.logError(e, module);
225             return ServiceUtil.returnError(e.getMessage());
226         }
227
228         Map JavaDoc result = ServiceUtil.returnSuccess();
229         result.put("previousBalance", new Double JavaDoc(previousBalance.doubleValue()));
230         result.put("balance", new Double JavaDoc(balance.doubleValue()));
231         result.put("amount", amount);
232         result.put("processResult", Boolean.TRUE);
233         result.put("responseCode", "1");
234         result.put("referenceNum", refNum);
235         Debug.log("Add Funds GC Result - " + result, module);
236         return result;
237     }
238
239     public static Map JavaDoc redeemGiftCertificate(DispatchContext dctx, Map JavaDoc context) {
240         LocalDispatcher dispatcher = dctx.getDispatcher();
241         GenericDelegator delegator = dctx.getDelegator();
242         final String JavaDoc withdrawl = "WITHDRAWAL";
243
244         GenericValue userLogin = (GenericValue) context.get("userLogin");
245         String JavaDoc productStoreId = (String JavaDoc) context.get("productStoreId");
246         String JavaDoc cardNumber = (String JavaDoc) context.get("cardNumber");
247         String JavaDoc pinNumber = (String JavaDoc) context.get("pinNumber");
248         Double JavaDoc amount = (Double JavaDoc) context.get("amount");
249
250         String JavaDoc partyId = (String JavaDoc) context.get("partyId");
251         if (UtilValidate.isEmpty(partyId)) {
252             partyId = "_NA_";
253         }
254         String JavaDoc currencyUom = (String JavaDoc) context.get("currency");
255         if (UtilValidate.isEmpty(currencyUom)) {
256             currencyUom = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
257         }
258
259         // validate the amount
260
if (amount.doubleValue() < 0.00) {
261             return ServiceUtil.returnError("Amount should be a positive number.");
262         }
263
264         // validate the pin if the store requires it
265
try {
266             GenericValue giftCertSettings = delegator.findByPrimaryKeyCache("ProductStoreFinActSetting", UtilMisc.toMap("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId));
267             if ("Y".equals(giftCertSettings.getString("requirePinCode")) && !validatePin(delegator, cardNumber, pinNumber)) {
268                 return ServiceUtil.returnError("PIN number is not valid!");
269             }
270         } catch (GenericEntityException ex) {
271             return ServiceUtil.returnError("Cannot get store fin account settings " + ex.getMessage());
272         }
273         Debug.logInfo("Attempting to redeem GC for " + amount, module);
274
275         // check the actual balance (excluding authorized amounts) and create the transaction if it is sufficient
276
double previousBalance = 0.00;
277         try {
278             previousBalance = FinAccountHelper.getBalance(cardNumber, currencyUom, delegator).doubleValue();
279         } catch (GeneralException e) {
280             Debug.logError(e, module);
281             return ServiceUtil.returnError(e.getMessage());
282         }
283
284         double balance = 0.00;
285         String JavaDoc refNum = null;
286         Boolean JavaDoc procResult;
287         if (previousBalance >= amount.doubleValue()) {
288             try {
289                 refNum = GiftCertificateServices.createTransaction(delegator, dispatcher, userLogin, amount,
290                         productStoreId, partyId, currencyUom, withdrawl, cardNumber);
291                 balance = FinAccountHelper.getAvailableBalance(cardNumber, currencyUom, delegator).doubleValue();
292                 procResult = Boolean.TRUE;
293             } catch (GeneralException e) {
294                 Debug.logError(e, module);
295                 return ServiceUtil.returnError(e.getMessage());
296             }
297         } else {
298             procResult = Boolean.FALSE;
299             balance = previousBalance;
300             refNum = "N/A";
301         }
302
303         Map JavaDoc result = ServiceUtil.returnSuccess();
304         result.put("previousBalance", new Double JavaDoc(previousBalance));
305         result.put("balance", new Double JavaDoc(balance));
306         result.put("amount", amount);
307         result.put("processResult", procResult);
308         result.put("responseCode", "2");
309         result.put("referenceNum", refNum);
310         Debug.log("Redeem GC Result - " + result, module);
311         return result;
312     }
313
314     public static Map JavaDoc checkGiftCertificateBalance(DispatchContext dctx, Map JavaDoc context) {
315         GenericDelegator delegator = dctx.getDelegator();
316         String JavaDoc cardNumber = (String JavaDoc) context.get("cardNumber");
317         String JavaDoc pinNumber = (String JavaDoc) context.get("pinNumber");
318
319         // validate the pin
320
if (!validatePin(delegator, cardNumber, pinNumber)) {
321             return ServiceUtil.returnError("PIN number is not valid!");
322         }
323
324         // TODO: get the real currency from context
325
String JavaDoc currencyUom = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
326         // get the balance
327
double balance = 0.00;
328         try {
329             balance = FinAccountHelper.getAvailableBalance(cardNumber, currencyUom, delegator).doubleValue();
330         } catch (GeneralException e) {
331             return ServiceUtil.returnError(e.getMessage());
332         }
333
334         Map JavaDoc result = ServiceUtil.returnSuccess();
335         result.put("balance", new Double JavaDoc(balance));
336         Debug.log("GC Balance Result - " + result, module);
337         return result;
338     }
339
340     // Fullfilment Services
341
public static Map JavaDoc giftCertificateProcessor(DispatchContext dctx, Map JavaDoc context) {
342         LocalDispatcher dispatcher = dctx.getDispatcher();
343         GenericDelegator delegator = dctx.getDelegator();
344         GenericValue userLogin = (GenericValue) context.get("userLogin");
345
346         Double JavaDoc amount = (Double JavaDoc) context.get("processAmount");
347         String JavaDoc currency = (String JavaDoc) context.get("currency");
348         // make sure we have a currency
349
if (currency == null) {
350             currency = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
351         }
352
353         // get the authorizations
354
GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
355         GenericValue authTransaction = (GenericValue) context.get("authTrans");
356         if (authTransaction == null){
357             authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
358         }
359         if (authTransaction == null) {
360             return ServiceUtil.returnError("No authorization transaction found for the OrderPaymentPreference; cannot capture");
361         }
362        
363         // get the gift certificate and its authorization from the authorization
364
String JavaDoc finAccountAuthId = authTransaction.getString("referenceNum");
365         try {
366             GenericValue finAccountAuth = delegator.findByPrimaryKey("FinAccountAuth", UtilMisc.toMap("finAccountAuthId", finAccountAuthId));
367             GenericValue giftCard = finAccountAuth.getRelatedOne("FinAccount");
368             // make sure authorization has not expired
369
Timestamp JavaDoc authExpiration = finAccountAuth.getTimestamp("thruDate");
370             if ((authExpiration != null) && (authExpiration.before(UtilDateTime.nowTimestamp()))) {
371                 return ServiceUtil.returnError("Authorization transaction [" + authTransaction.getString("paymentGatewayResponseId") + "] has expired as of " + authExpiration);
372             }
373             // make sure the fin account itself has not expired
374
if ((giftCard.getTimestamp("thruDate") != null) && (giftCard.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
375                 return ServiceUtil.returnError("Gift certificate has expired as of " + giftCard.getTimestamp("thruDate"));
376             }
377             
378             // obtain the order information
379
OrderReadHelper orh = new OrderReadHelper(delegator, orderPaymentPreference.getString("orderId"));
380             
381             Map JavaDoc redeemCtx = new HashMap JavaDoc();
382             redeemCtx.put("userLogin", userLogin);
383             redeemCtx.put("productStoreId", orh.getProductStoreId());
384             redeemCtx.put("cardNumber", giftCard.get("finAccountId"));
385             redeemCtx.put("pinNumber", giftCard.get("finAccountCode"));
386             redeemCtx.put("currency", currency);
387             if (orh.getBillToParty() != null) {
388                 redeemCtx.put("partyId", orh.getBillToParty().get("partyId"));
389             }
390             redeemCtx.put("amount", amount);
391
392             // invoke the redeem service
393
Map JavaDoc redeemResult = null;
394             redeemResult = dispatcher.runSync("redeemGiftCertificate", redeemCtx);
395             if (ServiceUtil.isError(redeemResult)) {
396                 return redeemResult;
397             }
398             
399             // now release the authorization should this use the gift card release service?
400
Map JavaDoc releaseResult = dispatcher.runSync("expireFinAccountAuth", UtilMisc.toMap("userLogin", userLogin, "finAccountAuthId", finAccountAuthId));
401             if (ServiceUtil.isError(releaseResult)) {
402                 return releaseResult;
403             }
404             
405             Map JavaDoc result = ServiceUtil.returnSuccess();
406             if (redeemResult != null) {
407                 Boolean JavaDoc processResult = (Boolean JavaDoc) redeemResult.get("processResult");
408                 result.put("processAmount", amount);
409                 result.put("captureResult", processResult);
410                 result.put("captureCode", "C");
411                 result.put("captureRefNum", redeemResult.get("referenceNum"));
412             }
413
414             return result;
415
416         } catch (GenericEntityException ex) {
417             return ServiceUtil.returnError("Cannot process gift card: " + ex.getMessage());
418         } catch (GenericServiceException ex) {
419             return ServiceUtil.returnError("Cannot process gift card: " + ex.getMessage());
420         }
421 }
422
423     
424     public static Map JavaDoc giftCertificateAuthorize(DispatchContext dctx, Map JavaDoc context) {
425         LocalDispatcher dispatcher = dctx.getDispatcher();
426         GenericDelegator delegator = dctx.getDelegator();
427         GenericValue userLogin = (GenericValue) context.get("userLogin");
428
429         GenericValue giftCard = (GenericValue) context.get("giftCard");
430         String JavaDoc currency = (String JavaDoc) context.get("currency");
431         String JavaDoc orderId = (String JavaDoc) context.get("orderId");
432         Double JavaDoc amount = (Double JavaDoc) context.get("processAmount");
433
434         // make sure we have a currency
435
if (currency == null) {
436             currency = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
437         }
438
439         // obtain the order information
440
OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
441         String JavaDoc productStoreId = orh.getProductStoreId();
442         try {
443             // if the store requires pin codes, then validate pin code against card number, and the gift certificate's finAccountId is the gift card's card number
444
// otherwise, the gift card's card number is an ecrypted string, which must be decoded to find the FinAccount
445
GenericValue giftCertSettings = delegator.findByPrimaryKeyCache("ProductStoreFinActSetting", UtilMisc.toMap("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId));
446             GenericValue finAccount = null;
447             String JavaDoc finAccountId = null;
448             if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
449                 if (validatePin(delegator, giftCard.getString("cardNumber"), giftCard.getString("pinNumber"))) {
450                     finAccountId = giftCard.getString("cardNumber");
451                     finAccount = delegator.findByPrimaryKey("FinAccount", UtilMisc.toMap("finAccountId", finAccountId));
452                 }
453             } else {
454                     finAccount = FinAccountHelper.getFinAccountFromCode(giftCard.getString("cardNumber"), delegator);
455                     if (finAccount == null) {
456                         return ServiceUtil.returnError("Gift certificate not found");
457                     }
458                     finAccountId = finAccount.getString("finAccountId");
459             }
460             if (finAccountId == null) {
461                 return ServiceUtil.returnError("Gift certificate pin number is invalid");
462             }
463             
464             // check for expiration date
465
if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
466                 return ServiceUtil.returnError("Gift certificate has expired as of " + finAccount.getTimestamp("thruDate"));
467             }
468             
469             // check the amount to authorize against the available balance of fin account, which includes active authorizations as well as transactions
470
BigDecimal JavaDoc availableBalance = FinAccountHelper.getAvailableBalance(finAccountId, currency, delegator);
471             Boolean JavaDoc processResult = null;
472             String JavaDoc refNum = null;
473             Map JavaDoc result = ServiceUtil.returnSuccess();
474
475             // turn amount into a big decimal, making sure to round and scale it to the same as availableBalance
476
BigDecimal JavaDoc amountBd = (new BigDecimal JavaDoc(amount.doubleValue())).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding);
477
478             // if availableBalance equal to or greater than amount, then auth
479
if (availableBalance.compareTo(amountBd) > -1) {
480                 Timestamp JavaDoc thruDate = null;
481                 if (giftCertSettings.getLong("authValidDays") != null) {
482                     thruDate = UtilDateTime.getDayEnd(UtilDateTime.nowTimestamp(), giftCertSettings.getLong("authValidDays").intValue());
483                 }
484                 Map JavaDoc tmpResult = dispatcher.runSync("createFinAccountAuth", UtilMisc.toMap("finAccountId", finAccountId, "amount", amount, "currencyUomId", currency,
485                         "thruDate", thruDate, "userLogin", userLogin));
486                 if (ServiceUtil.isError(tmpResult)) {
487                     return tmpResult;
488                 } else {
489                     refNum = (String JavaDoc) tmpResult.get("finAccountAuthId");
490                     processResult = Boolean.TRUE;
491                 }
492             } else {
493                 Debug.logError("Attempted to authorize [" + amount + "] against a balance of only [" + availableBalance + "]", module);
494                 refNum = "N/A"; // a refNum is always required from authorization
495
processResult = Boolean.FALSE;
496             }
497             
498             result.put("processAmount", amount);
499             result.put("authResult", processResult);
500             result.put("processAmount", amount);
501             result.put("authFlag", "2");
502             result.put("authCode", "A");
503             result.put("captureCode", "C");
504             result.put("authRefNum", refNum);
505             
506             return result;
507         } catch (GenericEntityException ex) {
508             Debug.logError(ex, "Cannot authorize gift certificate", module);
509             return ServiceUtil.returnError("Cannot authorize gift certificate due to " + ex.getMessage());
510         } catch (GenericServiceException ex) {
511             Debug.logError(ex, "Cannot authorize gift certificate", module);
512             return ServiceUtil.returnError("Cannot authorize gift certificate due to " + ex.getMessage());
513         }
514     }
515     
516     public static Map JavaDoc giftCertificateRefund(DispatchContext dctx, Map JavaDoc context) {
517         GenericValue userLogin = (GenericValue) context.get("userLogin");
518         GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
519         String JavaDoc currency = (String JavaDoc) context.get("currency");
520         Double JavaDoc amount = (Double JavaDoc) context.get("refundAmount");
521         return giftCertificateRestore(dctx, userLogin, paymentPref, amount, currency, "refund");
522     }
523
524     public static Map JavaDoc giftCertificateRelease(DispatchContext dctx, Map JavaDoc context) {
525         LocalDispatcher dispatcher = dctx.getDispatcher();
526         GenericValue userLogin = (GenericValue) context.get("userLogin");
527
528         GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
529
530         String JavaDoc err = "Unable to expire financial account authorization for Gift Certificate: ";
531         try {
532             // expire the related financial authorization transaction
533
GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(paymentPref);
534             if (authTransaction == null) {
535                 return ServiceUtil.returnError(err + " Could not find authorization transaction.");
536             }
537             Map JavaDoc input = UtilMisc.toMap("userLogin", userLogin, "finAccountAuthId", authTransaction.get("referenceNum"));
538             Map JavaDoc serviceResults = dispatcher.runSync("expireFinAccountAuth", input);
539
540             Map JavaDoc result = ServiceUtil.returnSuccess();
541             result.put("releaseRefNum", authTransaction.getString("referenceNum"));
542             result.put("releaseAmount", authTransaction.getDouble("amount"));
543             result.put("releaseResult", new Boolean JavaDoc(true));
544
545             // if there's an error, don't release
546
if (ServiceUtil.isError(serviceResults)) {
547                 return ServiceUtil.returnError(err + ServiceUtil.getErrorMessage(serviceResults));
548             }
549
550             return result;
551         } catch (GenericServiceException e) {
552             Debug.logError(e, e.getMessage(), module);
553             return ServiceUtil.returnError(err + e.getMessage());
554         }
555     }
556
557     private static Map JavaDoc giftCertificateRestore(DispatchContext dctx, GenericValue userLogin, GenericValue paymentPref, Double JavaDoc amount, String JavaDoc currency, String JavaDoc resultPrefix) {
558         LocalDispatcher dispatcher = dctx.getDispatcher();
559         GenericDelegator delegator = dctx.getDelegator();
560
561         // get the orderId for tracking
562
String JavaDoc orderId = paymentPref.getString("orderId");
563         OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
564         String JavaDoc productStoreId = orh.getProductStoreId();
565
566         // party ID for tracking
567
GenericValue placingParty = orh.getPlacingParty();
568         String JavaDoc partyId = null;
569         if (placingParty != null) {
570             partyId = placingParty.getString("partyId");
571         }
572
573         // get the GiftCard VO
574
GenericValue giftCard = null;
575         try {
576             giftCard = paymentPref.getRelatedOne("GiftCard");
577         } catch (GenericEntityException e) {
578             Debug.logError(e, "Unable to get GiftCard from OrderPaymentPreference", module);
579             return ServiceUtil.returnError("Unable to locate GiftCard Information");
580         }
581
582         if (giftCard == null) {
583             return ServiceUtil.returnError("Attempt to release GiftCard payment faild; not a valid GiftCard record");
584         }
585
586         // make sure we have a currency
587
if (currency == null) {
588             currency = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
589         }
590
591         Map JavaDoc refundCtx = new HashMap JavaDoc();
592         refundCtx.put("productStoreId", productStoreId);
593         refundCtx.put("currency", currency);
594         refundCtx.put("partyId", partyId);
595         //reloadCtx.put("orderId", orderId);
596
refundCtx.put("cardNumber", giftCard.get("cardNumber"));
597         refundCtx.put("pinNumber", giftCard.get("pinNumber"));
598         refundCtx.put("amount", amount);
599         refundCtx.put("userLogin", userLogin);
600
601         Map JavaDoc restoreGcResult = null;
602         try {
603             restoreGcResult = dispatcher.runSync("addFundsToGiftCertificate", refundCtx);
604         } catch (GenericServiceException e) {
605             Debug.logError(e, module);
606             return ServiceUtil.returnError("Unable to call refund service!");
607         }
608         if (ServiceUtil.isError(restoreGcResult)) {
609             return ServiceUtil.returnError(ServiceUtil.getErrorMessage(restoreGcResult));
610         }
611
612         Map JavaDoc result = ServiceUtil.returnSuccess();
613         if (restoreGcResult != null) {
614             Boolean JavaDoc processResult = (Boolean JavaDoc) restoreGcResult.get("processResult");
615             result.put(resultPrefix + "Amount", amount);
616             result.put(resultPrefix + "Result", processResult);
617             result.put(resultPrefix + "Code", "R");
618             result.put(resultPrefix + "Flag", restoreGcResult.get("responseCode"));
619             result.put(resultPrefix + "RefNum", restoreGcResult.get("referenceNum"));
620         }
621
622         return result;
623     }
624
625     public static Map JavaDoc giftCertificatePurchase(DispatchContext dctx, Map JavaDoc context) {
626         // this service should always be called via FULFILLMENT_EXTASYNC
627
LocalDispatcher dispatcher = dctx.getDispatcher();
628         GenericDelegator delegator = dctx.getDelegator();
629         GenericValue userLogin = (GenericValue) context.get("userLogin");
630         GenericValue orderItem = (GenericValue) context.get("orderItem");
631         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
632
633         // order ID for tracking
634
String JavaDoc orderId = orderItem.getString("orderId");
635
636         // the order header for store info
637
GenericValue orderHeader = null;
638         try {
639             orderHeader = orderItem.getRelatedOne("OrderHeader");
640         } catch (GenericEntityException e) {
641             Debug.logError(e, "Unable to get OrderHeader from OrderItem",module);
642             return ServiceUtil.returnError("Unable to get OrderHeader from OrderItem");
643         }
644
645         // get the order read helper
646
OrderReadHelper orh = new OrderReadHelper(orderHeader);
647
648         // get the currency
649
String JavaDoc currency = orh.getCurrency();
650
651         // make sure we have a currency
652
if (currency == null) {
653             currency = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
654         }
655
656         // get the product store
657
String JavaDoc productStoreId = null;
658         if (orderHeader != null) {
659             productStoreId = orh.getProductStoreId();
660         }
661         if (productStoreId == null) {
662             return ServiceUtil.returnError("Unable to process gift card purchase; no productStoreId on OrderHeader : " + orderId);
663         }
664
665         // party ID for tracking
666
GenericValue placingParty = orh.getPlacingParty();
667         String JavaDoc partyId = null;
668         if (placingParty != null) {
669             partyId = placingParty.getString("partyId");
670         }
671
672         // amount/quantity of the gift card(s)
673
Double JavaDoc amount = orderItem.getDouble("unitPrice");
674         Double JavaDoc quantity = orderItem.getDouble("quantity");
675
676         // the product entity needed for information
677
GenericValue product = null;
678         try {
679             product = orderItem.getRelatedOne("Product");
680         } catch (GenericEntityException e) {
681             Debug.logError(e, "Unable to get Product from OrderItem", module);
682         }
683         if (product == null) {
684             return ServiceUtil.returnError("No product associated with OrderItem, cannot fulfill gift card");
685         }
686
687         // Gift certificate settings are per store in this entity
688
GenericValue giftCertSettings = null;
689         try {
690             giftCertSettings = delegator.findByPrimaryKeyCache("ProductStoreFinActSetting", UtilMisc.toMap("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId));
691         } catch (GenericEntityException e) {
692             Debug.logError(e, "Unable to get Product Store FinAccount settings for " + FinAccountHelper.giftCertFinAccountTypeId, module);
693             ServiceUtil.returnError("Unable to get Product Store FinAccount settings for " + FinAccountHelper.giftCertFinAccountTypeId + ": " + e.getMessage());
694         }
695        
696         // survey information
697
String JavaDoc surveyId = giftCertSettings.getString("purchaseSurveyId");
698
699         // get the survey response
700
GenericValue surveyResponse = null;
701         try {
702             Map JavaDoc fields = UtilMisc.toMap("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId"), "surveyId", surveyId);
703             List JavaDoc order = UtilMisc.toList("-responseDate");
704             List JavaDoc responses = delegator.findByAnd("SurveyResponse", fields, order);
705             // there should be only one
706
surveyResponse = EntityUtil.getFirst(responses);
707         } catch (GenericEntityException e) {
708             Debug.logError(e, module);
709             return ServiceUtil.returnError("Unable to get survey response information; cannot fulfill gift card");
710         }
711         if (surveyResponse == null) {
712             return ServiceUtil.returnError("Survey response came back null from the database for order item: " + orderItem);
713         }
714
715         // get the response answers
716
List JavaDoc responseAnswers = null;
717         try {
718             responseAnswers = surveyResponse.getRelated("SurveyResponseAnswer");
719         } catch (GenericEntityException e) {
720             Debug.logError(e, module);
721             return ServiceUtil.returnError("Unable to get survey response answers from survey response; cannot fulfill gift card");
722         }
723
724         // make a map of answer info
725
Map JavaDoc answerMap = new HashMap JavaDoc();
726         if (responseAnswers != null) {
727             Iterator JavaDoc rai = responseAnswers.iterator();
728             while (rai.hasNext()) {
729                 GenericValue answer = (GenericValue) rai.next();
730                 GenericValue question = null;
731                 try {
732                     question = answer.getRelatedOne("SurveyQuestion");
733                 } catch (GenericEntityException e) {
734                     Debug.logError(e, module);
735                     return ServiceUtil.returnError("Unable to get survey question from answer");
736                 }
737                 if (question != null) {
738                     String JavaDoc desc = question.getString("description");
739                     String JavaDoc ans = answer.getString("textResponse"); // only support text response types for now
740
answerMap.put(desc, ans);
741                 }
742             }
743         }
744
745         // get the send to email address - key defined in product store settings entity
746
String JavaDoc sendToKey = giftCertSettings.getString("purchSurveySendTo");
747         String JavaDoc sendToEmail = (String JavaDoc) answerMap.get(sendToKey);
748
749         // get the copyMe flag and set the order email address
750
String JavaDoc orderEmails = orh.getOrderEmailString();
751         String JavaDoc copyMeField = giftCertSettings.getString("purchSurveyCopyMe");
752         String JavaDoc copyMeResp = copyMeField != null ? (String JavaDoc) answerMap.get(copyMeField) : null;
753         boolean copyMe = (UtilValidate.isNotEmpty(copyMeField)
754                 && UtilValidate.isNotEmpty(copyMeResp) && "true".equalsIgnoreCase(copyMeResp)) ? true : false;
755
756         int qtyLoop = quantity.intValue();
757         for (int i = 0; i < qtyLoop; i++) {
758             // create a gift certificate
759
Map JavaDoc createGcCtx = new HashMap JavaDoc();
760             //createGcCtx.put("paymentConfig", paymentConfig);
761
createGcCtx.put("productStoreId", productStoreId);
762             createGcCtx.put("currency", currency);
763             createGcCtx.put("partyId", partyId);
764             //createGcCtx.put("orderId", orderId);
765
createGcCtx.put("initialAmount", amount);
766             createGcCtx.put("userLogin", userLogin);
767
768             Map JavaDoc createGcResult = null;
769             try {
770                 createGcResult = dispatcher.runSync("createGiftCertificate", createGcCtx);
771             } catch (GenericServiceException e) {
772                 Debug.logError(e, module);
773                 return ServiceUtil.returnError("Unable to create gift certificate: " + e.getMessage());
774             }
775             if (ServiceUtil.isError(createGcResult)) {
776                 return ServiceUtil.returnError("Create Gift Certificate Failed: " + ServiceUtil.getErrorMessage(createGcResult));
777             }
778
779             // create the fulfillment record
780
Map JavaDoc gcFulFill = new HashMap JavaDoc();
781             gcFulFill.put("typeEnumId", "GC_ACTIVATE");
782             gcFulFill.put("partyId", partyId);
783             gcFulFill.put("orderId", orderId);
784             gcFulFill.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
785             gcFulFill.put("surveyResponseId", surveyResponse.get("surveyResponseId"));
786             gcFulFill.put("cardNumber", createGcResult.get("cardNumber"));
787             gcFulFill.put("pinNumber", createGcResult.get("pinNumber"));
788             gcFulFill.put("amount", createGcResult.get("initialAmount"));
789             gcFulFill.put("responseCode", createGcResult.get("responseCode"));
790             gcFulFill.put("referenceNum", createGcResult.get("referenceNum"));
791             gcFulFill.put("userLogin", userLogin);
792             try {
793                 dispatcher.runAsync("createGcFulFillmentRecord", gcFulFill, true);
794             } catch (GenericServiceException e) {
795                 Debug.logError(e, module);
796                 return ServiceUtil.returnError("Unable to store fulfillment info: " + e.getMessage());
797             }
798
799             // add some information to the answerMap for the email
800
answerMap.put("cardNumber", createGcResult.get("cardNumber"));
801             answerMap.put("pinNumber", createGcResult.get("pinNumber"));
802             answerMap.put("amount", createGcResult.get("initialAmount"));
803
804             // get the email setting for this email type
805
GenericValue productStoreEmail = null;
806             String JavaDoc emailType = "PRDS_GC_PURCHASE";
807             try {
808                 productStoreEmail = delegator.findByPrimaryKey("ProductStoreEmailSetting", UtilMisc.toMap("productStoreId", productStoreId, "emailType", emailType));
809             } catch (GenericEntityException e) {
810                 Debug.logError(e, "Unable to get product store email setting for gift card purchase", module);
811             }
812             if (productStoreEmail == null) {
813                 Debug.logError("No gift card purchase email setting found for this store; cannot send gift card information", module);
814             } else {
815                 ResourceBundleMapWrapper uiLabelMap = (ResourceBundleMapWrapper) UtilProperties.getResourceBundleMap("EcommerceUiLabels", locale);
816                 uiLabelMap.addBottomResourceBundle("OrderUiLabels");
817                 uiLabelMap.addBottomResourceBundle("CommonUiLabels");
818                 answerMap.put("uiLabelMap", uiLabelMap);
819                 answerMap.put("locale", locale);
820                 
821                 // set the bcc address(s)
822
String JavaDoc bcc = productStoreEmail.getString("bccAddress");
823                 if (copyMe) {
824                     if (UtilValidate.isNotEmpty(bcc)) {
825                         bcc = bcc + "," + orderEmails;
826                     } else {
827                         bcc = orderEmails;
828                     }
829                 }
830
831                 Map JavaDoc emailCtx = new HashMap JavaDoc();
832                 String JavaDoc bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
833                 if (UtilValidate.isEmpty(bodyScreenLocation)) {
834                     bodyScreenLocation = ProductStoreWorker.getDefaultProductStoreEmailScreenLocation(emailType);
835                 }
836                 emailCtx.put("bodyScreenUri", bodyScreenLocation);
837                 emailCtx.put("bodyParameters", answerMap);
838                 emailCtx.put("sendTo", sendToEmail);
839                 emailCtx.put("contentType", productStoreEmail.get("contentType"));
840                 emailCtx.put("sendFrom", productStoreEmail.get("fromAddress"));
841                 emailCtx.put("sendCc", productStoreEmail.get("ccAddress"));
842                 emailCtx.put("sendBcc", bcc);
843                 emailCtx.put("subject", productStoreEmail.getString("subject"));
844                 emailCtx.put("userLogin", userLogin);
845
846                 // send off the email async so we will retry on failed attempts
847
// SC 20060405: Changed to runSync because runAsync kept getting an error:
848
// Problem serializing service attributes (Cannot serialize object of class java.util.PropertyResourceBundle)
849
try {
850                     dispatcher.runSync("sendMailFromScreen", emailCtx);
851                 } catch (GenericServiceException e) {
852                     Debug.logError(e, "Problem sending mail", module);
853                     // this is fatal; we will rollback and try again later
854
return ServiceUtil.returnError("Error sending Gift Card notice email: " + e.toString());
855                 }
856             }
857         }
858
859         return ServiceUtil.returnSuccess();
860     }
861
862     public static Map JavaDoc giftCertificateReload(DispatchContext dctx, Map JavaDoc context) {
863         // this service should always be called via FULFILLMENT_EXTSYNC
864
LocalDispatcher dispatcher = dctx.getDispatcher();
865         GenericDelegator delegator = dctx.getDelegator();
866         GenericValue userLogin = (GenericValue) context.get("userLogin");
867         GenericValue orderItem = (GenericValue) context.get("orderItem");
868         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
869
870         // order ID for tracking
871
String JavaDoc orderId = orderItem.getString("orderId");
872
873         // the order header for store info
874
GenericValue orderHeader = null;
875         try {
876             orderHeader = orderItem.getRelatedOne("OrderHeader");
877         } catch (GenericEntityException e) {
878             Debug.logError(e, "Unable to get OrderHeader from OrderItem",module);
879             return ServiceUtil.returnError("Unable to get OrderHeader from OrderItem");
880         }
881
882         // get the order read helper
883
OrderReadHelper orh = new OrderReadHelper(orderHeader);
884
885         // get the currency
886
String JavaDoc currency = orh.getCurrency();
887
888         // make sure we have a currency
889
if (currency == null) {
890             currency = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
891         }
892
893         // get the product store
894
String JavaDoc productStoreId = null;
895         if (orderHeader != null) {
896             productStoreId = orh.getProductStoreId();
897         }
898         if (productStoreId == null) {
899             return ServiceUtil.returnError("Unable to process gift card reload; no productStoreId on OrderHeader : " + orderId);
900         }
901
902         // payment config
903
GenericValue paymentSetting = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, "GIFT_CARD", null, true);
904         String JavaDoc paymentConfig = null;
905         if (paymentSetting != null) {
906             paymentConfig = paymentSetting.getString("paymentPropertiesPath");
907         }
908         if (paymentConfig == null) {
909             return ServiceUtil.returnError("Unable to get payment configuration file");
910         }
911
912         // party ID for tracking
913
GenericValue placingParty = orh.getPlacingParty();
914         String JavaDoc partyId = null;
915         if (placingParty != null) {
916             partyId = placingParty.getString("partyId");
917         }
918
919         // amount of the gift card reload
920
Double JavaDoc amount = orderItem.getDouble("unitPrice");
921
922         // survey information
923
String JavaDoc surveyId = UtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.surveyId");
924
925         // get the survey response
926
GenericValue surveyResponse = null;
927         try {
928             Map JavaDoc fields = UtilMisc.toMap("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId"), "surveyId", surveyId);
929             List JavaDoc order = UtilMisc.toList("-responseDate");
930             List JavaDoc responses = delegator.findByAnd("SurveyResponse", fields, order);
931             // there should be only one
932
surveyResponse = EntityUtil.getFirst(responses);
933         } catch (GenericEntityException e) {
934             Debug.logError(e, module);
935             return ServiceUtil.returnError("Unable to get survey response information; cannot fulfill gift card reload");
936         }
937
938         // get the response answers
939
List JavaDoc responseAnswers = null;
940         try {
941             responseAnswers = surveyResponse.getRelated("SurveyResponseAnswer");
942         } catch (GenericEntityException e) {
943             Debug.logError(e, module);
944             return ServiceUtil.returnError("Unable to get survey response answers from survey response; cannot fulfill gift card reload");
945         }
946
947         // make a map of answer info
948
Map JavaDoc answerMap = new HashMap JavaDoc();
949         if (responseAnswers != null) {
950             Iterator JavaDoc rai = responseAnswers.iterator();
951             while (rai.hasNext()) {
952                 GenericValue answer = (GenericValue) rai.next();
953                 GenericValue question = null;
954                 try {
955                     question = answer.getRelatedOne("SurveyQuestion");
956                 } catch (GenericEntityException e) {
957                     Debug.logError(e, module);
958                     return ServiceUtil.returnError("Unable to get survey question from answer");
959                 }
960                 if (question != null) {
961                     String JavaDoc desc = question.getString("description");
962                     String JavaDoc ans = answer.getString("textResponse"); // only support text response types for now
963
answerMap.put(desc, ans);
964                 }
965             }
966         }
967
968         String JavaDoc cardNumberKey = UtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.survey.cardNumber");
969         String JavaDoc pinNumberKey = UtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.survey.pinNumber");
970         String JavaDoc cardNumber = (String JavaDoc) answerMap.get(cardNumberKey);
971         String JavaDoc pinNumber = (String JavaDoc) answerMap.get(pinNumberKey);
972
973         // reload the gift card
974
Map JavaDoc reloadCtx = new HashMap JavaDoc();
975         reloadCtx.put("productStoreId", productStoreId);
976         reloadCtx.put("currency", currency);
977         reloadCtx.put("partyId", partyId);
978         //reloadCtx.put("orderId", orderId);
979
reloadCtx.put("cardNumber", cardNumber);
980         reloadCtx.put("pinNumber", pinNumber);
981         reloadCtx.put("amount", amount);
982         reloadCtx.put("userLogin", userLogin);
983
984         String JavaDoc errorMessage = null;
985         Map JavaDoc reloadGcResult = null;
986         try {
987             reloadGcResult = dispatcher.runSync("addFundsToGiftCertificate", reloadCtx);
988         } catch (GenericServiceException e) {
989             Debug.logError(e, module);
990             errorMessage = "Unable to call reload service!";
991         }
992         if (ServiceUtil.isError(reloadGcResult)) {
993             errorMessage = ServiceUtil.getErrorMessage(reloadGcResult);
994         }
995
996         // create the fulfillment record
997
Map JavaDoc gcFulFill = new HashMap JavaDoc();
998         gcFulFill.put("typeEnumId", "GC_RELOAD");
999         gcFulFill.put("userLogin", userLogin);
1000        gcFulFill.put("partyId", partyId);
1001        gcFulFill.put("orderId", orderId);
1002        gcFulFill.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
1003        gcFulFill.put("surveyResponseId", surveyResponse.get("surveyResponseId"));
1004        gcFulFill.put("cardNumber", cardNumber);
1005        gcFulFill.put("pinNumber", pinNumber);
1006        gcFulFill.put("amount", amount);
1007        if (reloadGcResult != null) {
1008            gcFulFill.put("responseCode", reloadGcResult.get("responseCode"));
1009            gcFulFill.put("referenceNum", reloadGcResult.get("referenceNum"));
1010        }
1011        try {
1012            dispatcher.runAsync("createGcFulFillmentRecord", gcFulFill, true);
1013        } catch (GenericServiceException e) {
1014            Debug.logError(e, module);
1015            return ServiceUtil.returnError("Unable to store fulfillment info");
1016        }
1017
1018        if (errorMessage != null) {
1019            // there was a problem
1020
Debug.logError("Reload Failed Need to Refund : " + reloadGcResult, module);
1021
1022            // process the return
1023
try {
1024                Map JavaDoc refundCtx = UtilMisc.toMap("orderItem", orderItem, "partyId", partyId, "userLogin", userLogin);
1025                dispatcher.runAsync("refundGcPurchase", refundCtx, null, true, 300, true);
1026            } catch (GenericServiceException e) {
1027                Debug.logError(e, "ERROR! Unable to call create refund service; this failed reload will NOT be refunded", module);
1028            }
1029
1030            return ServiceUtil.returnError(errorMessage);
1031        }
1032
1033        // add some information to the answerMap for the email
1034
answerMap.put("processResult", reloadGcResult.get("processResult"));
1035        answerMap.put("responseCode", reloadGcResult.get("responseCode"));
1036        answerMap.put("previousAmount", reloadGcResult.get("previousBalance"));
1037        answerMap.put("amount", reloadGcResult.get("amount"));
1038
1039        // get the email setting for this email type
1040
GenericValue productStoreEmail = null;
1041        String JavaDoc emailType = "PRDS_GC_RELOAD";
1042        try {
1043            productStoreEmail = delegator.findByPrimaryKey("ProductStoreEmailSetting", UtilMisc.toMap("productStoreId", productStoreId, "emailType", emailType));
1044        } catch (GenericEntityException e) {
1045            Debug.logError(e, "Unable to get product store email setting for gift card purchase", module);
1046        }
1047        if (productStoreEmail == null) {
1048            Debug.logError("No gift card purchase email setting found for this store; cannot send gift card information", module);
1049        } else {
1050            ResourceBundleMapWrapper uiLabelMap = (ResourceBundleMapWrapper) UtilProperties.getResourceBundleMap("EcommerceUiLabels", locale);
1051            uiLabelMap.addBottomResourceBundle("OrderUiLabels");
1052            uiLabelMap.addBottomResourceBundle("CommonUiLabels");
1053            answerMap.put("uiLabelMap", uiLabelMap);
1054            answerMap.put("locale", locale);
1055
1056            Map JavaDoc emailCtx = new HashMap JavaDoc();
1057            String JavaDoc bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
1058            if (UtilValidate.isEmpty(bodyScreenLocation)) {
1059                bodyScreenLocation = ProductStoreWorker.getDefaultProductStoreEmailScreenLocation(emailType);
1060            }
1061            emailCtx.put("bodyScreenUri", bodyScreenLocation);
1062            emailCtx.put("bodyParameters", answerMap);
1063            emailCtx.put("sendTo", orh.getOrderEmailString());
1064            emailCtx.put("contentType", productStoreEmail.get("contentType"));
1065            emailCtx.put("sendFrom", productStoreEmail.get("fromAddress"));
1066            emailCtx.put("sendCc", productStoreEmail.get("ccAddress"));
1067            emailCtx.put("sendBcc", productStoreEmail.get("bccAddress"));
1068            emailCtx.put("subject", productStoreEmail.getString("subject"));
1069            emailCtx.put("userLogin", userLogin);
1070
1071            // send off the email async so we will retry on failed attempts
1072
try {
1073                dispatcher.runAsync("sendMailFromScreen", emailCtx);
1074            } catch (GenericServiceException e) {
1075                Debug.logError(e, "Problem sending mail", module);
1076                // this is fatal; we will rollback and try again later
1077
return ServiceUtil.returnError("Error sending Gift Card notice email: " + e.toString());
1078            }
1079        }
1080
1081        return ServiceUtil.returnSuccess();
1082    }
1083
1084    // Tracking Service
1085
public static Map JavaDoc createFulfillmentRecord(DispatchContext dctx, Map JavaDoc context) {
1086        GenericDelegator delegator = dctx.getDelegator();
1087
1088        // create the fulfillment record
1089
GenericValue gcFulFill = delegator.makeValue("GiftCardFulfillment", null);
1090        gcFulFill.set("fulfillmentId", delegator.getNextSeqId("GiftCardFulfillment"));
1091        gcFulFill.set("typeEnumId", context.get("typeEnumId"));
1092        gcFulFill.set("merchantId", context.get("merchantId"));
1093        gcFulFill.set("partyId", context.get("partyId"));
1094        gcFulFill.set("orderId", context.get("orderId"));
1095        gcFulFill.set("orderItemSeqId", context.get("orderItemSeqId"));
1096        gcFulFill.set("surveyResponseId", context.get("surveyResponseId"));
1097        gcFulFill.set("cardNumber", context.get("cardNumber"));
1098        gcFulFill.set("pinNumber", context.get("pinNumber"));
1099        gcFulFill.set("amount", context.get("amount"));
1100        gcFulFill.set("responseCode", context.get("responseCode"));
1101        gcFulFill.set("referenceNum", context.get("referenceNum"));
1102        gcFulFill.set("authCode", context.get("authCode"));
1103        gcFulFill.set("fulfillmentDate", UtilDateTime.nowTimestamp());
1104        try {
1105            delegator.create(gcFulFill);
1106        } catch (GenericEntityException e) {
1107            Debug.logError(e, module);
1108            return ServiceUtil.returnError("Unable to store fulfillment info");
1109        }
1110        return ServiceUtil.returnSuccess();
1111    }
1112
1113    // Refund Service
1114
public static Map JavaDoc refundGcPurchase(DispatchContext dctx, Map JavaDoc context) {
1115        LocalDispatcher dispatcher = dctx.getDispatcher();
1116        GenericDelegator delegator = dctx.getDelegator();
1117        GenericValue userLogin = (GenericValue) context.get("userLogin");
1118        GenericValue orderItem = (GenericValue) context.get("orderItem");
1119        String JavaDoc partyId = (String JavaDoc) context.get("partyId");
1120
1121        // refresh the item object for status changes
1122
try {
1123            orderItem.refresh();
1124        } catch (GenericEntityException e) {
1125            Debug.logError(e, module);
1126        }
1127
1128        Map JavaDoc returnableInfo = null;
1129        try {
1130            returnableInfo = dispatcher.runSync("getReturnableQuantity", UtilMisc.toMap("orderItem", orderItem, "userLogin", userLogin));
1131        } catch (GenericServiceException e) {
1132            Debug.logError(e, module);
1133            return ServiceUtil.returnError("Unable to get returnable infomation for order item : " + orderItem);
1134        }
1135
1136        if (returnableInfo != null) {
1137            Double JavaDoc returnableQuantity = (Double JavaDoc) returnableInfo.get("returnableQuantity");
1138            Double JavaDoc returnablePrice = (Double JavaDoc) returnableInfo.get("returnablePrice");
1139            Debug.logInfo("Returnable INFO : " + returnableQuantity + " @ " + returnablePrice + " :: " + orderItem, module);
1140
1141            // create the return header
1142
Map JavaDoc returnHeaderInfo = new HashMap JavaDoc();
1143            returnHeaderInfo.put("fromPartyId", partyId);
1144            returnHeaderInfo.put("userLogin", userLogin);
1145            Map JavaDoc returnHeaderResp = null;
1146            try {
1147                returnHeaderResp = dispatcher.runSync("createReturnHeader", returnHeaderInfo);
1148            } catch (GenericServiceException e) {
1149                Debug.logError(e, module);
1150                return ServiceUtil.returnError("Unable to create return header");
1151            }
1152
1153            if (returnHeaderResp != null) {
1154                String JavaDoc errorMessage = ServiceUtil.getErrorMessage(returnHeaderResp);
1155                if (errorMessage != null) {
1156                    return ServiceUtil.returnError(errorMessage);
1157                }
1158            }
1159
1160            String JavaDoc returnId = null;
1161            if (returnHeaderResp != null) {
1162                returnId = (String JavaDoc) returnHeaderResp.get("returnId");
1163            }
1164
1165            if (returnId == null) {
1166                return ServiceUtil.returnError("Create return did not return a valid return id");
1167            }
1168
1169            // create the return item
1170
Map JavaDoc returnItemInfo = new HashMap JavaDoc();
1171            returnItemInfo.put("returnId", returnId);
1172            returnItemInfo.put("returnReasonId", "RTN_DIG_FILL_FAIL");
1173            returnItemInfo.put("returnTypeId", "RTN_REFUND");
1174            returnItemInfo.put("returnItemType", "ITEM");
1175            returnItemInfo.put("description", orderItem.get("itemDescription"));
1176            returnItemInfo.put("orderId", orderItem.get("orderId"));
1177            returnItemInfo.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
1178            returnItemInfo.put("returnQuantity", returnableQuantity);
1179            returnItemInfo.put("returnPrice", returnablePrice);
1180            returnItemInfo.put("userLogin", userLogin);
1181            Map JavaDoc returnItemResp = null;
1182            try {
1183                returnItemResp = dispatcher.runSync("createReturnItem", returnItemInfo);
1184            } catch (GenericServiceException e) {
1185                Debug.logError(e, module);
1186                return ServiceUtil.returnError("Unable to create return item");
1187            }
1188
1189            if (returnItemResp != null) {
1190                String JavaDoc errorMessage = ServiceUtil.getErrorMessage(returnItemResp);
1191                if (errorMessage != null) {
1192                    return ServiceUtil.returnError(errorMessage);
1193                }
1194            }
1195
1196            String JavaDoc returnItemSeqId = null;
1197            if (returnItemResp != null) {
1198                returnItemSeqId = (String JavaDoc) returnItemResp.get("returnItemSeqId");
1199            }
1200
1201            if (returnItemSeqId == null) {
1202                return ServiceUtil.returnError("Create return item did not return a valid sequence id");
1203            } else {
1204                Debug.logVerbose("Created return item : " + returnId + " / " + returnItemSeqId, module);
1205            }
1206
1207            // need the admin userLogin to "fake" out the update service
1208
GenericValue admin = null;
1209            try {
1210                admin = delegator.findByPrimaryKey("UserLogin", UtilMisc.toMap("userLoginId", "admin"));
1211            } catch (GenericEntityException e) {
1212                Debug.logError(e, module);
1213                return ServiceUtil.returnError("Unable to look up UserLogin from database");
1214            }
1215
1216            // update the status to received so it can process
1217
Map JavaDoc updateReturnInfo = new HashMap JavaDoc();
1218            updateReturnInfo.put("returnId", returnId);
1219            updateReturnInfo.put("statusId", "RETURN_RECEIVED");
1220            updateReturnInfo.put("currentStatusId", "RETURN_REQUESTED");
1221            updateReturnInfo.put("userLogin", admin);
1222            Map JavaDoc updateReturnResp = null;
1223            try {
1224                updateReturnResp = dispatcher.runSync("updateReturnHeader", updateReturnInfo);
1225            } catch (GenericServiceException e) {
1226                Debug.logError(e, module);
1227                return ServiceUtil.returnError("Unable to update return header status");
1228            }
1229
1230            if (updateReturnResp != null) {
1231                String JavaDoc errorMessage = ServiceUtil.getErrorMessage(updateReturnResp);
1232                if (errorMessage != null) {
1233                    return ServiceUtil.returnError(errorMessage);
1234                }
1235            }
1236        }
1237
1238        return ServiceUtil.returnSuccess();
1239    }
1240
1241    // Private worker methods
1242
private static boolean validatePin(GenericDelegator delegator, String JavaDoc cardNumber, String JavaDoc pinNumber) {
1243        GenericValue finAccount = null;
1244        try {
1245            finAccount = delegator.findByPrimaryKey("FinAccount", UtilMisc.toMap("finAccountId", cardNumber));
1246        } catch (GenericEntityException e) {
1247            Debug.logError(e, module);
1248        }
1249        if (finAccount != null) {
1250            String JavaDoc dbPin = finAccount.getString("finAccountCode");
1251            Debug.log("GC Pin Validation: [Sent: " + pinNumber + "] [Actual: " + dbPin + "]", module);
1252            if (dbPin != null && dbPin.equals(pinNumber)) {
1253                return true;
1254            }
1255        } else {
1256            Debug.logInfo("GC FinAccount record not found (" + cardNumber + ")", module);
1257        }
1258        return false;
1259    }
1260
1261    private static String JavaDoc createTransaction(GenericDelegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, Double JavaDoc amount,
1262            String JavaDoc productStoreId, String JavaDoc partyId, String JavaDoc currencyUom, String JavaDoc txType, String JavaDoc finAccountId) throws GeneralException {
1263        final String JavaDoc coParty = getPayToPartyId(delegator, productStoreId);
1264        final String JavaDoc paymentMethodType = "GIFT_CERTIFICATE";
1265
1266        if (UtilValidate.isEmpty(partyId)) {
1267            partyId = "_NA_";
1268        }
1269
1270        String JavaDoc paymentType = null;
1271        String JavaDoc partyIdFrom = null;
1272        String JavaDoc partyIdTo = null;
1273        if ("DEPOSIT".equals(txType)) {
1274            paymentType = "GC_DEPOSIT";
1275            partyIdFrom = partyId;
1276            partyIdTo = coParty;
1277        } else if ("WITHDRAWAL".equals(txType)) {
1278            paymentType = "GC_WITHDRAWAL";
1279            partyIdFrom = coParty;
1280            partyIdTo = partyId;
1281        } else {
1282            throw new GeneralException("Unable to create financial account transaction!");
1283        }
1284
1285        // create the payment for the transaction
1286
Map JavaDoc paymentCtx = UtilMisc.toMap("paymentTypeId", paymentType);
1287        paymentCtx.put("paymentMethodTypeId", paymentMethodType);
1288        //paymentCtx.put("paymentMethodId", "");
1289
//paymentCtx.put("paymentGatewayResponseId", "");
1290
paymentCtx.put("partyIdTo", partyIdTo);
1291        paymentCtx.put("partyIdFrom", partyIdFrom);
1292        paymentCtx.put("statusId", "PMNT_RECEIVED");
1293        //paymentCtx.put("paymentPreferenceId", "");
1294
paymentCtx.put("currencyUomId", currencyUom);
1295        paymentCtx.put("amount", amount);
1296        paymentCtx.put("userLogin", userLogin);
1297        paymentCtx.put("paymentRefNum", "N/A");
1298
1299        String JavaDoc paymentId = null;
1300        Map JavaDoc payResult = null;
1301        try {
1302            payResult = dispatcher.runSync("createPayment", paymentCtx);
1303        } catch (GenericServiceException e) {
1304            throw new GeneralException(e);
1305        }
1306        if (payResult == null) {
1307            throw new GeneralException("Unknow error in creating financial account transaction!");
1308        }
1309        if (ServiceUtil.isError(payResult)) {
1310            throw new GeneralException(ServiceUtil.getErrorMessage(payResult));
1311        } else {
1312            paymentId = (String JavaDoc) payResult.get("paymentId");
1313        }
1314
1315        // create the initial transaction
1316
Map JavaDoc transCtx = UtilMisc.toMap("finAccountTransTypeId", txType);
1317        transCtx.put("finAccountId", finAccountId);
1318        transCtx.put("partyId", userLogin.getString("partyId"));
1319        transCtx.put("userLogin", userLogin);
1320        transCtx.put("paymentId", paymentId);
1321
1322        Map JavaDoc transResult = null;
1323        String JavaDoc txId = null;
1324        try {
1325            transResult = dispatcher.runSync("createFinAccountTrans", transCtx);
1326        } catch (GenericServiceException e) {
1327            throw new GeneralException(e);
1328        }
1329        if (transResult == null) {
1330            throw new GeneralException("Unknown error in creating financial account transaction!");
1331        }
1332        if (ServiceUtil.isError(transResult)) {
1333            throw new GeneralException(ServiceUtil.getErrorMessage(transResult));
1334        } else {
1335            txId = (String JavaDoc) transResult.get("finAccountTransId");
1336        }
1337
1338        return txId;
1339    }
1340
1341    private static String JavaDoc generateNumber(GenericDelegator delegator, int length, boolean isId) throws GenericEntityException {
1342        if (length > 19) {
1343            length = 19;
1344        }
1345
1346        Random JavaDoc rand = new Random JavaDoc();
1347        boolean isValid = false;
1348        String JavaDoc number = null;
1349        while (!isValid) {
1350            number = "";
1351            for (int i = 0; i < length; i++) {
1352                int randInt = rand.nextInt(9);
1353                number = number + randInt;
1354            }
1355
1356            if (isId) {
1357                int check = UtilValidate.getLuhnCheckDigit(number);
1358                number = number + check;
1359
1360                // validate the number
1361
if (checkCardNumber(number)) {
1362                    // make sure this number doens't already exist
1363
isValid = checkNumberInDatabase(delegator, number);
1364                }
1365            } else {
1366                isValid = true;
1367            }
1368        }
1369        return number;
1370    }
1371
1372    private static boolean checkNumberInDatabase(GenericDelegator delegator, String JavaDoc number) throws GenericEntityException {
1373        GenericValue finAccount = delegator.findByPrimaryKey("FinAccount", UtilMisc.toMap("finAccountId", number));
1374        if (finAccount == null) {
1375            return true;
1376        }
1377        return false;
1378    }
1379
1380    private static boolean checkCardNumber(String JavaDoc number) {
1381        number = number.replaceAll("\\D", "");
1382        return UtilValidate.sumIsMod10(UtilValidate.getLuhnSum(number));
1383    }
1384
1385    private static String JavaDoc getPayToPartyId(GenericDelegator delegator, String JavaDoc productStoreId) {
1386        String JavaDoc payToPartyId = "Company"; // default value
1387
GenericValue productStore = null;
1388        try {
1389            productStore = delegator.findByPrimaryKey("ProductStore", UtilMisc.toMap("productStoreId", productStoreId));
1390        } catch (GenericEntityException e) {
1391            Debug.logError(e, "Unable to locate ProductStore (" + productStoreId + ")", module);
1392            return null;
1393        }
1394        if (productStore != null && productStore.get("payToPartyId") != null) {
1395            payToPartyId = productStore.getString("payToPartyId");
1396        }
1397        return payToPartyId;
1398    }
1399}
1400
Popular Tags