⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utilcogs.java

📁 Sequoia ERP是一个真正的企业级开源ERP解决方案。它提供的模块包括:电子商务应用(e-commerce), POS系统(point of sales),知识管理,存货与仓库管理
💻 JAVA
字号:
/* * Copyright (C) 2006  Open Source Strategies, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */package com.opensourcestrategies.financials.util;import java.util.*;import java.sql.Timestamp;import java.math.BigDecimal;import javolution.util.FastMap;import org.ofbiz.accounting.AccountingException;import org.ofbiz.base.util.*;import org.ofbiz.entity.*;import org.ofbiz.entity.condition.*;import org.ofbiz.entity.util.*;import org.ofbiz.service.*;import com.opensourcestrategies.financials.util.UtilFinancial;/** * UtilCOGS - Utilities for Cost of Goods Sold services and calculations * * @author     <a href="mailto:leon@opensourcestrategies.com">Leon Torres</a>  * @version    $Rev: 81 $ * @since      2.2 */public class UtilCOGS {        public static String module = UtilCOGS.class.getName();    public static int decimals = UtilNumber.getBigDecimalScale("fin_arithmetic.properties", "financial.statements.decimals");    public static int rounding = UtilNumber.getBigDecimalRoundingMode("fin_arithmetic.properties", "financial.statements.rounding");    public static final BigDecimal ZERO = new BigDecimal("0");        /**     * Attempts to find the average cost of a given product.  First it will look in ProductAverageCost.       * Then it will call calculateProductCosts to find the average cost of the product in CostComponent.       * If neither method works, then a null will be returned, signaling that no product average cost was      * found and some other technique should be used, or an error should be raised.     */    public static BigDecimal getProductAverageCost(String productId, String organizationPartyId, GenericValue userLogin, GenericDelegator delegator, LocalDispatcher dispatcher) {        BigDecimal cost = null;        try {            // first try using the first unexpired ProductAverageCost.averageCost as the cost            EntityConditionList conditions = new EntityConditionList(UtilMisc.toList(                        EntityUtil.getFilterByDateExpr(),                        new EntityExpr("productId", EntityOperator.EQUALS, productId),                        new EntityExpr("organizationPartyId", EntityOperator.EQUALS, organizationPartyId)                        ), EntityOperator.AND);            GenericValue entry = EntityUtil.getFirst( delegator.findByCondition("ProductAverageCost", conditions, UtilMisc.toList("averageCost"), null) );            if (entry != null) {                cost = entry.getBigDecimal("averageCost");            }            // if we found a non-zero cost via ProductAverageCost, then we're done            if ((cost != null) && (cost.signum() != 0)) return cost;            // otherwise we have to look up the standard costs (the CostComponents with prefix EST_STD_)            GenericValue acctgPref = delegator.findByPrimaryKeyCache("PartyAcctgPreference", UtilMisc.toMap("partyId", organizationPartyId));            Map results = dispatcher.runSync("calculateProductCosts", UtilMisc.toMap("productId", productId, "currencyUomId", acctgPref.get("baseCurrencyUomId"), "costComponentTypePrefix", "EST_STD", "userLogin", userLogin));            if (!ServiceUtil.isError(results)) {                Double totalCost = (Double) results.get("totalCost");                if ((totalCost != null) && (totalCost.doubleValue() != 0.0)) {                    cost = new BigDecimal(totalCost.doubleValue());                }            }            // if we found a non-zero cost via calculateProductCosts, then we're done            if ((cost != null) && (cost.signum() != 0)) return cost;        } catch (GenericEntityException e) {            Debug.logError("Failed to get product average cost for productId [" + productId + "] and organization [" + organizationPartyId + "] due to entity error.", module);        } catch (GenericServiceException e) {            Debug.logError("Failed to get product average cost for productId [" + productId + "] and organization [" + organizationPartyId + "] due to service error.", module);        }        // if we get here, it's because no non-zero cost was found, so return null        return null;    }    /**     * Gets the value of a product in the inventory of an organization.     * The value is the sum of posted debits minus the sum of posted credits     * in the INVENTORY_ACCOUNT or INV_ADJ_AVG_COST GL accounts for this product.     *     * @param   productId               The product to get the value of     * @param   organizationPartyId     Organization of the transactions, which is required.     * @param   transactionDate         An optional timestamp. If specified, the sum will be taken up to this date, inclusive.     * @return  BigDecimal value of the product     */    public static BigDecimal getInventoryValueForProduct(String productId, String organizationPartyId, Timestamp transactionDate, GenericDelegator delegator)        throws GenericEntityException {        Map results = getNetInventoryValueHelper(productId, organizationPartyId, transactionDate, delegator);        return (BigDecimal) results.get(productId);    }    /**     * Gets the value of all products in the inventory of an organization.     * The value is the sum of posted debits minus the sum of posted credits     * in the INVENTORY_ACCOUNT or INV_ADJ_AVG_COST GL accounts for each product.     *     * @param   productId               Specify this to limit the query to one product     * @param   organizationPartyId     Organization of the transactions, always specify this.     * @param   transactionDate         Specify this to sum over all transactions before the transactionDate or set to null to sum over all dates     * @return  Map of productIds keyed to their net (debit - credit) amounts     */    public static Map getInventoryValueForAllProducts(String organizationPartyId, Timestamp transactionDate, GenericDelegator delegator)        throws GenericEntityException {        return getNetInventoryValueHelper(null, organizationPartyId, transactionDate, delegator);    }    /**     * Helper method to get product inventory values. Use one of the other methods that implements this,     * getInventoryValueForProduct() or getInventoryValueForAllProducts().     *     * @param   productId               Specify this to limit the query to one product     * @param   organizationPartyId     Organization of the transactions, always specify this.     * @param   transactionDate         Specify this to sum over all transactions before the transactionDate or set to null to sum over all dates     * @return  Map of productIds keyed to their net (debit - credit) amounts     */    private static Map getNetInventoryValueHelper(String productId, String organizationPartyId, Timestamp transactionDate, GenericDelegator delegator)        throws GenericEntityException {        if (organizationPartyId == null) {            throw new GenericEntityException("No organizationPartyId specified for getting product inventory value(s).");        }        // fields to select: exclude the transaction date from select list, otherwise we can't use the special view        List selectFields = UtilMisc.toList("productId", "amount", "glAccountTypeId");        // common AND conditions        List commonConditions = UtilMisc.toList(                new EntityExpr("isPosted", EntityOperator.EQUALS, "Y"),                new EntityExpr("organizationPartyId", EntityOperator.EQUALS, organizationPartyId)                );        // select all the inventory account types        commonConditions.add(new EntityConditionList(UtilMisc.toList(                    new EntityExpr("glAccountTypeId", EntityOperator.EQUALS, "INVENTORY_ACCOUNT"),                    new EntityExpr("glAccountTypeId", EntityOperator.EQUALS, "INV_ADJ_AVG_COST"),                    new EntityExpr("glAccountTypeId", EntityOperator.EQUALS, "RAWMAT_INVENTORY"),                    new EntityExpr("glAccountTypeId", EntityOperator.EQUALS, "WIP_INVENTORY")                    ), EntityOperator.OR));        // add optional constraints to common conditions        if (productId != null) commonConditions.add(new EntityExpr("productId", EntityOperator.EQUALS, productId));        if (transactionDate != null) commonConditions.add(new EntityExpr("transactionDate", EntityOperator.LESS_THAN_EQUAL_TO, transactionDate));        // build condition for debits        List debitConditions = new ArrayList(commonConditions);        debitConditions.add(new EntityExpr("debitCreditFlag", EntityOperator.EQUALS, "D"));        EntityConditionList debitConditionList = new EntityConditionList(debitConditions, EntityOperator.AND);        // perform the query        EntityListIterator listIt = delegator.findListIteratorByCondition("AcctgTransEntryProdSums", debitConditionList, null, selectFields,                UtilMisc.toList("productId"), // fields to order by                // the first true here is for "specifyTypeAndConcur" the second true is for a distinct select                new EntityFindOptions(true, EntityFindOptions.TYPE_SCROLL_INSENSITIVE, EntityFindOptions.CONCUR_READ_ONLY, true));        // get all values from the entity list iterator        List debitSums = listIt.getCompleteList();        // build condition for credits        List creditConditions = new ArrayList(commonConditions);        creditConditions.add(new EntityExpr("debitCreditFlag", EntityOperator.EQUALS, "C"));        EntityConditionList creditConditionList = new EntityConditionList(creditConditions, EntityOperator.AND);        // perform the query        listIt = delegator.findListIteratorByCondition("AcctgTransEntryProdSums", creditConditionList, null, selectFields,                UtilMisc.toList("productId"), // fields to order by                // the first true here is for "specifyTypeAndConcur" the second true is for a distinct select                new EntityFindOptions(true, EntityFindOptions.TYPE_SCROLL_INSENSITIVE, EntityFindOptions.CONCUR_READ_ONLY, true));        // get all values from the entity list iterator        List creditSums = listIt.getCompleteList();        // make a map of the product Id to the (debit - credit) amount        Map inventoryValueByProduct = FastMap.newInstance();        // the strategy is to store the negative of the credit amount in the map first (because debits might not exist for a particular product)        for (Iterator iter = creditSums.iterator(); iter.hasNext(); ) {            GenericValue value = (GenericValue) iter.next();            inventoryValueByProduct.put(UtilFinancial.getProductIdOrDefault(value), ZERO.subtract(value.getBigDecimal("amount")).setScale(decimals, rounding));        }        // then go through debits and add the debit amounts        for (Iterator iter = debitSums.iterator(); iter.hasNext(); ) {            GenericValue value = (GenericValue) iter.next();            BigDecimal creditAmount = (BigDecimal) inventoryValueByProduct.get(UtilFinancial.getProductIdOrDefault(value));            if (creditAmount == null) creditAmount = ZERO;  // if credit didn't exist, set to zero            BigDecimal difference = value.getBigDecimal("amount").add(creditAmount).setScale(decimals, rounding);            inventoryValueByProduct.put(UtilFinancial.getProductIdOrDefault(value), difference);        }        return inventoryValueByProduct;    }        /**     * Method to get total inventory quantity on hand in all facilities for a given product and organizataiton.     */    public static BigDecimal getInventoryQuantityForProduct(String productId, String organizationPartyId, GenericDelegator delegator, LocalDispatcher dispatcher)         throws GenericServiceException, GenericEntityException {        BigDecimal quantity = ZERO;        // the strategy is to loop through the organization facilities and get the product inventory for each facility        List facilities = delegator.findByAnd("Facility", UtilMisc.toMap("ownerPartyId", organizationPartyId));        for (Iterator iter = facilities.iterator(); iter.hasNext(); ) {            String facilityId = ((GenericValue) iter.next()).getString("facilityId");            Map serviceResults = dispatcher.runSync("getInventoryAvailableByFacility", UtilMisc.toMap("productId", productId, "facilityId", facilityId));            if (ServiceUtil.isError(serviceResults)) {                throw new GenericServiceException(ServiceUtil.getErrorMessage(serviceResults));            }            BigDecimal facilityQuantity = new BigDecimal(((Double) serviceResults.get("quantityOnHandTotal")).doubleValue());            quantity = quantity.add(facilityQuantity).setScale(decimals, rounding); // TODO: quantity sum needs its own decimals and rounding        }        return quantity;    }        /**     * Returns the total inventory value based on data from InventoryItem rather than accounting ledger data     *      * @param productId     * @param organizationPartyId     * @param delegator     * @param dispatcher     * @return     * @throws GenericEntityException     * @throws GenericServiceException     */    public static BigDecimal getInventoryValueFromItems(String productId, String organizationPartyId, GenericDelegator delegator, LocalDispatcher dispatcher)         throws GenericEntityException, GenericServiceException {        List items = delegator.findByAnd("InventoryItem", UtilMisc.toMap("productId", productId, "ownerPartyId", organizationPartyId));        BigDecimal total = ZERO;                for (Iterator it = items.iterator(); it.hasNext(); ) {            GenericValue item = (GenericValue) it.next();            if ((item.get("unitCost") != null) && (item.get("quantityOnHandTotal") != null)) {                BigDecimal conversionFactor = new BigDecimal(UtilFinancial.determineUomConversionFactor(delegator, dispatcher, organizationPartyId, item.getString("currencyUomId")));                // this precision is probably OK since we're multiplying                total = total.add(item.getBigDecimal("unitCost").multiply(item.getBigDecimal("quantityOnHandTotal")).multiply(conversionFactor)).setScale(decimals, rounding);            }        }                return total;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -