You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ja...@apache.org on 2007/03/27 06:47:02 UTC

svn commit: r522749 - /ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java

Author: jaz
Date: Mon Mar 26 21:47:01 2007
New Revision: 522749

URL: http://svn.apache.org/viewvc?view=rev&rev=522749
Log:
partially working payment services for financial accounts; implements payment processor interfaces and generic deposit/withdraw services 

Added:
    ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java   (with props)

Added: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java?view=auto&rev=522749
==============================================================================
--- ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java (added)
+++ ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java Mon Mar 26 21:47:01 2007
@@ -0,0 +1,787 @@
+/*
+ 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.ofbiz.accounting.finaccount;
+
+import org.ofbiz.service.DispatchContext;
+import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceUtil;
+import org.ofbiz.service.GenericServiceException;
+import org.ofbiz.entity.GenericDelegator;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.util.EntityUtil;
+import org.ofbiz.base.util.*;
+import org.ofbiz.order.order.OrderReadHelper;
+import org.ofbiz.order.finaccount.FinAccountHelper;
+import org.ofbiz.accounting.payment.PaymentGatewayServices;
+import org.ofbiz.product.store.ProductStoreWorker;
+
+import java.util.Map;
+import java.util.List;
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+
+import javolution.util.FastMap;
+
+/**
+ * FinAccountPaymentServices - Financial account used as payment method
+ */
+public class FinAccountPaymentServices {
+
+    public static final String module = FinAccountPaymentServices.class.getName();
+
+    // base payment intergration services
+    public static Map finAccountPreAuth(DispatchContext dctx, Map context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        GenericDelegator delegator = dctx.getDelegator();
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+
+        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
+        String finAccountCode = (String) context.get("finAccountCode");
+        String finAccountPin = (String) context.get("finAccountPin");
+        String finAccountId = (String) context.get("finAccountId");
+
+        String currency = (String) context.get("currency");
+        String orderId = (String) context.get("orderId");
+        Double amount = (Double) context.get("processAmount");
+
+        // make sure we have a currency
+        if (currency == null) {
+            currency = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
+        }
+
+        // check for an existing auth trans and cancel it
+        GenericValue authTrans = PaymentGatewayServices.getAuthTransaction(paymentPref);
+        if (authTrans != null) {
+            Map input = UtilMisc.toMap("userLogin", userLogin, "finAccountAuthId", authTrans.get("referenceNum"));
+            try {
+                dispatcher.runSync("expireFinAccountAuth", input);
+            } catch (GenericServiceException e) {
+                Debug.logError(e, module);
+                return ServiceUtil.returnError(e.getMessage());
+            }
+        }
+
+        // obtain the order information
+        OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
+        String productStoreId = orh.getProductStoreId();
+
+        // get the financial account
+        GenericValue finAccount;
+        if (finAccountId != null) {
+            try {
+                finAccount = delegator.findByPrimaryKey("FinAccount", UtilMisc.toMap("finAccountId", finAccountId));
+            } catch (GenericEntityException e) {
+                Debug.logError(e, module);
+                return ServiceUtil.returnError(e.getMessage());
+            }
+        } else {
+            if (finAccountCode != null) {
+                try {
+                    finAccount = FinAccountHelper.getFinAccountFromCode(finAccountCode, delegator);
+                } catch (GenericEntityException e) {
+                    Debug.logError(e, module);
+                    return ServiceUtil.returnError("Unable to locate financial account from account code");
+                }
+            } else {
+                return ServiceUtil.returnError("Both finAccountId and finAccountCode cannot be null; at least one is required");
+            }
+        }
+        if (finAccount == null) {
+            return ServiceUtil.returnError("Invalid financial account; cannot locate account");
+        }
+
+        String finAccountTypeId = finAccount.getString("finAccountTypeId");
+        finAccountId = finAccount.getString("finAccountId");
+
+        try {
+            // fin the store requires a pin number; validate the PIN with the code
+            GenericValue finAccountSettings = delegator.findByPrimaryKeyCache("ProductStoreFinActSetting",
+                    UtilMisc.toMap("productStoreId", productStoreId, "finAccountTypeId", finAccountTypeId));
+            String allowAuthToNegative = "N";
+
+            if (finAccountSettings != null) {
+                allowAuthToNegative = finAccountSettings.getString("allowAuthToNegative");
+
+                // validate the PIN if the store requires it
+                if ("Y".equals(finAccountSettings.getString("requirePinCode"))) {
+                    if (!FinAccountHelper.validatePin(delegator, finAccountCode, finAccountPin)) {
+                        return ServiceUtil.returnError("Financial account PIN/CODE combination not found");
+                    }
+                }
+            }
+           
+            // check for account being frozen
+            String isFrozen = finAccount.getString("isFrozen");
+            if (isFrozen != null && "Y".equals(isFrozen)) {
+                return ServiceUtil.returnError("Financial account is currently frozen");    
+            }
+
+            // check for expiration date
+            if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
+                return ServiceUtil.returnError("Financial account has expired as of " + finAccount.getTimestamp("thruDate"));
+            }
+
+            // check the amount to authorize against the available balance of fin account, which includes active authorizations as well as transactions
+            BigDecimal availableBalance = FinAccountHelper.getAvailableBalance(finAccountId, currency, delegator);
+            Map result = ServiceUtil.returnSuccess();
+            Boolean processResult;
+            String refNum;
+
+            // turn amount into a big decimal, making sure to round and scale it to the same as availableBalance
+            BigDecimal amountBd = (new BigDecimal(amount.doubleValue())).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding);
+
+            Debug.log("Allow auth to negative: " + allowAuthToNegative + " :: available: " + availableBalance + " comp: " + FinAccountHelper.ZERO + " = " + availableBalance.compareTo(FinAccountHelper.ZERO) + " :: req: " + amountBd, module);
+            // check the available balance to see if we can auth this tx
+            if (("Y".equals(allowAuthToNegative) && availableBalance.compareTo(FinAccountHelper.ZERO) > -1)
+                    || (availableBalance.compareTo(amountBd) > -1)) {
+                Timestamp thruDate;
+                
+                if (finAccountSettings != null && finAccountSettings.getLong("authValidDays") != null) {
+                    thruDate = UtilDateTime.getDayEnd(UtilDateTime.nowTimestamp(), finAccountSettings.getLong("authValidDays").intValue());
+                } else {
+                    thruDate = UtilDateTime.getDayEnd(UtilDateTime.nowTimestamp(), 30); // default 30 days for an auth
+                }
+
+                Map tmpResult = dispatcher.runSync("createFinAccountAuth", UtilMisc.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;
+                }
+
+                // mark the account as frozen if we have gone negative
+                BigDecimal newBalance = FinAccountHelper.getAvailableBalance(finAccountId, currency, delegator);
+                if (newBalance.compareTo(FinAccountHelper.ZERO) == -1) {
+                    finAccount.set("isFrozen", "Y");
+                    try {
+                        finAccount.store();
+                    } catch (GenericEntityException e) {
+                        Debug.logError(e, module);
+                        return ServiceUtil.returnError(e.getMessage());
+                    }
+                }
+
+            } else {
+                Debug.logError("Attempted to authorize [" + amount + "] against a balance of only [" + availableBalance + "]", module);
+                refNum = "0"; // 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", "1");
+            result.put("authCode", "A");            
+            result.put("authRefNum", refNum);
+
+            return result;
+        } catch (GenericEntityException ex) {
+            Debug.logError(ex, "Cannot authorize financial account", module);
+            return ServiceUtil.returnError("Cannot authorize financial account due to " + ex.getMessage());
+        } catch (GenericServiceException ex) {
+            Debug.logError(ex, "Cannot authorize gift certificate", module);
+            return ServiceUtil.returnError("Cannot authorize financial account due to " + ex.getMessage());
+        }
+    }
+
+    public static Map finAccountReleaseAuth(DispatchContext dctx, Map context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+
+        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
+
+        String err = "Unable to expire financial account authorization: ";
+        try {
+
+            // expire the related financial authorization transaction
+            GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(paymentPref);
+            if (authTransaction == null) {
+                return ServiceUtil.returnError(err + " Could not find authorization transaction.");
+            }
+            
+            Map input = UtilMisc.toMap("userLogin", userLogin, "finAccountAuthId", authTransaction.get("referenceNum"));
+            Map serviceResults = dispatcher.runSync("expireFinAccountAuth", input);
+
+            Map result = ServiceUtil.returnSuccess();
+            result.put("releaseRefNum", authTransaction.getString("referenceNum"));
+            result.put("releaseAmount", authTransaction.getDouble("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());
+        }
+    }
+
+    public static Map finAccountCapture(DispatchContext dctx, Map context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        GenericDelegator delegator = dctx.getDelegator();
+
+        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        GenericValue authTrans = (GenericValue) context.get("authTrans");
+        Double amount = (Double) context.get("captureAmount");
+        String currency = (String) context.get("currency");
+
+        // get the authorization transaction
+        if (authTrans == null){
+            authTrans = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
+        }
+        if (authTrans == null) {
+            return ServiceUtil.returnError("No authorization transaction found for the OrderPaymentPreference; cannot capture");
+        }
+
+        // get the auth record
+        String finAccountAuthId = authTrans.getString("referenceNum");
+        GenericValue finAccountAuth;
+        try {
+            finAccountAuth = delegator.findByPrimaryKey("FinAccountAuth", UtilMisc.toMap("finAccountAuthId", finAccountAuthId));
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // get the financial account
+        GenericValue finAccount;
+        try {
+            finAccount = finAccountAuth.getRelatedOne("FinAccount");
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // make sure authorization has not expired
+        Timestamp authExpiration = finAccountAuth.getTimestamp("thruDate");
+        if ((authExpiration != null) && (authExpiration.before(UtilDateTime.nowTimestamp()))) {
+            return ServiceUtil.returnError("Authorization transaction [" + authTrans.getString("paymentGatewayResponseId") + "] has expired as of " + authExpiration);
+        }
+
+        // make sure the fin account itself has not expired
+        if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
+            return ServiceUtil.returnError("Financial account has expired as of " + finAccount.getTimestamp("thruDate"));
+        }
+        String finAccountId = finAccount.getString("finAccountId");
+
+        // need the product store ID & party ID
+        String orderId = orderPaymentPreference.getString("orderId");
+        String productStoreId = null;
+        String partyId = null;
+        if (orderId != null) {
+            OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
+            productStoreId = orh.getProductStoreId();
+
+            GenericValue billToParty = orh.getBillToParty();
+            if (billToParty != null) {
+                partyId = billToParty.getString("partyId");
+            }
+        }
+
+        // build the withdraw context
+        Map withdrawCtx = FastMap.newInstance();
+        withdrawCtx.put("finAccountId", finAccountId);
+        withdrawCtx.put("productStoreId", productStoreId);
+        withdrawCtx.put("currency", currency);
+        withdrawCtx.put("partyId", partyId);
+        withdrawCtx.put("amount", amount);
+        withdrawCtx.put("userLogin", userLogin);
+
+        // call the withdraw service
+        Map withdrawResp;
+        try {
+            withdrawResp = dispatcher.runSync("finAccountWithdraw", withdrawCtx);
+        } catch (GenericServiceException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        if (ServiceUtil.isError(withdrawResp)) {
+            return withdrawResp;
+        }
+
+        // cancel the authorization
+        Map releaseResult;
+        try {
+            releaseResult = dispatcher.runSync("expireFinAccountAuth", UtilMisc.toMap("userLogin", userLogin, "finAccountAuthId", finAccountAuthId));
+        } catch (GenericServiceException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        if (ServiceUtil.isError(releaseResult)) {
+            return releaseResult;
+        }
+
+        // create the capture response
+        Map result = ServiceUtil.returnSuccess();
+        Boolean processResult = (Boolean) withdrawResp.get("processResult");
+        Double withdrawAmount = (Double) withdrawResp.get("amount");
+        String referenceNum = (String) withdrawResp.get("referenceNum");
+        result.put("captureResult", processResult);
+        result.put("captureRefNum", referenceNum);
+        result.put("captureCode", "C");
+        result.put("captureFlag", "1");
+        result.put("captureAmount", withdrawAmount);
+
+        return result;
+    }
+
+    public static Map finAccountRefund(DispatchContext dctx, Map context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        GenericDelegator delegator = dctx.getDelegator();
+
+        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        Double amount = (Double) context.get("refundAmount");
+        String currency = (String) context.get("currency");
+        String finAccountId = (String) context.get("finAccountId");
+
+        String productStoreId = null;
+        String partyId = null;
+
+        if (orderPaymentPreference != null) {
+            String orderId = orderPaymentPreference.getString("orderId");
+            if (orderId != null) {
+                OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
+                productStoreId = orh.getProductStoreId();
+
+                GenericValue billToParty = orh.getBillToParty();
+                if (billToParty != null) {
+                    partyId = billToParty.getString("partyId");
+                }
+            }
+        }
+
+        // call the deposit service
+        Map depositCtx = FastMap.newInstance();
+        depositCtx.put("finAccountId", finAccountId);
+        depositCtx.put("productStoreId", productStoreId);
+        depositCtx.put("isRefund", Boolean.TRUE);
+        depositCtx.put("currency", currency);
+        depositCtx.put("partyId", partyId);
+        depositCtx.put("amount", amount);
+        depositCtx.put("userLogin", userLogin);
+
+        Map depositResp;
+        try {
+            depositResp = dispatcher.runSync("finAccountDeposit", depositCtx);
+        } catch (GenericServiceException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        if (ServiceUtil.isError(depositResp)) {
+            return depositResp;
+        }
+
+        // create the refund response
+        Map result = ServiceUtil.returnSuccess();
+        Boolean processResult = (Boolean) depositResp.get("processResult");
+        Double depositAmount = (Double) depositResp.get("amount");
+        String referenceNum = (String) depositResp.get("referenceNum");
+        result.put("refundResult", processResult);
+        result.put("refundRefNum", referenceNum);
+        result.put("refundCode", "R");
+        result.put("refundFlag", "1");
+        result.put("refundAmount", depositAmount);
+
+        return result;
+    }
+
+    // base account transaction services
+    public static Map finAccountWithdraw(DispatchContext dctx, Map context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        GenericDelegator delegator = dctx.getDelegator();
+
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String productStoreId = (String) context.get("productStoreId");
+        String finAccountId = (String) context.get("finAccountId");
+        Double amount = (Double) context.get("amount");
+
+        final String WITHDRAWAL = "WITHDRAWAL";
+
+        String partyId = (String) context.get("partyId");
+        if (UtilValidate.isEmpty(partyId)) {
+            partyId = "_NA_";
+        }
+        String currencyUom = (String) context.get("currency");
+        if (UtilValidate.isEmpty(currencyUom)) {
+            currencyUom = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
+        }
+
+        // validate the amount
+        if (amount.doubleValue() < 0.00) {
+            return ServiceUtil.returnError("Amount should be a positive number.");
+        }
+
+        GenericValue finAccount;
+        try {
+            finAccount = delegator.findByPrimaryKey("FinAccount", UtilMisc.toMap("finAccountId", finAccountId));
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // verify we have a financial account
+        if (finAccount == null) {
+            return ServiceUtil.returnError("Unable to find Financial account for this transaction");
+        }
+
+        // make sure the fin account itself has not expired
+        if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
+            return ServiceUtil.returnError("Financial account has expired as of " + finAccount.getTimestamp("thruDate"));
+        }
+
+        // check the actual balance (excluding authorized amounts) and create the transaction if it is sufficient
+        BigDecimal previousBalance;
+        try {
+            previousBalance = FinAccountHelper.getBalance(finAccountId, currencyUom, delegator);
+        } catch (GeneralException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        BigDecimal balance;
+        String refNum;
+        Boolean procResult;
+        if (previousBalance.doubleValue() >= amount.doubleValue()) {
+            try {
+                refNum = FinAccountPaymentServices.createFinAcctPaymentTransaction(delegator, dispatcher, userLogin, amount,
+                        productStoreId, partyId, currencyUom, WITHDRAWAL, finAccountId);
+                balance = FinAccountHelper.getAvailableBalance(finAccountId, currencyUom, delegator);
+                        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 result = ServiceUtil.returnSuccess();
+        result.put("previousBalance", new Double(previousBalance.doubleValue()));
+        result.put("balance", new Double(balance.doubleValue()));
+        result.put("amount", amount);
+        result.put("processResult", procResult);
+        result.put("referenceNum", refNum);
+        return result;
+    }
+
+    // base deposit service
+    public static Map finAccountDeposit(DispatchContext dctx, Map context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        GenericDelegator delegator = dctx.getDelegator();
+
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String productStoreId = (String) context.get("productStoreId");
+        String finAccountId = (String) context.get("finAccountId");        
+        Boolean isRefund = (Boolean) context.get("isRefund");
+        Double amount = (Double) context.get("amount");
+
+        final String DEPOSIT = isRefund == null || !isRefund.booleanValue() ? "DEPOSIT" : "ADJUSTMENT";
+
+        String partyId = (String) context.get("partyId");
+        if (UtilValidate.isEmpty(partyId)) {
+            partyId = "_NA_";
+        }
+        String currencyUom = (String) context.get("currency");
+        if (UtilValidate.isEmpty(currencyUom)) {
+            currencyUom = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
+        }
+
+        GenericValue finAccount;
+        try {
+            finAccount = delegator.findByPrimaryKey("FinAccount", UtilMisc.toMap("finAccountId", finAccountId));
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // verify we have a financial account
+        if (finAccount == null) {
+            return ServiceUtil.returnError("Unable to find Financial account for this transaction");
+        }
+
+        // make sure the fin account itself has not expired
+        if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) {
+            return ServiceUtil.returnError("Financial account has expired as of " + finAccount.getTimestamp("thruDate"));
+        }
+        Debug.log("Deposit into financial account #" + finAccountId + " [" + amount + "]", module);
+        
+        // get the previous balance
+        BigDecimal previousBalance;
+        try {
+            previousBalance = FinAccountHelper.getAvailableBalance(finAccountId, currencyUom, delegator);
+        } catch (GeneralException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // create the transaction
+        BigDecimal balance;
+        String refNum;
+        try {
+            refNum = FinAccountPaymentServices.createFinAcctPaymentTransaction(delegator, dispatcher, userLogin, amount,
+                    productStoreId, partyId, currencyUom, DEPOSIT, finAccountId);
+            balance = FinAccountHelper.getAvailableBalance(finAccountId, currencyUom, delegator);
+        } catch (GeneralException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        Map result = ServiceUtil.returnSuccess();
+        result.put("previousBalance", new Double(previousBalance.doubleValue()));
+        result.put("balance", new Double(balance.doubleValue()));
+        result.put("amount", amount);
+        result.put("processResult", Boolean.TRUE);
+        result.put("referenceNum", refNum);        
+        return result;
+    }
+
+    // auto-replenish service (deposit)
+    public static Map finAccountReplenish(DispatchContext dctx, Map context) {
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        GenericDelegator delegator = dctx.getDelegator();
+
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String productStoreId = (String) context.get("productStoreId");
+        String finAccountId = (String) context.get("finAccountId");
+
+        // lookup the FinAccount
+        GenericValue finAccount;
+        try {
+            finAccount = delegator.findByPrimaryKey("FinAccount", UtilMisc.toMap("finAccountId", finAccountId));
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        if (finAccount == null) {
+            return ServiceUtil.returnError("Invalid financial account [" + finAccountId + "]");
+        }
+        String currency = finAccount.getString("currencyUomId");
+
+        // look up the type -- determine auto-replenish is active
+        GenericValue finAccountType;
+        try {
+            finAccountType = finAccount.getRelatedOne("FinAccountType");
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        String replenishEnumId = finAccountType.getString("replenishEnumId");
+        if (!"FARP_AUTOMATIC".equals(replenishEnumId)) {
+            // type does not support auto-replenish
+            return ServiceUtil.returnSuccess();
+        }
+
+        BigDecimal replenishLevel = finAccount.getBigDecimal("replenishLevel");
+        if (replenishLevel == null) {
+            // no replenish level set; this account goes not support auto-replenish
+            return ServiceUtil.returnSuccess();
+        }
+
+        // get the current balance
+        BigDecimal balance;
+        try {
+             balance = FinAccountHelper.getBalance(finAccountId, currency, delegator);
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // the deposit is level - balance (500 - (-10) = 510 || 500 - (10) = 490)
+        BigDecimal depositAmount = replenishLevel.subtract(balance);
+
+        // find the owner party
+        List finAcctOwners;
+        try {
+            finAcctOwners = delegator.findByAnd("FinAccountRole", UtilMisc.toMap("finAccountId", finAccountId, "roleTypeId", "OWNER"), UtilMisc.toList("-fromDate"));
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        finAcctOwners = EntityUtil.filterByDate(finAcctOwners);
+        GenericValue finAccountOwner = EntityUtil.getFirst(finAcctOwners);
+        if (finAccountOwner == null) {
+            // no owner cannot replenish; (not fatal, just not supported by this account)
+            Debug.logWarning("No owner attached to financial account [" + finAccountId + "] cannot auto-replenish", module);
+            return ServiceUtil.returnSuccess();
+        }
+        String partyId = finAccountOwner.getString("partyId");
+
+        // determine the payment method to use to replenish
+        List paymentMethods;
+        try {
+            paymentMethods = delegator.findByAnd("PaymentMethod", UtilMisc.toMap("partyId", partyId), UtilMisc.toList("-fromDate"));
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        paymentMethods = EntityUtil.filterByDate(paymentMethods);
+        GenericValue paymentMethod = EntityUtil.getFirst(paymentMethods);
+        if (paymentMethod == null) {
+            // no payment methods on file; cannot replenish
+            Debug.logWarning("No payment methods attached to party [" + partyId + "] cannot auto-replenish", module);
+            return ServiceUtil.returnSuccess();
+        }
+
+        // clear out the frozen flag
+        finAccount.set("isFrozen", "N");
+        try {
+            finAccount.store();
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
+        // hit the payment method for the amount to replenish
+        Map orderItemMap = UtilMisc.toMap("Auto-Replenishment", new Double(depositAmount.doubleValue()));
+        Map replOrderCtx = FastMap.newInstance();
+        replOrderCtx.put("productStoreId", productStoreId);
+        replOrderCtx.put("paymentMethodId", paymentMethod.getString("paymentMethodId"));
+        replOrderCtx.put("currency", currency);
+        replOrderCtx.put("partyId", partyId);
+        replOrderCtx.put("itemMap", orderItemMap);
+        replOrderCtx.put("userLogin", userLogin);
+        Map replResp;
+        try {
+            replResp = dispatcher.runSync("createSimpleNonProductSalesOrder", replOrderCtx);
+        } catch (GenericServiceException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        if (ServiceUtil.isError(replResp)) {
+            return replResp;
+        }
+
+        // create the deposit
+        Map depositCtx = FastMap.newInstance();
+        depositCtx.put("productStoreId", productStoreId);
+        depositCtx.put("finAccountId", finAccountId);
+        depositCtx.put("currency", currency);
+        depositCtx.put("partyId", partyId);
+        depositCtx.put("amount",  new Double(depositAmount.doubleValue()));
+        depositCtx.put("userLogin", userLogin);
+        Map depositResp;
+        try {
+            depositResp = dispatcher.runSync("finAccountDeposit", depositCtx);
+        } catch (GenericServiceException e) {
+            Debug.logError(e, module);
+            return ServiceUtil.returnError(e.getMessage());
+        }
+        if (ServiceUtil.isError(depositResp)) {
+            return depositResp;
+        }
+
+        return ServiceUtil.returnSuccess();
+    }
+    
+    private static String createFinAcctPaymentTransaction(GenericDelegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, Double amount,
+            String productStoreId, String partyId, String currencyUom, String txType, String finAccountId) throws GeneralException {
+
+        final String coParty = ProductStoreWorker.getProductStorePayToPartyId(productStoreId, delegator);
+        final String paymentMethodType = "FIN_ACCOUNT";
+
+        if (UtilValidate.isEmpty(partyId)) {
+            partyId = "_NA_";
+        }
+
+        String paymentType;
+        String partyIdFrom;
+        String partyIdTo;
+
+        // determine the payment type and which direction the parties should go
+        if ("DEPOSIT".equals(txType)) {
+            paymentType = "RECEIPT";
+            partyIdFrom = partyId;
+            partyIdTo = coParty;
+        } else if ("WITHDRAWAL".equals(txType)) {
+            paymentType = "DISBURSEMENT";
+            partyIdFrom = coParty;
+            partyIdTo = partyId;
+        } else if ("ADJUSTMENT".equals(txType)) {
+            paymentType = "CUSTOMER_REFUND";
+            partyIdFrom = coParty;
+            partyIdTo = partyId;
+        } else {
+            throw new GeneralException("Unable to create financial account transaction!");
+        }
+
+        // create the payment for the transaction
+        Map paymentCtx = UtilMisc.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", Long.toString(UtilDateTime.nowTimestamp().getTime()));
+
+        String paymentId;
+        Map payResult;
+        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 transCtx = UtilMisc.toMap("finAccountTransTypeId", txType);
+        transCtx.put("finAccountId", finAccountId);
+        transCtx.put("partyId", userLogin.getString("partyId"));
+        transCtx.put("userLogin", userLogin);        
+        transCtx.put("paymentId", paymentId);
+
+        Map transResult;
+        String txId;
+        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;
+    }
+}

Propchange: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java
------------------------------------------------------------------------------
    svn:keywords = "Date Rev Author URL Id"

Propchange: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/finaccount/FinAccountPaymentServices.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain