blob: d72e9f300aafd7b7243630c55a8bcb410341f9c3 [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*******************************************************************************/
package org.apache.ofbiz.accounting.payment;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtilProperties;
import org.apache.ofbiz.order.finaccount.FinAccountHelper;
import org.apache.ofbiz.order.order.OrderReadHelper;
import org.apache.ofbiz.product.store.ProductStoreWorker;
import org.apache.ofbiz.service.DispatchContext;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ServiceUtil;
public class GiftCertificateServices {
public static final String module = GiftCertificateServices.class.getName();
public static final String resourceError = "AccountingErrorUiLabels";
public static final String resourceOrderError = "OrderErrorUiLabels";
// These are default settings, in case ProductStoreFinActSetting does not have them
public static final int CARD_NUMBER_LENGTH = 14;
public static final int PIN_NUMBER_LENGTH = 6;
public static BigDecimal ZERO = BigDecimal.ZERO;
// Base Gift Certificate Services
public static Map<String, Object> createGiftCertificate(DispatchContext dctx, Map<String, ? extends Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
Locale locale = (Locale) context.get("locale");
GenericValue userLogin = (GenericValue) context.get("userLogin");
String productStoreId = (String) context.get("productStoreId");
BigDecimal initialAmount = (BigDecimal) context.get("initialAmount");
String partyId = (String) context.get("partyId");
if (UtilValidate.isEmpty(partyId)) {
partyId = "_NA_";
}
String currencyUom = (String) context.get("currency");
if (UtilValidate.isEmpty(currencyUom)) {
currencyUom = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
String cardNumber = null;
String pinNumber = null;
String refNum = null;
String finAccountId = null;
try {
final String accountName = "Gift Certificate Account";
final String deposit = "DEPOSIT";
GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
.where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
.cache().queryOne();
Map<String, Object> acctResult = null;
if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
// TODO: move this code to createFinAccountForStore as well
int cardNumberLength = CARD_NUMBER_LENGTH;
int pinNumberLength = PIN_NUMBER_LENGTH;
if (giftCertSettings.getLong("accountCodeLength") != null) {
cardNumberLength = giftCertSettings.getLong("accountCodeLength").intValue();
}
if (giftCertSettings.getLong("pinCodeLength") != null) {
pinNumberLength = giftCertSettings.getLong("pinCodeLength").intValue();
}
cardNumber = generateNumber(delegator, cardNumberLength, true);
pinNumber = generateNumber(delegator, pinNumberLength, false);
// in this case, the card number is the finAccountId
finAccountId = cardNumber;
// create the FinAccount
Map<String, Object> acctCtx = UtilMisc.<String, Object>toMap("finAccountId", finAccountId);
acctCtx.put("finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId);
acctCtx.put("finAccountName", accountName);
acctCtx.put("finAccountCode", pinNumber);
acctCtx.put("userLogin", userLogin);
acctResult = dispatcher.runSync("createFinAccount", acctCtx);
} else {
acctResult = dispatcher.runSync("createFinAccountForStore", UtilMisc.<String, Object>toMap("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId, "userLogin", userLogin));
if (acctResult.get("finAccountId") != null) {
finAccountId = cardNumber = (String) acctResult.get("finAccountId");
}
if (acctResult.get("finAccountCode") != null) {
cardNumber = (String) acctResult.get("finAccountCode");
}
}
if (ServiceUtil.isError(acctResult)) {
String error = ServiceUtil.getErrorMessage(acctResult);
return ServiceUtil.returnError(error);
}
// create the initial (deposit) transaction
// do something tricky here: run as the "system" user
// that can actually create a financial account transaction
GenericValue permUserLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").cache().queryOne();
refNum = createTransaction(delegator, dispatcher, permUserLogin, initialAmount, productStoreId,
partyId, currencyUom, deposit, finAccountId, locale);
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCreationError", locale));
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCreationError", locale));
} catch (GeneralException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(e.getMessage());
}
Map<String, Object> result = ServiceUtil.returnSuccess();
result.put("cardNumber", cardNumber);
result.put("pinNumber", pinNumber);
result.put("initialAmount", initialAmount);
result.put("processResult", Boolean.TRUE);
result.put("responseCode", "1");
result.put("referenceNum", refNum);
Debug.logInfo("Create GC Result - " + result, module);
return result;
}
public static Map<String, Object> addFundsToGiftCertificate(DispatchContext dctx, Map<String, ? extends Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
Locale locale = (Locale) context.get("locale");
final String deposit = "DEPOSIT";
GenericValue userLogin = (GenericValue) context.get("userLogin");
String productStoreId = (String) context.get("productStoreId");
String cardNumber = (String) context.get("cardNumber");
String pinNumber = (String) context.get("pinNumber");
BigDecimal amount = (BigDecimal) context.get("amount");
String partyId = (String) context.get("partyId");
if (UtilValidate.isEmpty(partyId)) {
partyId = "_NA_";
}
String currencyUom = (String) context.get("currency");
if (UtilValidate.isEmpty(currencyUom)) {
currencyUom = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
String finAccountId = null;
GenericValue finAccount = null;
// validate the pin if the store requires it and figure out the finAccountId from card number
try {
GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
.where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
.cache().queryOne();
if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
if (!validatePin(delegator, cardNumber, pinNumber)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberPinNotValid", locale));
}
finAccountId = cardNumber;
} else {
finAccount = FinAccountHelper.getFinAccountFromCode(cardNumber, delegator);
if (finAccount != null) {
finAccountId = finAccount.getString("finAccountId");
}
}
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountSetting",
UtilMisc.toMap("productStoreId", productStoreId,
"finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId), locale));
}
if (finAccountId == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", ""), locale));
}
if (finAccount == null) {
try {
finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", finAccountId).queryOne();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", finAccountId), locale));
}
}
// get the previous balance
BigDecimal previousBalance = ZERO;
if (finAccount.get("availableBalance") != null) {
previousBalance = finAccount.getBigDecimal("availableBalance");
}
// create the transaction
BigDecimal balance = ZERO;
String refNum = null;
try {
refNum = GiftCertificateServices.createTransaction(delegator, dispatcher, userLogin, amount, productStoreId, partyId,
currencyUom, deposit, finAccountId, locale);
finAccount.refresh();
balance = finAccount.getBigDecimal("availableBalance");
} catch (GeneralException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(e.getMessage());
}
Map<String, Object> result = ServiceUtil.returnSuccess();
result.put("previousBalance", previousBalance);
result.put("balance", balance);
result.put("amount", amount);
result.put("processResult", Boolean.TRUE);
result.put("responseCode", "1");
result.put("referenceNum", refNum);
Debug.logInfo("Add Funds GC Result - " + result, module);
return result;
}
public static Map<String, Object> redeemGiftCertificate(DispatchContext dctx, Map<String, ? extends Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
final String withdrawl = "WITHDRAWAL";
Locale locale = (Locale) context.get("locale");
GenericValue userLogin = (GenericValue) context.get("userLogin");
String productStoreId = (String) context.get("productStoreId");
String cardNumber = (String) context.get("cardNumber");
String pinNumber = (String) context.get("pinNumber");
BigDecimal amount = (BigDecimal) context.get("amount");
String partyId = (String) context.get("partyId");
if (UtilValidate.isEmpty(partyId)) {
partyId = "_NA_";
}
String currencyUom = (String) context.get("currency");
if (UtilValidate.isEmpty(currencyUom)) {
currencyUom = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
// validate the amount
if (amount.compareTo(BigDecimal.ZERO) < 0) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountMustBePositive", locale));
}
// validate the pin if the store requires it
try {
GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
.where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
.cache().queryOne();
if ("Y".equals(giftCertSettings.getString("requirePinCode")) && !validatePin(delegator, cardNumber, pinNumber)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberPinNotValid", locale));
}
} catch (GenericEntityException ex) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountSetting",
UtilMisc.toMap("productStoreId", productStoreId,
"finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId), locale));
}
Debug.logInfo("Attempting to redeem GC for " + amount, module);
GenericValue finAccount = null;
try {
finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", cardNumber).queryOne();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", cardNumber), locale));
}
// check the actual balance (excluding authorized amounts) and create the transaction if it is sufficient
BigDecimal previousBalance = finAccount.get("actualBalance") == null ? BigDecimal.ZERO : finAccount.getBigDecimal("actualBalance");
BigDecimal balance = BigDecimal.ZERO;
String refNum = null;
Boolean procResult;
if (previousBalance.compareTo(amount) >= 0) {
try {
refNum = GiftCertificateServices.createTransaction(delegator, dispatcher, userLogin, amount, productStoreId,
partyId, currencyUom, withdrawl, cardNumber, locale);
finAccount.refresh();
balance = finAccount.get("availableBalance") == null ? BigDecimal.ZERO : finAccount.getBigDecimal("availableBalance");
procResult = Boolean.TRUE;
} catch (GeneralException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(e.getMessage());
}
} else {
procResult = Boolean.FALSE;
balance = previousBalance;
refNum = "N/A";
}
Map<String, Object> result = ServiceUtil.returnSuccess();
result.put("previousBalance", previousBalance);
result.put("balance", balance);
result.put("amount", amount);
result.put("processResult", procResult);
result.put("responseCode", "2");
result.put("referenceNum", refNum);
Debug.logInfo("Redeem GC Result - " + result, module);
return result;
}
public static Map<String, Object> checkGiftCertificateBalance(DispatchContext dctx, Map<String, ? extends Object> context) {
Delegator delegator = dctx.getDelegator();
String cardNumber = (String) context.get("cardNumber");
String pinNumber = (String) context.get("pinNumber");
Locale locale = (Locale) context.get("locale");
// validate the pin
if (!validatePin(delegator, cardNumber, pinNumber)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberPinNotValid", locale));
}
GenericValue finAccount = null;
try {
finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", cardNumber).queryOne();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", cardNumber), locale));
}
// TODO: get the real currency from context
// get the balance
BigDecimal balance = finAccount.get("availableBalance") == null ? BigDecimal.ZERO : finAccount.getBigDecimal("availableBalance");
Map<String, Object> result = ServiceUtil.returnSuccess();
result.put("balance", balance);
Debug.logInfo("GC Balance Result - " + result, module);
return result;
}
// Fullfilment Services
public static Map<String, Object> giftCertificateProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
BigDecimal amount = (BigDecimal) context.get("processAmount");
String currency = (String) context.get("currency");
// make sure we have a currency
if (currency == null) {
currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
// get the authorizations
GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
GenericValue authTransaction = (GenericValue) context.get("authTrans");
if (authTransaction == null) {
authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
}
if (authTransaction == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountCannotCapture", locale));
}
// get the gift certificate and its authorization from the authorization
String finAccountAuthId = authTransaction.getString("referenceNum");
try {
GenericValue finAccountAuth = EntityQuery.use(delegator).from("FinAccountAuth").where("finAccountAuthId", finAccountAuthId).queryOne();
GenericValue giftCard = finAccountAuth.getRelatedOne("FinAccount", false);
// make sure authorization has not expired
Timestamp authExpiration = finAccountAuth.getTimestamp("thruDate");
if ((authExpiration != null) && (authExpiration.before(UtilDateTime.nowTimestamp()))) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountAuthorizationExpired",
UtilMisc.toMap("paymentGatewayResponseId", authTransaction.getString("paymentGatewayResponseId"),
"authExpiration", authExpiration), locale));
}
// make sure the fin account itself has not expired
if ((giftCard.getTimestamp("thruDate") != null) && (giftCard.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberExpired",
UtilMisc.toMap("thruDate", giftCard.getTimestamp("thruDate")), locale));
}
// obtain the order information
OrderReadHelper orh = new OrderReadHelper(delegator, orderPaymentPreference.getString("orderId"));
Map<String, Object> redeemCtx = new HashMap<String, Object>();
redeemCtx.put("userLogin", userLogin);
redeemCtx.put("productStoreId", orh.getProductStoreId());
redeemCtx.put("cardNumber", giftCard.get("finAccountId"));
redeemCtx.put("pinNumber", giftCard.get("finAccountCode"));
redeemCtx.put("currency", currency);
if (orh.getBillToParty() != null) {
redeemCtx.put("partyId", orh.getBillToParty().get("partyId"));
}
redeemCtx.put("amount", amount);
// invoke the redeem service
Map<String, Object> redeemResult = null;
redeemResult = dispatcher.runSync("redeemGiftCertificate", redeemCtx);
if (ServiceUtil.isError(redeemResult)) {
return redeemResult;
}
// now release the authorization should this use the gift card release service?
Map<String, Object> releaseResult = dispatcher.runSync("expireFinAccountAuth",
UtilMisc.<String, Object>toMap("userLogin", userLogin, "finAccountAuthId", finAccountAuthId));
if (ServiceUtil.isError(releaseResult)) {
return releaseResult;
}
String authRefNum = authTransaction.getString("referenceNum");
Map<String, Object> result = ServiceUtil.returnSuccess();
if (redeemResult != null) {
Boolean processResult = (Boolean) redeemResult.get("processResult");
result.put("processAmount", amount);
result.put("captureResult", processResult);
result.put("captureCode", "C");
result.put("captureRefNum", redeemResult.get("referenceNum"));
result.put("authRefNum", authRefNum);
}
return result;
} catch (GenericEntityException ex) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotProcess",
UtilMisc.toMap("errorString", ex.getMessage()), locale));
} catch (GenericServiceException ex) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotProcess",
UtilMisc.toMap("errorString", ex.getMessage()), locale));
}
}
public static Map<String, Object> giftCertificateAuthorize(DispatchContext dctx, Map<String, ? extends Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
GenericValue giftCard = (GenericValue) context.get("giftCard");
String currency = (String) context.get("currency");
String orderId = (String) context.get("orderId");
BigDecimal amount = (BigDecimal) context.get("processAmount");
// make sure we have a currency
if (currency == null) {
currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
// obtain the order information
OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
String productStoreId = orh.getProductStoreId();
try {
// 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
// otherwise, the gift card's card number is an ecrypted string, which must be decoded to find the FinAccount
GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
.where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
.cache().queryOne();
GenericValue finAccount = null;
String finAccountId = null;
if (UtilValidate.isNotEmpty(giftCertSettings)) {
if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
if (validatePin(delegator, giftCard.getString("cardNumber"), giftCard.getString("pinNumber"))) {
finAccountId = giftCard.getString("cardNumber");
finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", finAccountId).queryOne();
}
} else {
finAccount = FinAccountHelper.getFinAccountFromCode(giftCard.getString("cardNumber"), delegator);
if (finAccount == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberNotFound",
UtilMisc.toMap("finAccountId", ""), locale));
}
finAccountId = finAccount.getString("finAccountId");
}
} else {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountSetting",
UtilMisc.toMap("productStoreId", productStoreId,
"finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId), locale));
}
if (finAccountId == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberPinNotValid", locale));
}
// check for expiration date
if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberExpired",
UtilMisc.toMap("thruDate", finAccount.getTimestamp("thruDate")), locale));
}
// check the amount to authorize against the available balance of fin account, which includes active authorizations as well as transactions
BigDecimal availableBalance = finAccount.getBigDecimal("availableBalance");
Boolean processResult = null;
String refNum = null;
Map<String, Object> result = ServiceUtil.returnSuccess();
// make sure to round and scale it to the same as availableBalance
amount = amount.setScale(FinAccountHelper.decimals, FinAccountHelper.rounding);
// if availableBalance equal to or greater than amount, then auth
if (UtilValidate.isNotEmpty(availableBalance) && availableBalance.compareTo(amount) >= 0) {
Timestamp thruDate = null;
if (giftCertSettings.getLong("authValidDays") != null) {
thruDate = UtilDateTime.getDayEnd(UtilDateTime.nowTimestamp(), giftCertSettings.getLong("authValidDays"));
}
Map<String, Object> tmpResult = dispatcher.runSync("createFinAccountAuth",
UtilMisc.<String, Object>toMap("finAccountId", finAccountId,
"amount", amount, "currencyUomId", currency,
"thruDate", thruDate, "userLogin", userLogin));
if (ServiceUtil.isError(tmpResult)) {
return tmpResult;
} else {
refNum = (String) tmpResult.get("finAccountAuthId");
processResult = Boolean.TRUE;
}
} else {
Debug.logError("Attempted to authorize [" + amount + "] against a balance of only [" + availableBalance + "]", module);
refNum = "N/A"; // a refNum is always required from authorization
processResult = Boolean.FALSE;
}
result.put("processAmount", amount);
result.put("authResult", processResult);
result.put("processAmount", amount);
result.put("authFlag", "2");
result.put("authCode", "A");
result.put("captureCode", "C");
result.put("authRefNum", refNum);
return result;
} catch (GenericEntityException ex) {
Debug.logError(ex, "Cannot authorize gift certificate", module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotAuthorize",
UtilMisc.toMap("errorString", ex.getMessage()), locale));
} catch (GenericServiceException ex) {
Debug.logError(ex, "Cannot authorize gift certificate", module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotAuthorize",
UtilMisc.toMap("errorString", ex.getMessage()), locale));
}
}
public static Map<String, Object> giftCertificateRefund(DispatchContext dctx, Map<String, ? extends Object> context) {
GenericValue userLogin = (GenericValue) context.get("userLogin");
GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
String currency = (String) context.get("currency");
BigDecimal amount = (BigDecimal) context.get("refundAmount");
Locale locale = (Locale) context.get("locale");
return giftCertificateRestore(dctx, userLogin, paymentPref, amount, currency, "refund", locale);
}
public static Map<String, Object> giftCertificateRelease(DispatchContext dctx, Map<String, ? extends Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
GenericValue userLogin = (GenericValue) context.get("userLogin");
GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
Locale locale = (Locale) context.get("locale");
String err = UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotBeExpired", locale);
try {
// expire the related financial authorization transaction
GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(paymentPref);
if (authTransaction == null) {
return ServiceUtil.returnError(err + UtilProperties.getMessage(resourceError,
"AccountingFinAccountCannotFindAuthorization", locale));
}
Map<String, Object> input = UtilMisc.<String, Object>toMap("userLogin", userLogin,
"finAccountAuthId", authTransaction.get("referenceNum"));
Map<String, Object> serviceResults = dispatcher.runSync("expireFinAccountAuth", input);
Map<String, Object> result = ServiceUtil.returnSuccess();
result.put("releaseRefNum", authTransaction.getString("referenceNum"));
result.put("releaseAmount", authTransaction.getBigDecimal("amount"));
result.put("releaseResult", Boolean.TRUE);
// if there's an error, don't release
if (ServiceUtil.isError(serviceResults)) {
return ServiceUtil.returnError(err + ServiceUtil.getErrorMessage(serviceResults));
}
return result;
} catch (GenericServiceException e) {
Debug.logError(e, e.getMessage(), module);
return ServiceUtil.returnError(err + e.getMessage());
}
}
private static Map<String, Object> giftCertificateRestore(DispatchContext dctx, GenericValue userLogin, GenericValue paymentPref,
BigDecimal amount, String currency, String resultPrefix, Locale locale) {
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
// get the orderId for tracking
String orderId = paymentPref.getString("orderId");
OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
String productStoreId = orh.getProductStoreId();
// party ID for tracking
GenericValue placingParty = orh.getPlacingParty();
String partyId = null;
if (placingParty != null) {
partyId = placingParty.getString("partyId");
}
// get the GiftCard VO
GenericValue giftCard = null;
try {
giftCard = paymentPref.getRelatedOne("GiftCard", false);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get GiftCard from OrderPaymentPreference", module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotLocateItFromOrderPaymentPreference", locale));
}
if (giftCard == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotRelease", locale));
}
// make sure we have a currency
if (currency == null) {
currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
Map<String, Object> refundCtx = new HashMap<String, Object>();
refundCtx.put("productStoreId", productStoreId);
refundCtx.put("currency", currency);
refundCtx.put("partyId", partyId);
refundCtx.put("cardNumber", giftCard.get("cardNumber"));
refundCtx.put("pinNumber", giftCard.get("pinNumber"));
refundCtx.put("amount", amount);
refundCtx.put("userLogin", userLogin);
Map<String, Object> restoreGcResult = null;
try {
restoreGcResult = dispatcher.runSync("addFundsToGiftCertificate", refundCtx);
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberRefundCallError", locale));
}
if (ServiceUtil.isError(restoreGcResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(restoreGcResult));
}
Map<String, Object> result = ServiceUtil.returnSuccess();
if (restoreGcResult != null) {
Boolean processResult = (Boolean) restoreGcResult.get("processResult");
result.put(resultPrefix + "Amount", amount);
result.put(resultPrefix + "Result", processResult);
result.put(resultPrefix + "Code", "R");
result.put(resultPrefix + "Flag", restoreGcResult.get("responseCode"));
result.put(resultPrefix + "RefNum", restoreGcResult.get("referenceNum"));
}
return result;
}
public static Map<String, Object> giftCertificatePurchase(DispatchContext dctx, Map<String, ? extends Object> context) {
// this service should always be called via FULFILLMENT_EXTASYNC
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
GenericValue userLogin = (GenericValue) context.get("userLogin");
GenericValue orderItem = (GenericValue) context.get("orderItem");
Locale locale = (Locale) context.get("locale");
// order ID for tracking
String orderId = orderItem.getString("orderId");
// the order header for store info
GenericValue orderHeader = null;
try {
orderHeader = orderItem.getRelatedOne("OrderHeader", false);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get OrderHeader from OrderItem",module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderCannotGetOrderHeader", UtilMisc.toMap("orderId", orderId), locale));
}
// get the order read helper
OrderReadHelper orh = new OrderReadHelper(orderHeader);
// get the currency
String currency = orh.getCurrency();
// make sure we have a currency
if (currency == null) {
currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
// get the product store
String productStoreId = null;
if (orderHeader != null) {
productStoreId = orh.getProductStoreId();
}
if (productStoreId == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotProcess",
UtilMisc.toMap("orderId", orderId), locale));
}
// party ID for tracking
GenericValue placingParty = orh.getPlacingParty();
String partyId = null;
if (placingParty != null) {
partyId = placingParty.getString("partyId");
}
// amount/quantity of the gift card(s)
BigDecimal amount = orderItem.getBigDecimal("unitPrice");
BigDecimal quantity = orderItem.getBigDecimal("quantity");
// the product entity needed for information
GenericValue product = null;
try {
product = orderItem.getRelatedOne("Product", false);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get Product from OrderItem", module);
}
if (product == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotFulfill", locale));
}
// Gift certificate settings are per store in this entity
GenericValue giftCertSettings = null;
try {
giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting")
.where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId)
.cache().queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get Product Store FinAccount settings for " + FinAccountHelper.giftCertFinAccountTypeId, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingFinAccountSetting",
UtilMisc.toMap("productStoreId", productStoreId,
"finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId), locale) + ": " + e.getMessage());
}
// survey information
String surveyId = giftCertSettings.getString("purchaseSurveyId");
// get the survey response
GenericValue surveyResponse = null;
try {
// there should be only one
surveyResponse = EntityQuery.use(delegator).from("SurveyResponse")
.where("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId"), "surveyId", surveyId)
.orderBy("-responseDate").queryFirst();
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotFulfill", locale));
}
if (surveyResponse == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotFulfill", locale));
}
// get the response answers
List<GenericValue> responseAnswers = null;
try {
responseAnswers = surveyResponse.getRelated("SurveyResponseAnswer", null, null, false);
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotFulfillFromSurveyAnswers", locale));
}
// make a map of answer info
Map<String, Object> answerMap = new HashMap<String, Object>();
if (responseAnswers != null) {
for (GenericValue answer : responseAnswers) {
GenericValue question = null;
try {
question = answer.getRelatedOne("SurveyQuestion", false);
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotFulfillFromSurveyAnswers", locale));
}
if (question != null) {
String desc = question.getString("description");
String ans = answer.getString("textResponse"); // only support text response types for now
answerMap.put(desc, ans);
}
}
}
// get the send to email address - key defined in product store settings entity
String sendToKey = giftCertSettings.getString("purchSurveySendTo");
String sendToEmail = (String) answerMap.get(sendToKey);
// get the copyMe flag and set the order email address
String orderEmails = orh.getOrderEmailString();
String copyMeField = giftCertSettings.getString("purchSurveyCopyMe");
String copyMeResp = copyMeField != null ? (String) answerMap.get(copyMeField) : null;
boolean copyMe = (UtilValidate.isNotEmpty(copyMeField)
&& UtilValidate.isNotEmpty(copyMeResp) && "true".equalsIgnoreCase(copyMeResp)) ? true : false;
int qtyLoop = quantity.intValue();
for (int i = 0; i < qtyLoop; i++) {
// create a gift certificate
Map<String, Object> createGcCtx = new HashMap<String, Object>();
createGcCtx.put("productStoreId", productStoreId);
createGcCtx.put("currency", currency);
createGcCtx.put("partyId", partyId);
createGcCtx.put("initialAmount", amount);
createGcCtx.put("userLogin", userLogin);
Map<String, Object> createGcResult = null;
try {
createGcResult = dispatcher.runSync("createGiftCertificate", createGcCtx);
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCreationError", locale) + e.getMessage());
}
if (ServiceUtil.isError(createGcResult)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCreationError", locale)
+ ServiceUtil.getErrorMessage(createGcResult));
}
// create the fulfillment record
Map<String, Object> gcFulFill = new HashMap<String, Object>();
gcFulFill.put("typeEnumId", "GC_ACTIVATE");
gcFulFill.put("partyId", partyId);
gcFulFill.put("orderId", orderId);
gcFulFill.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
gcFulFill.put("surveyResponseId", surveyResponse.get("surveyResponseId"));
gcFulFill.put("cardNumber", createGcResult.get("cardNumber"));
gcFulFill.put("pinNumber", createGcResult.get("pinNumber"));
gcFulFill.put("amount", createGcResult.get("initialAmount"));
gcFulFill.put("responseCode", createGcResult.get("responseCode"));
gcFulFill.put("referenceNum", createGcResult.get("referenceNum"));
gcFulFill.put("userLogin", userLogin);
try {
dispatcher.runAsync("createGcFulFillmentRecord", gcFulFill, true);
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotStoreFulfillmentInfo",
UtilMisc.toMap("errorString", e.getMessage()), locale));
}
// add some information to the answerMap for the email
answerMap.put("cardNumber", createGcResult.get("cardNumber"));
answerMap.put("pinNumber", createGcResult.get("pinNumber"));
answerMap.put("amount", createGcResult.get("initialAmount"));
// get the email setting for this email type
GenericValue productStoreEmail = null;
String emailType = "PRDS_GC_PURCHASE";
try {
productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", emailType).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get product store email setting for gift card purchase", module);
}
if (productStoreEmail == null) {
Debug.logError("No gift card purchase email setting found for this store; cannot send gift card information", module);
} else {
answerMap.put("locale", locale);
// set the bcc address(s)
String bcc = productStoreEmail.getString("bccAddress");
if (copyMe) {
if (UtilValidate.isNotEmpty(bcc)) {
bcc = bcc + "," + orderEmails;
} else {
bcc = orderEmails;
}
}
Map<String, Object> emailCtx = new HashMap<String, Object>();
String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
if (UtilValidate.isEmpty(bodyScreenLocation)) {
bodyScreenLocation = ProductStoreWorker.getDefaultProductStoreEmailScreenLocation(emailType);
}
emailCtx.put("bodyScreenUri", bodyScreenLocation);
emailCtx.put("bodyParameters", answerMap);
emailCtx.put("sendTo", sendToEmail);
emailCtx.put("contentType", productStoreEmail.get("contentType"));
emailCtx.put("sendFrom", productStoreEmail.get("fromAddress"));
emailCtx.put("sendCc", productStoreEmail.get("ccAddress"));
emailCtx.put("sendBcc", bcc);
emailCtx.put("subject", productStoreEmail.getString("subject"));
emailCtx.put("userLogin", userLogin);
// send off the email async so we will retry on failed attempts
// SC 20060405: Changed to runSync because runAsync kept getting an error:
// Problem serializing service attributes (Cannot serialize object of class java.util.PropertyResourceBundle)
try {
dispatcher.runSync("sendMailFromScreen", emailCtx);
} catch (GenericServiceException e) {
Debug.logError(e, "Problem sending mail", module);
// this is fatal; we will rollback and try again later
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotSendEmailNotice",
UtilMisc.toMap("errorString", e.toString()), locale));
}
}
}
return ServiceUtil.returnSuccess();
}
public static Map<String, Object> giftCertificateReload(DispatchContext dctx, Map<String, ? extends Object> context) {
// this service should always be called via FULFILLMENT_EXTSYNC
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
GenericValue userLogin = (GenericValue) context.get("userLogin");
GenericValue orderItem = (GenericValue) context.get("orderItem");
Locale locale = (Locale) context.get("locale");
// order ID for tracking
String orderId = orderItem.getString("orderId");
// the order header for store info
GenericValue orderHeader = null;
try {
orderHeader = orderItem.getRelatedOne("OrderHeader", false);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get OrderHeader from OrderItem",module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderCannotGetOrderHeader", UtilMisc.toMap("orderId", orderId), locale));
}
// get the order read helper
OrderReadHelper orh = new OrderReadHelper(orderHeader);
// get the currency
String currency = orh.getCurrency();
// make sure we have a currency
if (currency == null) {
currency = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
// get the product store
String productStoreId = null;
if (orderHeader != null) {
productStoreId = orh.getProductStoreId();
}
if (productStoreId == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"AccountingGiftCerticateNumberCannotReload", UtilMisc.toMap("orderId", orderId), locale));
}
// payment config
GenericValue paymentSetting = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, "GIFT_CARD", null, true);
String paymentConfig = null;
if (paymentSetting != null) {
paymentConfig = paymentSetting.getString("paymentPropertiesPath");
}
if (paymentConfig == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"AccountingGiftCerticateNumberCannotGetPaymentConfiguration", locale));
}
// party ID for tracking
GenericValue placingParty = orh.getPlacingParty();
String partyId = null;
if (placingParty != null) {
partyId = placingParty.getString("partyId");
}
// amount of the gift card reload
BigDecimal amount = orderItem.getBigDecimal("unitPrice");
// survey information
String surveyId = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.surveyId", delegator);
// get the survey response
GenericValue surveyResponse = null;
try {
// there should be only one
surveyResponse = EntityQuery.use(delegator).from("SurveyResponse")
.where("orderId", orderId, "orderItemSeqId", orderItem.get("orderItemSeqId"), "surveyId", surveyId)
.orderBy("-responseDate").queryFirst();
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"AccountingGiftCerticateNumberCannotReload", locale));
}
// get the response answers
List<GenericValue> responseAnswers = null;
try {
responseAnswers = surveyResponse.getRelated("SurveyResponseAnswer", null, null, false);
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"AccountingGiftCerticateNumberCannotReloadFromSurveyAnswers", locale));
}
// make a map of answer info
Map<String, Object> answerMap = new HashMap<String, Object>();
if (responseAnswers != null) {
for (GenericValue answer : responseAnswers) {
GenericValue question = null;
try {
question = answer.getRelatedOne("SurveyQuestion", false);
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"AccountingGiftCerticateNumberCannotReloadFromSurveyAnswers", locale));
}
if (question != null) {
String desc = question.getString("description");
String ans = answer.getString("textResponse"); // only support text response types for now
answerMap.put(desc, ans);
}
}
}
String cardNumberKey = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.survey.cardNumber", delegator);
String pinNumberKey = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.giftcert.reload.survey.pinNumber", delegator);
String cardNumber = (String) answerMap.get(cardNumberKey);
String pinNumber = (String) answerMap.get(pinNumberKey);
// reload the gift card
Map<String, Object> reloadCtx = new HashMap<String, Object>();
reloadCtx.put("productStoreId", productStoreId);
reloadCtx.put("currency", currency);
reloadCtx.put("partyId", partyId);
reloadCtx.put("cardNumber", cardNumber);
reloadCtx.put("pinNumber", pinNumber);
reloadCtx.put("amount", amount);
reloadCtx.put("userLogin", userLogin);
String errorMessage = null;
Map<String, Object> reloadGcResult = null;
try {
reloadGcResult = dispatcher.runSync("addFundsToGiftCertificate", reloadCtx);
} catch (GenericServiceException e) {
Debug.logError(e, module);
errorMessage = "Unable to call reload service!";
}
if (ServiceUtil.isError(reloadGcResult)) {
errorMessage = ServiceUtil.getErrorMessage(reloadGcResult);
}
// create the fulfillment record
Map<String, Object> gcFulFill = new HashMap<String, Object>();
gcFulFill.put("typeEnumId", "GC_RELOAD");
gcFulFill.put("userLogin", userLogin);
gcFulFill.put("partyId", partyId);
gcFulFill.put("orderId", orderId);
gcFulFill.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
gcFulFill.put("surveyResponseId", surveyResponse.get("surveyResponseId"));
gcFulFill.put("cardNumber", cardNumber);
gcFulFill.put("pinNumber", pinNumber);
gcFulFill.put("amount", amount);
if (reloadGcResult != null) {
gcFulFill.put("responseCode", reloadGcResult.get("responseCode"));
gcFulFill.put("referenceNum", reloadGcResult.get("referenceNum"));
}
try {
dispatcher.runAsync("createGcFulFillmentRecord", gcFulFill, true);
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotStoreFulfillmentInfo",
UtilMisc.toMap("errorString", e.getMessage()), locale));
}
if (errorMessage != null) {
// there was a problem
Debug.logError("Reload Failed Need to Refund : " + reloadGcResult, module);
// process the return
try {
Map<String, Object> refundCtx = UtilMisc.toMap("orderItem", orderItem,
"partyId", partyId, "userLogin", userLogin);
dispatcher.runAsync("refundGcPurchase", refundCtx, null, true, 300, true);
} catch (GenericServiceException e) {
Debug.logError(e, "ERROR! Unable to call create refund service; this failed reload will NOT be refunded", module);
}
return ServiceUtil.returnError(errorMessage);
}
// add some information to the answerMap for the email
answerMap.put("processResult", reloadGcResult.get("processResult"));
answerMap.put("responseCode", reloadGcResult.get("responseCode"));
answerMap.put("previousAmount", reloadGcResult.get("previousBalance"));
answerMap.put("amount", reloadGcResult.get("amount"));
// get the email setting for this email type
GenericValue productStoreEmail = null;
String emailType = "PRDS_GC_RELOAD";
try {
productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", emailType).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get product store email setting for gift card purchase", module);
}
if (productStoreEmail == null) {
Debug.logError("No gift card purchase email setting found for this store; cannot send gift card information", module);
} else {
answerMap.put("locale", locale);
Map<String, Object> emailCtx = new HashMap<String, Object>();
String bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation");
if (UtilValidate.isEmpty(bodyScreenLocation)) {
bodyScreenLocation = ProductStoreWorker.getDefaultProductStoreEmailScreenLocation(emailType);
}
emailCtx.put("bodyScreenUri", bodyScreenLocation);
emailCtx.put("bodyParameters", answerMap);
emailCtx.put("sendTo", orh.getOrderEmailString());
emailCtx.put("contentType", productStoreEmail.get("contentType"));
emailCtx.put("sendFrom", productStoreEmail.get("fromAddress"));
emailCtx.put("sendCc", productStoreEmail.get("ccAddress"));
emailCtx.put("sendBcc", productStoreEmail.get("bccAddress"));
emailCtx.put("subject", productStoreEmail.getString("subject"));
emailCtx.put("userLogin", userLogin);
// send off the email async so we will retry on failed attempts
try {
dispatcher.runAsync("sendMailFromScreen", emailCtx);
} catch (GenericServiceException e) {
Debug.logError(e, "Problem sending mail", module);
// this is fatal; we will rollback and try again later
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotSendEmailNotice",
UtilMisc.toMap("errorString", e.toString()), locale));
}
}
return ServiceUtil.returnSuccess();
}
// Tracking Service
public static Map<String, Object> createFulfillmentRecord(DispatchContext dctx, Map<String, ? extends Object> context) {
Delegator delegator = dctx.getDelegator();
Locale locale = (Locale) context.get("locale");
// create the fulfillment record
GenericValue gcFulFill = delegator.makeValue("GiftCardFulfillment");
gcFulFill.set("fulfillmentId", delegator.getNextSeqId("GiftCardFulfillment"));
gcFulFill.set("typeEnumId", context.get("typeEnumId"));
gcFulFill.set("merchantId", context.get("merchantId"));
gcFulFill.set("partyId", context.get("partyId"));
gcFulFill.set("orderId", context.get("orderId"));
gcFulFill.set("orderItemSeqId", context.get("orderItemSeqId"));
gcFulFill.set("surveyResponseId", context.get("surveyResponseId"));
gcFulFill.set("cardNumber", context.get("cardNumber"));
gcFulFill.set("pinNumber", context.get("pinNumber"));
gcFulFill.set("amount", context.get("amount"));
gcFulFill.set("responseCode", context.get("responseCode"));
gcFulFill.set("referenceNum", context.get("referenceNum"));
gcFulFill.set("authCode", context.get("authCode"));
gcFulFill.set("fulfillmentDate", UtilDateTime.nowTimestamp());
try {
delegator.create(gcFulFill);
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
"AccountingGiftCerticateNumberCannotStoreFulfillmentInfo",
UtilMisc.toMap("errorString", e.toString()), locale));
}
return ServiceUtil.returnSuccess();
}
// Refund Service
public static Map<String, Object> refundGcPurchase(DispatchContext dctx, Map<String, ? extends Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
GenericValue userLogin = (GenericValue) context.get("userLogin");
GenericValue orderItem = (GenericValue) context.get("orderItem");
String partyId = (String) context.get("partyId");
Locale locale = (Locale) context.get("locale");
// refresh the item object for status changes
try {
orderItem.refresh();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
Map<String, Object> returnableInfo = null;
try {
returnableInfo = dispatcher.runSync("getReturnableQuantity", UtilMisc.toMap("orderItem", orderItem,
"userLogin", userLogin));
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderErrorUnableToGetReturnItemInformation", locale));
}
if (returnableInfo != null) {
BigDecimal returnableQuantity = (BigDecimal) returnableInfo.get("returnableQuantity");
BigDecimal returnablePrice = (BigDecimal) returnableInfo.get("returnablePrice");
Debug.logInfo("Returnable INFO : " + returnableQuantity + " @ " + returnablePrice + " :: " + orderItem, module);
// create the return header
Map<String, Object> returnHeaderInfo = new HashMap<String, Object>();
returnHeaderInfo.put("fromPartyId", partyId);
returnHeaderInfo.put("userLogin", userLogin);
Map<String, Object> returnHeaderResp = null;
try {
returnHeaderResp = dispatcher.runSync("createReturnHeader", returnHeaderInfo);
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderErrorUnableToCreateReturnHeader", locale));
}
if (returnHeaderResp != null) {
String errorMessage = ServiceUtil.getErrorMessage(returnHeaderResp);
if (errorMessage != null) {
return ServiceUtil.returnError(errorMessage);
}
}
String returnId = null;
if (returnHeaderResp != null) {
returnId = (String) returnHeaderResp.get("returnId");
}
if (returnId == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderErrorCreateReturnHeaderWithoutId", locale));
}
// create the return item
Map<String, Object> returnItemInfo = new HashMap<String, Object>();
returnItemInfo.put("returnId", returnId);
returnItemInfo.put("returnReasonId", "RTN_DIG_FILL_FAIL");
returnItemInfo.put("returnTypeId", "RTN_REFUND");
returnItemInfo.put("returnItemType", "ITEM");
returnItemInfo.put("description", orderItem.get("itemDescription"));
returnItemInfo.put("orderId", orderItem.get("orderId"));
returnItemInfo.put("orderItemSeqId", orderItem.get("orderItemSeqId"));
returnItemInfo.put("returnQuantity", returnableQuantity);
returnItemInfo.put("returnPrice", returnablePrice);
returnItemInfo.put("userLogin", userLogin);
Map<String, Object> returnItemResp = null;
try {
returnItemResp = dispatcher.runSync("createReturnItem", returnItemInfo);
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderErrorUnableToCreateReturnItem", locale));
}
if (returnItemResp != null) {
String errorMessage = ServiceUtil.getErrorMessage(returnItemResp);
if (errorMessage != null) {
return ServiceUtil.returnError(errorMessage);
}
}
String returnItemSeqId = null;
if (returnItemResp != null) {
returnItemSeqId = (String) returnItemResp.get("returnItemSeqId");
}
if (returnItemSeqId == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderErrorCreateReturnItemWithoutId", locale));
} else {
Debug.logVerbose("Created return item : " + returnId + " / " + returnItemSeqId, module);
}
// need the system userLogin to "fake" out the update service
GenericValue admin = null;
try {
admin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderErrorUnableToUpdateReturnHeaderStatusWithoutUserLogin", locale));
}
// update the status to received so it can process
Map<String, Object> updateReturnInfo = new HashMap<String, Object>();
updateReturnInfo.put("returnId", returnId);
updateReturnInfo.put("statusId", "RETURN_RECEIVED");
updateReturnInfo.put("currentStatusId", "RETURN_REQUESTED");
updateReturnInfo.put("userLogin", admin);
Map<String, Object> updateReturnResp = null;
try {
updateReturnResp = dispatcher.runSync("updateReturnHeader", updateReturnInfo);
} catch (GenericServiceException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrderError,
"OrderErrorUnableToUpdateReturnHeaderStatus", locale));
}
if (updateReturnResp != null) {
String errorMessage = ServiceUtil.getErrorMessage(updateReturnResp);
if (errorMessage != null) {
return ServiceUtil.returnError(errorMessage);
}
}
}
return ServiceUtil.returnSuccess();
}
// Private worker methods
private static boolean validatePin(Delegator delegator, String cardNumber, String pinNumber) {
GenericValue finAccount = null;
try {
finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", cardNumber).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
if (finAccount != null) {
String dbPin = finAccount.getString("finAccountCode");
Debug.logInfo("GC Pin Validation: [Sent: " + pinNumber + "] [Actual: " + dbPin + "]", module);
if (dbPin != null && dbPin.equals(pinNumber)) {
return true;
}
} else {
Debug.logInfo("GC FinAccount record not found (" + cardNumber + ")", module);
}
return false;
}
private static String createTransaction(Delegator delegator, LocalDispatcher dispatcher, GenericValue userLogin,
BigDecimal amount, String productStoreId, String partyId, String currencyUom, String txType,
String finAccountId, Locale locale) throws GeneralException {
final String coParty = getPayToPartyId(delegator, productStoreId);
final String paymentMethodType = "GIFT_CERTIFICATE";
if (UtilValidate.isEmpty(partyId)) {
partyId = "_NA_";
}
String paymentType = null;
String partyIdFrom = null;
String partyIdTo = null;
if ("DEPOSIT".equals(txType)) {
paymentType = "GC_DEPOSIT";
partyIdFrom = partyId;
partyIdTo = coParty;
} else if ("WITHDRAWAL".equals(txType)) {
paymentType = "GC_WITHDRAWAL";
partyIdFrom = coParty;
partyIdTo = partyId;
} else {
throw new GeneralException(UtilProperties.getMessage(resourceError,
"AccountingFinAccountCannotCreateTransaction", locale));
}
// create the payment for the transaction
Map<String, Object> paymentCtx = UtilMisc.<String, Object>toMap("paymentTypeId", paymentType);
paymentCtx.put("paymentMethodTypeId", paymentMethodType);
paymentCtx.put("partyIdTo", partyIdTo);
paymentCtx.put("partyIdFrom", partyIdFrom);
paymentCtx.put("statusId", "PMNT_RECEIVED");
paymentCtx.put("currencyUomId", currencyUom);
paymentCtx.put("amount", amount);
paymentCtx.put("userLogin", userLogin);
paymentCtx.put("paymentRefNum", "N/A");
String paymentId = null;
Map<String, Object> payResult = null;
try {
payResult = dispatcher.runSync("createPayment", paymentCtx);
} catch (GenericServiceException e) {
throw new GeneralException(e);
}
if (payResult == null) {
throw new GeneralException("Unknow error in creating financial account transaction!");
}
if (ServiceUtil.isError(payResult)) {
throw new GeneralException(ServiceUtil.getErrorMessage(payResult));
} else {
paymentId = (String) payResult.get("paymentId");
}
// create the initial transaction
Map<String, Object> transCtx = UtilMisc.<String, Object>toMap("finAccountTransTypeId", txType);
transCtx.put("finAccountId", finAccountId);
transCtx.put("partyId", userLogin.getString("partyId"));
transCtx.put("userLogin", userLogin);
transCtx.put("paymentId", paymentId);
transCtx.put("amount", amount);
Map<String, Object> transResult = null;
String txId = null;
try {
transResult = dispatcher.runSync("createFinAccountTrans", transCtx);
} catch (GenericServiceException e) {
throw new GeneralException(e);
}
if (transResult == null) {
throw new GeneralException("Unknown error in creating financial account transaction!");
}
if (ServiceUtil.isError(transResult)) {
throw new GeneralException(ServiceUtil.getErrorMessage(transResult));
} else {
txId = (String) transResult.get("finAccountTransId");
}
return txId;
}
private static String generateNumber(Delegator delegator, int length, boolean isId) throws GenericEntityException {
if (length > 19) {
length = 19;
}
Random rand = new SecureRandom();
boolean isValid = false;
StringBuilder number = null;
while (!isValid) {
number = new StringBuilder("");
for (int i = 0; i < length; i++) {
int randInt = rand.nextInt(9);
number.append(randInt);
}
if (isId) {
number.append(UtilValidate.getLuhnCheckDigit(number.toString()));
// validate the number
if (checkCardNumber(number.toString())) {
// make sure this number doens't already exist
isValid = checkNumberInDatabase(delegator, number.toString());
}
} else {
isValid = true;
}
}
return number.toString();
}
private static boolean checkNumberInDatabase(Delegator delegator, String number) throws GenericEntityException {
GenericValue finAccount = EntityQuery.use(delegator).from("FinAccount").where("finAccountId", number).queryOne();
if (finAccount == null) {
return true;
}
return false;
}
private static boolean checkCardNumber(String number) {
number = number.replaceAll("\\D", "");
return UtilValidate.sumIsMod10(UtilValidate.getLuhnSum(number));
}
private static String getPayToPartyId(Delegator delegator, String productStoreId) {
String payToPartyId = "Company"; // default value
GenericValue productStore = null;
try {
productStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to locate ProductStore (" + productStoreId + ")", module);
return null;
}
if (productStore != null && productStore.get("payToPartyId") != null) {
payToPartyId = productStore.getString("payToPartyId");
}
return payToPartyId;
}
}