org.openbravo.materialmgmt.VariantAutomaticGenerationProcess.java Source code

Java tutorial

Introduction

Here is the source code for org.openbravo.materialmgmt.VariantAutomaticGenerationProcess.java

Source

/*
 *************************************************************************
 * The contents of this file are subject to the Openbravo  Public  License
 * Version  1.0  (the  "License"),  being   the  Mozilla   Public  License
 * Version 1.1  with a permitted attribution clause; you may not  use this
 * file except in compliance with the License. You  may  obtain  a copy of
 * the License at http://www.openbravo.com/legal/license.html
 * Software distributed under the License  is  distributed  on  an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific  language  governing  rights  and  limitations
 * under the License.
 * The Original Code is Openbravo ERP.
 * The Initial Developer of the Original Code is Openbravo SLU
 * All portions are Copyright (C) 2013-2015 Openbravo SLU
 * All Rights Reserved.
 * Contributor(s):  ______________________________________.
 *************************************************************************
 */
package org.openbravo.materialmgmt;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.QueryTimeoutException;
import org.hibernate.criterion.Restrictions;
import org.hibernate.exception.GenericJDBCException;
import org.openbravo.advpaymentmngt.utility.FIN_Utility;
import org.openbravo.base.exception.OBException;
import org.openbravo.base.model.Entity;
import org.openbravo.base.model.ModelProvider;
import org.openbravo.base.model.Property;
import org.openbravo.base.provider.OBProvider;
import org.openbravo.dal.core.DalUtil;
import org.openbravo.dal.service.OBCriteria;
import org.openbravo.dal.service.OBDal;
import org.openbravo.dal.service.OBDao;
import org.openbravo.erpCommon.utility.OBError;
import org.openbravo.erpCommon.utility.OBMessageUtils;
import org.openbravo.model.ad.system.Client;
import org.openbravo.model.ad.utility.Image;
import org.openbravo.model.common.plm.Product;
import org.openbravo.model.common.plm.ProductAccounts;
import org.openbravo.model.common.plm.ProductCharacteristic;
import org.openbravo.model.common.plm.ProductCharacteristicConf;
import org.openbravo.model.common.plm.ProductCharacteristicValue;
import org.openbravo.model.pricing.pricelist.ProductPrice;
import org.openbravo.scheduling.Process;
import org.openbravo.scheduling.ProcessBundle;

public class VariantAutomaticGenerationProcess implements Process {
    private static final Logger log4j = Logger.getLogger(VariantAutomaticGenerationProcess.class);
    private static final int searchKeyLength = getSearchKeyColumnLength();
    private static final String SALES_PRICELIST = "SALES";
    private static final String PURCHASE_PRICELIST = "PURCHASE";

