/**
* Axelor Business Solutions
*
* Copyright (C) 2016 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.apps.base.service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.axelor.apps.base.db.Product;
import com.axelor.apps.base.db.ProductVariant;
import com.axelor.apps.base.db.ProductVariantAttr;
import com.axelor.apps.base.db.ProductVariantValue;
import com.axelor.apps.base.db.repo.ProductRepository;
import com.axelor.apps.base.db.repo.ProductVariantRepository;
import com.google.inject.Inject;
public class ProductVariantService {
private static final Logger LOG = LoggerFactory.getLogger(ProductVariantService.class);
@Inject
private ProductRepository productRepo;
@Inject
private ProductVariantRepository productVariantRepo;
public ProductVariant createProductVariant(ProductVariantAttr productVariantAttr1, ProductVariantAttr productVariantAttr2,
ProductVariantAttr productVariantAttr3, ProductVariantAttr productVariantAttr4, ProductVariantValue productVariantValue1,
ProductVariantValue productVariantValue2, ProductVariantValue productVariantValue3, ProductVariantValue productVariantValue4, boolean usedForStock) {
ProductVariant productVariant = new ProductVariant();
productVariant.setProductVariantAttr1(productVariantAttr1);
productVariant.setProductVariantAttr2(productVariantAttr2);
productVariant.setProductVariantAttr3(productVariantAttr3);
productVariant.setProductVariantAttr4(productVariantAttr4);
productVariant.setProductVariantValue1(productVariantValue1);
productVariant.setProductVariantValue2(productVariantValue2);
productVariant.setProductVariantValue3(productVariantValue3);
productVariant.setProductVariantValue4(productVariantValue4);
productVariant.setUsedForStock(usedForStock);
return productVariant;
}
public ProductVariantValue createProductVariantValue(ProductVariantAttr productVariantAttr, String code, String name, BigDecimal priceExtra) {
ProductVariantValue productVariantValue = new ProductVariantValue();
productVariantValue.setCode(code);
productVariantValue.setName(name);
productVariantValue.setPriceExtra(priceExtra);
productVariantValue.setProductVariantAttr(productVariantAttr);
return productVariantValue;
}
public ProductVariantAttr createProductVariantAttr(String name) {
ProductVariantAttr productVariantAttr = new ProductVariantAttr();
productVariantAttr.setName(name);
productVariantAttr.setProductVariantValueList(new ArrayList<ProductVariantValue>());
return productVariantAttr;
}
public boolean equalsName(ProductVariant productVariant1, ProductVariant productVariant2) {
if(productVariant1 != null && productVariant2 != null && productVariant1.getName().equals(productVariant2.getName())) {
return true;
}
return false;
}
public boolean equals(ProductVariant productVariant1, ProductVariant productVariant2) {
if(productVariant1 != null && productVariant2 != null
&& productVariant1.getProductVariantAttr1().equals(productVariant2.getProductVariantAttr1())
&& productVariant1.getProductVariantAttr2().equals(productVariant2.getProductVariantAttr2())
&& productVariant1.getProductVariantAttr3().equals(productVariant2.getProductVariantAttr3())
&& productVariant1.getProductVariantAttr4().equals(productVariant2.getProductVariantAttr4())
&& productVariant1.getProductVariantValue1().equals(productVariant2.getProductVariantValue1())
&& productVariant1.getProductVariantValue2().equals(productVariant2.getProductVariantValue2())
&& productVariant1.getProductVariantValue3().equals(productVariant2.getProductVariantValue3())
&& productVariant1.getProductVariantValue4().equals(productVariant2.getProductVariantValue4()))
{
return true;
}
return false;
}
private ProductVariant getProductVariant(ProductVariantAttr productVariantAttr1, ProductVariantAttr productVariantAttr2,
ProductVariantAttr productVariantAttr3, ProductVariantAttr productVariantAttr4, ProductVariantValue productVariantValue1,
ProductVariantValue productVariantValue2, ProductVariantValue productVariantValue3, ProductVariantValue productVariantValue4, boolean usedForStock) {
return productVariantRepo.all().filter("self.productVariantAttr1 = ?1 AND self.productVariantAttr2 = ?2 AND self.productVariantAttr3 = ?3 AND " +
"self.productVariantAttr4 = ?4 AND self.productVariantValue1 = ?5 AND self.productVariantValue2 = ?6 AND self.productVariantValue3 = ?7 AND " +
"self.productVariantValue4 = ?8 AND self.usedForStock = 'true'", productVariantAttr1, productVariantAttr2, productVariantAttr3,
productVariantAttr4, productVariantValue1, productVariantValue2, productVariantValue3, productVariantValue4, usedForStock).fetchOne();
}
public ProductVariant copyProductVariant(ProductVariant productVariant, boolean usedForStock) {
return this.createProductVariant(
productVariant.getProductVariantAttr1(),
productVariant.getProductVariantAttr2(),
productVariant.getProductVariantAttr3(),
productVariant.getProductVariantAttr4(),
productVariant.getProductVariantValue1(),
productVariant.getProductVariantValue2(),
productVariant.getProductVariantValue3(),
productVariant.getProductVariantValue4(),
usedForStock);
}
public ProductVariant getStockProductVariant(ProductVariant productVariant) {
ProductVariant stockProductVariant = this.getProductVariant(
productVariant.getProductVariantAttr1(),
productVariant.getProductVariantAttr2(),
productVariant.getProductVariantAttr3(),
productVariant.getProductVariantAttr4(),
productVariant.getProductVariantValue1(),
productVariant.getProductVariantValue2(),
productVariant.getProductVariantValue3(),
productVariant.getProductVariantValue4(),
true);
if(stockProductVariant == null) {
stockProductVariant = this.copyProductVariant(productVariant, true);
}
return stockProductVariant;
}
/**
* Méthode permettant de récupérer la déclinaison de produit en fonction des attributs du parent (produit fabriqué)
* @param parentProduct
* Le produit finis ou semi-finis
* @param productModel
* Le modele de produit (Produit consommé)
* @return
* La déclinaison de produit consommé
*/
public Product getProductVariant(Product parentProduct, Product productModel) {
ProductVariant productVariant = parentProduct.getProductVariant();
if(productVariant != null && productModel.getIsModel()) {
return this.getProductVariant(productVariant, productModel);
}
return productModel;
}
private Product getProductVariant(ProductVariant parentProductVariant, Product productSearched) {
LOG.debug("Recherche d'un variant du produit {} ayant des attributs communs avec {}", productSearched.getCode(), parentProductVariant.getName());
ProductVariantValue productVariantValue1 = parentProductVariant.getProductVariantValue1();
ProductVariantValue productVariantValue2 = parentProductVariant.getProductVariantValue2();
ProductVariantValue productVariantValue3 = parentProductVariant.getProductVariantValue3();
ProductVariantValue productVariantValue4 = parentProductVariant.getProductVariantValue4();
if(productVariantValue1 != null) {
LOG.debug("Recherche d'un variant de produit ayant au moins comme attributs {} : {}",
productVariantValue1.getProductVariantAttr().getCode(), productVariantValue1.getCode());
List<? extends Product> productList = productRepo.all().filter("self.parentProduct = ?1 " +
"AND ((self.productVariant.productVariantAttr1.code = ?2 AND self.productVariant.productVariantValue1.code = ?3) " +
"OR (self.productVariant.productVariantAttr2.code = ?2 AND self.productVariant.productVariantValue2.code = ?3) " +
"OR (self.productVariant.productVariantAttr3.code = ?2 AND self.productVariant.productVariantValue3.code = ?3) " +
"OR (self.productVariant.productVariantAttr4.code = ?2 AND self.productVariant.productVariantValue4.code = ?3)) ",
productSearched, productVariantValue1.getProductVariantAttr().getCode(), productVariantValue1.getCode()).fetch();
if(productList == null || productList.isEmpty()) {
return productSearched;
}
Product productFind = null;
int nbAttr = 0;
for(Product product : productList) {
if(productVariantValue1 != null && productVariantValue2 != null && productVariantValue3 != null && productVariantValue4 != null) {
//4
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue2)
&& this.containsProductVariantValue(product, productVariantValue3) && this.containsProductVariantValue(product, productVariantValue4)) {
LOG.debug("Variant de produit trouvé directement : {} avec l'ensemble des attributs (4) en commun", product.getCode());
return product;
}
//3
if(nbAttr < 3) {
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue2)
&& this.containsProductVariantValue(product, productVariantValue3)) {
productFind = product;
nbAttr = 3;
}
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue2)
&& this.containsProductVariantValue(product, productVariantValue4)) {
productFind = product;
nbAttr = 3;
}
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue3)
&& this.containsProductVariantValue(product, productVariantValue4)) {
productFind = product;
nbAttr = 3;
}
if(this.containsProductVariantValue(product, productVariantValue2) && this.containsProductVariantValue(product, productVariantValue3)
&& this.containsProductVariantValue(product, productVariantValue4)) {
productFind = product;
nbAttr = 3;
}
}
if(nbAttr < 2) {
//2
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue2)) {
productFind = product;
nbAttr = 2;
}
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue3)) {
productFind = product;
nbAttr = 2;
}
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue4)) {
productFind = product;
nbAttr = 2;
}
if(this.containsProductVariantValue(product, productVariantValue2) && this.containsProductVariantValue(product, productVariantValue3)) {
productFind = product;
nbAttr = 2;
}
if(this.containsProductVariantValue(product, productVariantValue2) && this.containsProductVariantValue(product, productVariantValue4)) {
productFind = product;
nbAttr = 2;
}
if(this.containsProductVariantValue(product, productVariantValue3) && this.containsProductVariantValue(product, productVariantValue4)) {
productFind = product;
nbAttr = 2;
}
}
if(nbAttr < 1) {
//1
if(this.containsProductVariantValue(product, productVariantValue1)) {
productFind = product;
nbAttr = 1;
}
if(this.containsProductVariantValue(product, productVariantValue2)) {
productFind = product;
nbAttr = 1;
}
if(this.containsProductVariantValue(product, productVariantValue3)) {
productFind = product;
nbAttr = 1;
}
if(this.containsProductVariantValue(product, productVariantValue4)) {
productFind = product;
nbAttr = 1;
}
}
}
if(productVariantValue1 != null && productVariantValue2 != null && productVariantValue3 != null) {
//3
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue2)
&& this.containsProductVariantValue(product, productVariantValue3)) {
LOG.debug("Variant de produit trouvé directement : {} avec l'ensemble des attributs (3) en commun", product.getCode());
return product;
}
if(nbAttr < 2) {
//2
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue2)) {
productFind = product;
nbAttr = 2;
}
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue3)) {
productFind = product;
nbAttr = 2;
}
if(this.containsProductVariantValue(product, productVariantValue2) && this.containsProductVariantValue(product, productVariantValue3)) {
productFind = product;
nbAttr = 2;
}
}
if(nbAttr < 1) {
//1
if(this.containsProductVariantValue(product, productVariantValue1)) {
productFind = product;
nbAttr = 1;
}
if(this.containsProductVariantValue(product, productVariantValue2)) {
productFind = product;
nbAttr = 1;
}
if(this.containsProductVariantValue(product, productVariantValue3)) {
productFind = product;
nbAttr = 1;
}
}
}
if(productVariantValue1 != null && productVariantValue2 != null) {
//2
if(this.containsProductVariantValue(product, productVariantValue1) && this.containsProductVariantValue(product, productVariantValue2)) {
LOG.debug("Variant de produit trouvé directement : {} avec l'ensemble des attributs (2) en commun", product.getCode());
return product;
}
if(nbAttr < 1) {
//1
if(this.containsProductVariantValue(product, productVariantValue1)) {
productFind = product;
nbAttr = 1;
}
if(this.containsProductVariantValue(product, productVariantValue2)) {
productFind = product;
nbAttr = 1;
}
}
}
if(productVariantValue1 != null) {
if(this.containsProductVariantValue(product, productVariantValue1)) {
LOG.debug("Variant de produit trouvé directement : {} avec l'ensemble des attributs (1) en commun", product.getCode());
return product;
}
}
}
if(productFind != null) {
LOG.debug("Variant de produit trouvé : {} avec {} attributs en commun", productFind.getCode(), nbAttr);
return productFind;
}
}
return productSearched;
}
private boolean containsProductVariantValue(Product product, ProductVariantValue productVariantValue) {
ProductVariant productVariantFind = product.getProductVariant();
ProductVariantValue productVariantValue1 = productVariantFind.getProductVariantValue1();
ProductVariantValue productVariantValue2 = productVariantFind.getProductVariantValue2();
ProductVariantValue productVariantValue3 = productVariantFind.getProductVariantValue3();
ProductVariantValue productVariantValue4 = productVariantFind.getProductVariantValue4();
if((productVariantValue1 != null && productVariantValue1.getCode().equals(productVariantValue.getCode())
&& productVariantValue1.getProductVariantAttr().getCode().equals(productVariantValue.getProductVariantAttr().getCode()))
|| (productVariantValue2 != null && productVariantValue2.getCode().equals(productVariantValue.getCode())
&& productVariantValue2.getProductVariantAttr().getCode().equals(productVariantValue.getProductVariantAttr().getCode()))
|| (productVariantValue3 != null && productVariantValue3.getCode().equals(productVariantValue.getCode())
&& productVariantValue3.getProductVariantAttr().getCode().equals(productVariantValue.getProductVariantAttr().getCode()))
|| (productVariantValue4 != null && productVariantValue4.getCode().equals(productVariantValue.getCode())
&& productVariantValue4.getProductVariantAttr().getCode().equals(productVariantValue.getProductVariantAttr().getCode()))) {
return true;
}
return false;
}
}