/*
* Copyright (C) 2014 GG-Net GmbH - Oliver Günther
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package eu.ggnet.dwoss.receipt.gen;
import eu.ggnet.dwoss.rules.ReceiptOperation;
import eu.ggnet.dwoss.rules.TradeName;
import eu.ggnet.dwoss.rules.SalesChannel;
import eu.ggnet.dwoss.progress.MonitorFactory;
import eu.ggnet.dwoss.progress.SubMonitor;
import eu.ggnet.dwoss.stock.entity.Shipment;
import eu.ggnet.dwoss.stock.entity.StockTransaction;
import eu.ggnet.dwoss.stock.entity.Stock;
import eu.ggnet.dwoss.uniqueunit.entity.Product;
import eu.ggnet.dwoss.uniqueunit.entity.PriceType;
import eu.ggnet.dwoss.uniqueunit.entity.UniqueUnit;
import java.util.*;
import javax.ejb.*;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import org.slf4j.*;
import eu.ggnet.dwoss.mandator.api.value.Contractors;
import eu.ggnet.dwoss.spec.assist.gen.SpecGenerator;
import eu.ggnet.dwoss.spec.entity.ProductSpec;
import eu.ggnet.dwoss.stock.StockTransactionProcessor;
import eu.ggnet.dwoss.stock.assist.Stocks;
import eu.ggnet.dwoss.stock.assist.gen.StockGeneratorOperation;
import eu.ggnet.dwoss.stock.emo.StockTransactionEmo;
import eu.ggnet.dwoss.uniqueunit.UniqueUnitAgent;
import eu.ggnet.dwoss.uniqueunit.assist.UniqueUnits;
import eu.ggnet.dwoss.uniqueunit.assist.gen.UniqueUnitGenerator;
import eu.ggnet.dwoss.uniqueunit.op.ProductOperation;
import eu.ggnet.dwoss.util.persistence.eao.DefaultEao;
import eu.ggnet.dwoss.receipt.ProductProcessor;
import eu.ggnet.dwoss.receipt.UnitProcessor;
import static eu.ggnet.dwoss.rules.ProductGroup.COMMENTARY;
/**
* Generator for Products an
* import static de.dw.rules.ProductGroup.COMMENTARY;
* d Units to be receipt, uses {@link SpecGenerator}.
*
* @author oliver.guenther
*/
@Stateless
public class ReceiptGeneratorOperation {
private final static Random R = new Random();
private final Logger L = LoggerFactory.getLogger(ReceiptGeneratorOperation.class);
@Inject
@Stocks
private EntityManager stockEm;
@Inject
@UniqueUnits
private EntityManager uuEm;
@Inject
private StockGeneratorOperation stockGen;
@EJB
private ProductProcessor productProcessor;
@EJB
private UnitProcessor unitProcessor;
@EJB
private StockTransactionProcessor stockTransactionProcessor;
@Inject
private ProductOperation productOperation;
@EJB
private UniqueUnitAgent uniqueUnitAgent;
@Inject
private MonitorFactory monitorFactory;
@Inject
private StockTransactionEmo stockTransactionEmo;
@Inject
private Contractors contractors;
private final UniqueUnitGenerator unitGenerator = new UniqueUnitGenerator();
private final SpecGenerator specGenerator = new SpecGenerator();
/**
* Generates an amount of ProductSpecs and receipts them.
*
* @param amount the amount to generate.
* @param generateCostPrice
* @return the generated and receipted specs.
*/
public List<ProductSpec> makeProductSpecs(int amount, boolean generateCostPrice) {
SubMonitor m = monitorFactory.newSubMonitor("Generating " + amount + " Products", amount);
m.start();
List<ProductSpec> specs = new ArrayList<>();
for (int i = 0; i < amount; i++) {
ProductSpec spec = makeProductSpec(generateCostPrice);
specs.add(spec);
m.worked(1, spec.getPartNo());
}
m.finish();
return specs;
}
/**
* Generates one ProductSpec and receipts it.
*
* @param generateCostPrice if true generates a random costprice between 1 and 1000
* @return the generated ProductSpec.
*/
private ProductSpec makeProductSpec(boolean generateCostPrice) {
ProductSpec spec = specGenerator.makeSpec();
L.info("Persisting {}", spec);
spec = productProcessor.create(spec, spec.getModel());
if ( generateCostPrice ) productOperation.updatePrice(spec.getProductId(), PriceType.MANUFACTURER_COST,
R.nextInt(1000) + 1, "Generated by ReceiptGeneratorOperation.makeProductSpec()");
return spec;
}
/**
* Generates one ProductSpec and receipts it.
*
* @return the generated ProductSpec.
*/
public ProductSpec makeProductSpec() {
return makeProductSpec(false);
}
/**
* Generates an amount of UniquUnits and receipts them.
*
* @param amount the amount to generate.
* @param generateSalesChannel
* @param generatePrice if true a random customer and retailer price is set
* @return the generated and receipted UniquUnits.
*/
// TODO: Create more Shipments on multiple contractors.
public List<UniqueUnit> makeUniqueUnits(int amount, boolean generateSalesChannel, boolean generatePrice) {
final int minProducts = 5;
final int maxProducts = 450;
int amountProducts = (amount / 25);
if ( amountProducts <= minProducts ) amountProducts = minProducts;
if ( amountProducts >= maxProducts ) amountProducts = maxProducts;
SubMonitor m = monitorFactory.newSubMonitor("Generating " + amount + " Units", amount);
m.start();
List<ProductSpec> productSpecs = makeProductSpecs(amountProducts, generatePrice);
List<UniqueUnit> units = new ArrayList<>();
Stock stock = findOrMakeStock();
TradeName contractor = new ArrayList<>(contractors.all()).get(R.nextInt(contractors.all().size()));
Shipment shipment = new Shipment("TEST-SHIPMENT-" + R.nextInt(10), contractor, TradeName.ACER, Shipment.Status.OPENED);
stockEm.persist(shipment);
StockTransaction transaction = stockTransactionEmo.requestRollInPrepared(stock.getId(), "SampleGenerator", "Rollin via make UniqueUnits");
for (int i = 0; i < amount; i++) {
ProductSpec productSpec = productSpecs.get(R.nextInt(productSpecs.size()));
Product product = uniqueUnitAgent.findById(Product.class, productSpec.getProductId());
UniqueUnit unit = unitGenerator.makeUniqueUnit(contractor, product);
m.worked(1, "created SopoNr " + unit.getRefurbishId());
if ( generatePrice ) {
int price = R.nextInt(1000) + 1;
unit.setPrice(PriceType.CUSTOMER, price, "Generated by ReceiptGeneratorOperation.makeUniqueUnits()");
unit.setPrice(PriceType.RETAILER, price * 1.08, "Generated by ReceiptGeneratorOperation.makeUniqueUnits()");
}
if ( generateSalesChannel ) unit.setSalesChannel(R.nextBoolean() ? SalesChannel.CUSTOMER : SalesChannel.RETAILER);
unitProcessor.receipt(unit, product, shipment, transaction, ReceiptOperation.SALEABLE, "SampleGenerator", "Generator");
units.add(unit);
}
stockTransactionProcessor.rollIn(Arrays.asList(transaction), "JUnit");
m.finish();
return units;
}
/**
* Generates one UniquUnits and receipts it.
*
* @return the generated UniquUnits.
*/
public UniqueUnit makeUniqueUnit() {
Stock stock = findOrMakeStock();
TradeName contractor = new ArrayList<>(contractors.all()).get(R.nextInt(contractors.all().size()));
Shipment shipment = new Shipment("TEST-SHIPMENT-" + R.nextInt(10), contractor, TradeName.ACER, Shipment.Status.OPENED);
stockEm.persist(shipment);
StockTransaction transaction = stockTransactionEmo.requestRollInPrepared(stock.getId(), "SampleGenerator", "Rollin via makeUniqueUnit");
ProductSpec productSpec = makeProductSpec();
Product product = uniqueUnitAgent.findById(Product.class, productSpec.getProductId());
UniqueUnit unit = unitGenerator.makeUniqueUnit(contractor, product);
unit.setProduct(product);
unitProcessor.receipt(unit, unit.getProduct(), shipment, transaction, ReceiptOperation.SALEABLE, "SampleGenerator", "Generator");
stockTransactionProcessor.rollIn(Arrays.asList(transaction), "JUnit");
return unit;
}
public void makeWarrantyProduct(String partNumber) {
Product p = new Product();
p.setPartNo(partNumber);
p.setTradeName(TradeName.ACER);
p.setName("Garantieerweiterung auf 2 Jahre inkl. 1 Jahr McAfee, Seriennummer: ");
p.setDescription("Mit dem Kauf der Garantieerweiterung wird bestätigt, "
+ "dass die angegebene e-mail Addresse für die Aktivierung ausschließlich an die Acer Computer GmbH weitergegeben wird."
+ " Seriennummer des Gerätes: ");
p.setGroup(COMMENTARY);
uuEm.persist(p);
}
private Stock findOrMakeStock() {
List<Stock> stocks = new DefaultEao<>(Stock.class, stockEm).findAll();
if ( !stocks.isEmpty() ) return stocks.get(0);
return stockGen.makeStocksAndLocations(1).get(0);
}
}