    @Override
    public void execute(ProcessBundle bundle) throws Exception {
        OBError msg = new OBError();
        msg.setType("Success");
        msg.setTitle(OBMessageUtils.messageBD("Success"));

        try {
            // retrieve standard params
            final String recordID = (String) bundle.getParams().get("M_Product_ID");
            Product product = OBDal.getInstance().get(Product.class, recordID);

            runChecks(product);

            int totalMaxLength = product.getSearchKey().length();
            long variantNumber = 1;
            Map<String, ProductCharacteristicAux> prChUseCode = new HashMap<String, ProductCharacteristicAux>();

            OBCriteria<ProductCharacteristic> prChCrit = OBDal.getInstance()
                    .createCriteria(ProductCharacteristic.class);
            prChCrit.add(Restrictions.eq(ProductCharacteristic.PROPERTY_PRODUCT, product));
            prChCrit.add(Restrictions.eq(ProductCharacteristic.PROPERTY_VARIANT, true));
            prChCrit.addOrderBy(ProductCharacteristic.PROPERTY_SEQUENCENUMBER, true);
            List<String> prChs = new ArrayList<String>();
            for (ProductCharacteristic pc : prChCrit.list()) {
                prChs.add(pc.getId());
            }
            int chNumber = prChs.size();
            String[] currentValues = new String[chNumber];

            int i = 0;
            for (ProductCharacteristic prCh : prChCrit.list()) {
                OBCriteria<ProductCharacteristicConf> prChConfCrit = OBDal.getInstance()
                        .createCriteria(ProductCharacteristicConf.class);
                prChConfCrit.add(Restrictions.eq(ProductCharacteristicConf.PROPERTY_CHARACTERISTICOFPRODUCT, prCh));

                List<String> prChConfs = new ArrayList<String>();
                for (ProductCharacteristicConf pcc : prChConfCrit.list()) {
                    prChConfs.add(pcc.getId());
                }
                long valuesCount = prChConfs.size();

                boolean useCode = true;
                int maxLength = 0;
                for (String id : prChConfs) {
                    ProductCharacteristicConf prChConf = OBDal.getInstance().get(ProductCharacteristicConf.class,
                            id);
                    if (StringUtils.isBlank(prChConf.getCode())) {
                        useCode = false;
                        break;
                    }
                    if (prChConf.getCode().length() > maxLength) {
                        maxLength = prChConf.getCode().length();
                    }
                }

                variantNumber = variantNumber * valuesCount;
                if (useCode) {
                    totalMaxLength += maxLength;
                }
                ProductCharacteristicAux prChAux = new ProductCharacteristicAux(useCode, prChConfs);
                currentValues[i] = prChAux.getNextValue();
                prChUseCode.put(prCh.getId(), prChAux);
                i++;
            }
            totalMaxLength += Long.toString(variantNumber).length();
            boolean useCodes = totalMaxLength <= searchKeyLength;

            boolean hasNext = true;
            int productNo = 0;
            int k = 0;
            Long start = System.currentTimeMillis();
            boolean multilingualDocs = OBDal.getInstance().get(Client.class, bundle.getContext().getClient())
                    .isMultilingualDocuments();
            do {
                k = k + 1;
                // Create variant product
                product = OBDal.getInstance().get(Product.class, recordID);
                Product variant = (Product) DalUtil.copy(product);

                if (multilingualDocs) {
                    variant.set(Product.PROPERTY_PRODUCTTRLLIST, null);
                }

                if (product.getImage() != null) {
                    Image newPrImage = (Image) DalUtil.copy(product.getImage(), false);
                    OBDal.getInstance().save(newPrImage);
                    variant.setImage(newPrImage);
                }

                variant.setGenericProduct(product);
                variant.setProductAccountsList(Collections.<ProductAccounts>emptyList());
                variant.setGeneric(false);
                for (ProductCharacteristic prCh : variant.getProductCharacteristicList()) {
                    prCh.setProductCharacteristicConfList(Collections.<ProductCharacteristicConf>emptyList());
                }

                String searchKey = product.getSearchKey();
                for (i = 0; i < chNumber; i++) {
                    ProductCharacteristicConf prChConf = OBDal.getInstance().get(ProductCharacteristicConf.class,
                            currentValues[i]);
                    ProductCharacteristicAux prChConfAux = prChUseCode.get(prChs.get(i));

                    if (useCodes && prChConfAux.isUseCode()) {
                        searchKey += prChConf.getCode();
                    }
                }
                for (int j = 0; j < (Long.toString(variantNumber).length()
                        - Integer.toString(productNo).length()); j++) {
                    searchKey += "0";
                }
                searchKey += productNo;
                variant.setSearchKey(searchKey);
                OBDal.getInstance().save(variant);
                String strChDesc = "";
                for (i = 0; i < chNumber; i++) {
                    ProductCharacteristicConf prChConf = OBDal.getInstance().get(ProductCharacteristicConf.class,
                            currentValues[i]);
                    ProductCharacteristicValue newPrChValue = OBProvider.getInstance()
                            .get(ProductCharacteristicValue.class);
                    newPrChValue.setCharacteristic(prChConf.getCharacteristicOfProduct().getCharacteristic());
                    newPrChValue.setCharacteristicValue(prChConf.getCharacteristicValue());
                    newPrChValue.setProduct(variant);
                    newPrChValue.setOrganization(product.getOrganization());
                    if (StringUtils.isNotBlank(strChDesc)) {
                        strChDesc += ", ";
                    }
                    strChDesc += prChConf.getCharacteristicOfProduct().getCharacteristic().getName() + ":";
                    strChDesc += " " + prChConf.getCharacteristicValue().getName();
                    OBDal.getInstance().save(newPrChValue);
                    if (prChConf.getCharacteristicOfProduct().isDefinesPrice()
                            && prChConf.getNetUnitPrice() != null) {
                        setPrice(variant, prChConf.getNetUnitPrice(),
                                prChConf.getCharacteristicOfProduct().getPriceListType());
                    }
                    if (prChConf.getCharacteristicOfProduct().isDefinesImage() && prChConf.getImage() != null) {
                        Image newImage = (Image) DalUtil.copy(prChConf.getImage(), false);
                        OBDal.getInstance().save(newImage);
                        variant.setImage(newImage);
                    }
                }
                variant.setCharacteristicDescription(strChDesc);
                OBDal.getInstance().save(variant);

                for (i = 0; i < chNumber; i++) {
                    ProductCharacteristicAux prChConfAux = prChUseCode.get(prChs.get(i));
                    currentValues[i] = prChConfAux.getNextValue();
                    if (!prChConfAux.isIteratorReset()) {
                        break;
                    } else if (i + 1 == chNumber) {
                        hasNext = false;
                    }
                }
                productNo++;

                // Creates variants from 1 to 1000 and shows time spent on it.
                if (k == 1000) {
                    OBDal.getInstance().flush();
                    OBDal.getInstance().getSession().clear();
                    log4j.debug("Variants loop: " + productNo + " : " + ((System.currentTimeMillis()) - (start)));
                    k = 0;
                    start = System.currentTimeMillis();
                }

            } while (hasNext);

            OBDal.getInstance().flush();
            OBDal.getInstance().getSession().clear();

            String message = OBMessageUtils.messageBD("variantsCreated");
            Map<String, String> map = new HashMap<String, String>();
            map.put("variantNo", Long.toString(productNo));
            msg.setMessage(OBMessageUtils.parseTranslation(message, map));
            bundle.setResult(msg);

            // Postgres wraps the exception into a GenericJDBCException
        } catch (GenericJDBCException ge) {
            log4j.error("Exception processing variant generation", ge);
            msg.setType("Error");
            msg.setTitle(
                    OBMessageUtils.messageBD(bundle.getConnection(), "Error", bundle.getContext().getLanguage()));
            msg.setMessage(ge.getSQLException().getMessage());
            bundle.setResult(msg);
            OBDal.getInstance().rollbackAndClose();
            // Oracle wraps the exception into a QueryTimeoutException
        } catch (QueryTimeoutException qte) {
            log4j.error("Exception processing variant generation", qte);
            msg.setType("Error");
            msg.setTitle(
                    OBMessageUtils.messageBD(bundle.getConnection(), "Error", bundle.getContext().getLanguage()));
            msg.setMessage(qte.getSQLException().getMessage().split("\n")[0]);
            bundle.setResult(msg);
            OBDal.getInstance().rollbackAndClose();
        } catch (final Exception e) {
            log4j.error("Exception processing variant generation", e);
            msg.setType("Error");
            msg.setTitle(
                    OBMessageUtils.messageBD(bundle.getConnection(), "Error", bundle.getContext().getLanguage()));
            msg.setMessage(FIN_Utility.getExceptionMessage(e));
            bundle.setResult(msg);
            OBDal.getInstance().rollbackAndClose();
        }

    }

    private static int getSearchKeyColumnLength() {
        final Entity prodEntity = ModelProvider.getInstance().getEntity(Product.ENTITY_NAME);

        final Property searchKeyProperty = prodEntity.getProperty(Product.PROPERTY_SEARCHKEY);
        return searchKeyProperty.getFieldLength();
    }

    private void runChecks(Product product) throws OBException {
        // Check existence of variants
        if (!product.getProductGenericProductList().isEmpty()) {
            throw new OBException(OBMessageUtils.parseTranslation("@ProductWithVariantsError@"));
        }
        // Check it is a generic product
        if (!product.isGeneric()) {
            throw new OBException(OBMessageUtils.parseTranslation("@ProductIsNotGenericError@"));
        }
        // Check existence of variant characteristic assigned to the product
        boolean errorFlag = true;
        for (ProductCharacteristic prCh : product.getProductCharacteristicList()) {
            if (prCh.isVariant()) {
                errorFlag = false;
                break;
            }
        }
        if (errorFlag) {
            throw new OBException(OBMessageUtils.parseTranslation("@GenericWithNoVariantChError@"));
        }
    }

    private void setPrice(Product variant, BigDecimal price, String strPriceListType) {
        List<ProductPrice> prodPrices = OBDao.getActiveOBObjectList(variant,
                Product.PROPERTY_PRICINGPRODUCTPRICELIST);
        for (ProductPrice prodPrice : prodPrices) {
            boolean isSOPriceList = prodPrice.getPriceListVersion().getPriceList().isSalesPriceList();
            if (SALES_PRICELIST.equals(strPriceListType) && !isSOPriceList) {
                continue;
            } else if (PURCHASE_PRICELIST.equals(strPriceListType) && isSOPriceList) {
                continue;
            }
            prodPrice.setStandardPrice(price);
            prodPrice.setListPrice(price);
            prodPrice.setPriceLimit(price);
            OBDal.getInstance().save(prodPrice);
        }
    }

    private static class ProductCharacteristicAux {
        private boolean useCode;
        private boolean isIteratorReset;
        private List<String> values;
        private Iterator<String> iterator;

        ProductCharacteristicAux(boolean _useCode, List<String> _values) {
            useCode = _useCode;
            values = _values;
        }

        public boolean isUseCode() {
            return useCode;
        }

        public boolean isIteratorReset() {
            return isIteratorReset;
        }

        public String getNextValue() {
            String prChConf;
            if (iterator == null || !iterator.hasNext()) {
                iterator = values.iterator();
                isIteratorReset = true;
            } else {
                isIteratorReset = false;
            }
            prChConf = iterator.next();
            return prChConf;
        }
    }
}