use of eu.ggnet.dwoss.uniqueunit.ee.entity.Product in project dwoss by gg-net.
the class PriceCoreOperationIT method testStore.
@Test
public void testStore() {
stockGenerator.makeStocksAndLocations(2);
receiptGenerator.makeUniqueUnits(20, true, false);
// Estimate all Units
List<PriceEngineResult> pers = priceCore.loadAndCalculate(null);
final double fixedUnitPrice = 100;
final double fixedProductPrice = 50;
String fixedPriceRefurbishId = pers.get(0).getRefurbishedId();
pers.get(0).setCustomerPrice(100);
pers.get(0).setRetailerPrice(100);
pers.get(0).setUnitPriceFixed(PriceEngineResult.Change.SET);
String fixedPartNo = pers.get(3).getManufacturerPartNo();
pers.get(3).setCustomerPrice(50);
pers.get(3).setRetailerPrice(50);
pers.get(3).setManufacturerPartPriceFixed(PriceEngineResult.Change.SET);
priceCore.store(pers, "via test", "testuser", null);
UniqueUnit uniqueUnit = uniqueUnitAgent.findUnitByIdentifierEager(Identifier.REFURBISHED_ID, fixedPriceRefurbishId);
assertEquals(fixedUnitPrice, uniqueUnit.getPrice(PriceType.CUSTOMER), 0.001);
assertEquals(fixedUnitPrice, uniqueUnit.getPrice(PriceType.RETAILER), 0.001);
assertTrue("Unit should contain Flage PriceFixed" + uniqueUnit.getFlags(), uniqueUnit.getFlags().contains(UniqueUnit.Flag.PRICE_FIXED));
for (PriceHistory priceHistory : uniqueUnit.getPriceHistory()) {
assertTrue(priceHistory.getComment().contains("unitfix"));
assertEquals(fixedUnitPrice, priceHistory.getPrice(), 0.001);
assertTrue(priceHistory.getType() == PriceType.CUSTOMER || priceHistory.getType() == PriceType.RETAILER);
}
Product product = uniqueUnitAgent.findProductByPartNoEager(fixedPartNo);
assertEquals(fixedProductPrice, product.getPrice(PriceType.CUSTOMER), 0.001);
assertEquals(fixedProductPrice, product.getPrice(PriceType.RETAILER), 0.001);
assertTrue(product.getFlags().contains(Product.Flag.PRICE_FIXED));
for (PriceHistory priceHistory : product.getPriceHistory()) {
assertTrue(priceHistory.getComment().contains("productfix"));
assertEquals(fixedProductPrice, priceHistory.getPrice(), 0.001);
assertTrue(priceHistory.getType() == PriceType.CUSTOMER || priceHistory.getType() == PriceType.RETAILER);
}
}
use of eu.ggnet.dwoss.uniqueunit.ee.entity.Product in project dwoss by gg-net.
the class ReceiptGeneratorOperation method makeUniqueUnits.
/**
* 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;
L.info("Generating {} Units", amount);
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");
L.debug("Transaction prepared {}", transaction);
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");
// Ad the now persisted instance.
units.add(uniqueUnitAgent.findUnitByIdentifierEager(REFURBISHED_ID, unit.getRefurbishId()));
}
stockTransactionProcessor.rollIn(Arrays.asList(transaction), "JUnit");
m.finish();
return units;
}
use of eu.ggnet.dwoss.uniqueunit.ee.entity.Product in project dwoss by gg-net.
the class ReceiptGeneratorOperation method makeWarrantyProduct.
public void makeWarrantyProduct(String partNumber) {
Product p = new Product();
p.setPartNo(partNumber);
p.setTradeName(TradeName.ACER);
p.setName("Garantieerweiterung auf 2 Jahre, 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 123 weitergegeben wird." + " Seriennummer des Gerätes: ");
p.setGroup(COMMENTARY);
uuEm.persist(p);
}
use of eu.ggnet.dwoss.uniqueunit.ee.entity.Product in project dwoss by gg-net.
the class ContractorPricePartNoImporterOperation method fromContractorXls.
// Manufacturer PartNo | EAN | Name | Contractor Reference Price | ContractorPartNo <br />
/**
* See {@link ContractorPricePartNoImporter#fromContractorXls(de.dw.rules.TradeName, de.dw.util.FileJacket, java.lang.String) }.
* <p/>
* @param inFile the inFile
* @param arranger the arranger
* @return
*/
@Override
public Reply<Void> fromContractorXls(TradeName contractor, FileJacket inFile, String arranger) {
final SubMonitor m = monitorFactory.newSubMonitor(contractor + " Preise und Artikelnummern importieren", 100);
m.start();
m.message("Reading File");
ProductEao productEao = new ProductEao(uuEm);
ReportLineEao reportLineEao = new ReportLineEao(reportEm);
LucidCalcReader reader = new JExcelLucidCalcReader();
reader.addColumn(0, String.class).addColumn(1, String.class).addColumn(2, String.class).addColumn(3, Double.class).addColumn(4, String.class);
List<ContractorImport> imports = reader.read(inFile.toTemporaryFile(), ContractorImport.class);
List<String> errors = reader.getErrors();
List<String> info = new ArrayList<>();
// here for size, needed down below
List<ReportLine> missingContractorPartNo = reportLineEao.findMissingContractorPartNo(contractor);
m.worked(5);
m.setWorkRemaining((int) (imports.size() + imports.size() * 0.5 + missingContractorPartNo.size()));
int databaseLines = 0;
int updatedGtin = 0;
int newPrices = 0;
int updatedPrices = 0;
int updatedContractorPartNo = 0;
Map<Product, SortedSet<ContractorImport>> importable = new HashMap<>();
for (ContractorImport ci : imports) {
m.worked(1, "Preparing and Sorting (" + ci.manufacturerPartNo + ")");
if (!ci.hasManufacturerPartNoOrGtin()) {
errors.add("No ManufacturerPartNo or EAN found for " + ci);
continue;
}
Product p = null;
// First, try finding it via gtin
if (ci.hasValidGtin())
p = productEao.findByGtin(Long.parseLong(ci.gtin));
// Second try finding it via the partNo field raw
if (p == null && !StringUtils.isBlank(ci.manufacturerPartNo))
p = productEao.findByPartNo(ci.manufacturerPartNo);
if (p == null) {
// Third, try it by regex matching of part no patterns
// Todo: implement more partno patterns an use them here, or add the type of import to this method.
Matcher matcher = AcerRules.PART_NO_PATTERN.matcher(ci.manufacturerPartNo);
if (matcher.find())
p = productEao.findByPartNo(matcher.group());
}
if (p == null) {
errors.add("No UniqueUnit.Product Entity found for PartNo " + ci.manufacturerPartNo + " bzw. Gtin " + ci.gtin + ", Ignoring");
continue;
}
databaseLines++;
if (importable.containsKey(p)) {
// sorting based on product
importable.get(p).add(ci);
} else {
SortedSet<ContractorImport> set = new TreeSet<>(Comparator.comparing(ContractorImport::getReferencePrice));
set.add(ci);
importable.put(p, set);
}
}
// update size
m.setWorkRemaining(missingContractorPartNo.size() + importable.size());
for (Entry<Product, SortedSet<ContractorImport>> entry : importable.entrySet()) {
Product p = entry.getKey();
// only us the importline with the lowest price.
ContractorImport ci = entry.getValue().first();
m.worked(1, "Importing " + ProductFormater.toDetailedName(p));
if (p.getGtin() == 0 && ci.hasValidGtin()) {
// Optional set of gtin, if it is missing.
p.setGtin(Long.parseLong(ci.gtin));
updatedGtin++;
}
if (ci.getReferencePrice() > 0.01 && !TwoDigits.equals(p.getPrice(CONTRACTOR_REFERENCE), ci.getReferencePrice())) {
// If price is valid and not equal, set it.
double oldPrice = p.getPrice(CONTRACTOR_REFERENCE);
if (p.hasPrice(CONTRACTOR_REFERENCE))
updatedPrices++;
else
newPrices++;
p.setPrice(CONTRACTOR_REFERENCE, ci.getReferencePrice(), "Import by " + arranger);
info.add(ProductFormater.toDetailedName(p) + " added/updated contractor reference price from " + oldPrice + " to " + ci.getReferencePrice());
} else {
errors.add(ci + " hat keinen Preis");
}
if (ci.hasValidContractorPartNo(contractor)) {
// If partNo is valid, set it.
String contractorPartNo = ci.toNormalizeContractorPart(contractor);
if (!contractorPartNo.equals(p.getAdditionalPartNo(contractor))) {
info.add(ProductFormater.toDetailedName(p) + " added/updated contractor partno from " + p.getAdditionalPartNo(contractor) + " to " + contractorPartNo);
p.setAdditionalPartNo(contractor, contractorPartNo);
updatedContractorPartNo++;
}
} else {
errors.add(ci.violationMessagesOfContractorPartNo(contractor));
}
}
uuEm.flush();
// Also update existing report lines, which have unset values.
// TODO: This should happen from the report component on needed basis or as event call. not here.
m.message("Updateing existing Reportlines");
int updatedReportLinePartNo = 0;
int updatedReportLineReferencePrice = 0;
int updatedReportLineGtin = 0;
for (ReportLine line : missingContractorPartNo) {
Product product = uuEm.find(Product.class, line.getProductId());
m.worked(1, "Updating ReportLine: " + line.getId());
String head = "ReportLine(id=" + line.getId() + ") of " + ProductFormater.toDetailedName(product);
String msg = "";
if (product.getAdditionalPartNo(contractor) != null) {
line.setContractorPartNo(product.getAdditionalPartNo(contractor));
msg += " contractorPartNo:" + line.getContractorPartNo();
updatedReportLinePartNo++;
}
if (product.hasPrice(CONTRACTOR_REFERENCE) && line.getContractorReferencePrice() == 0) {
line.setContractorReferencePrice(product.getPrice(CONTRACTOR_REFERENCE));
msg += " contractorReferencePrice:" + line.getContractorReferencePrice();
updatedReportLineReferencePrice++;
}
if (product.getGtin() != line.getGtin()) {
line.setGtin(product.getGtin());
msg += " gtin:" + line.getGtin();
updatedReportLineGtin++;
}
if (StringUtils.isBlank(msg)) {
errors.add(head + ", no updateable values found in product.");
} else {
info.add(head + " updated " + msg);
}
}
String summary = "Zeilen, mit gefunden (db)Artikeln: " + databaseLines + " (Entweder über PartNo oder Gtin)\n" + "GTIN/EAN aktuallisiert: " + updatedGtin + "\n" + "Neue Preise hinterlegt: " + newPrices + "\n" + "Preise aktualisiert: " + updatedPrices + "\n" + "Lieferantenartikelnummer aktualisiert: " + updatedContractorPartNo + "\n" + "Report-Fehlende GTIN/Preise/Artikelnummern Zeilen: " + missingContractorPartNo.size() + "\n" + "Report-GTIN/EAN aktuallisiert: " + updatedReportLineGtin + "\n" + "Report-Preise aktualisiert: " + updatedReportLineReferencePrice + "\n" + "Report-Lieferantenartikelnummer aktualisiert: " + updatedReportLinePartNo;
StringBuilder details = new StringBuilder();
if (!info.isEmpty()) {
details.append("Infos\n-----\n");
info.forEach((i) -> details.append(i).append("\n"));
}
details.append("-----------------\nFehler/Nicht importierbar\n-----------------\n");
errors.forEach((error) -> details.append(error).append("\n"));
m.finish();
if (updatedGtin + newPrices + updatedPrices + updatedContractorPartNo == 0)
return Reply.failure(summary, details.toString());
else
return Reply.success(null, summary, details.toString());
}
use of eu.ggnet.dwoss.uniqueunit.ee.entity.Product in project dwoss by gg-net.
the class ContractorPricePartNoImporterOperation method fromManufacturerXls.
@Override
public Reply<Void> fromManufacturerXls(TradeName contractorManufacturer, FileJacket inFile, String arranger) {
if (!contractorManufacturer.isManufacturer())
throw new RuntimeException(contractorManufacturer + " is not a Manufacturer");
final SubMonitor m = monitorFactory.newSubMonitor(contractorManufacturer.getName() + " Costpreise importieren", 100);
m.start().message("Reading File");
ProductEao productEao = new ProductEao(uuEm);
LucidCalcReader reader = new JExcelLucidCalcReader();
reader.addColumn(0, String.class).addColumn(1, Double.class);
List<ManufacturerImport> imports = reader.read(inFile.toTemporaryFile(), ManufacturerImport.class);
List<String> errors = reader.getErrors();
m.worked(5);
m.setWorkRemaining(imports.size());
L.info("Imports: {}", imports);
PartNoSupport partNoSupport = contractorManufacturer.getPartNoSupport();
int databaseLines = 0;
int newPrices = 0;
int updatedPrices = 0;
for (ManufacturerImport mi : imports) {
m.worked(1);
if (partNoSupport != null && !partNoSupport.isValid(mi.partNo)) {
errors.add(partNoSupport.violationMessages(mi.partNo));
continue;
}
if (mi.costPrice == null || mi.costPrice <= 0.01) {
errors.add("PartNo " + mi.costPrice + " hat keinen Preis");
continue;
}
m.message("Importing (" + mi.partNo + ")");
Product p = productEao.findByPartNo(mi.partNo);
if (p == null) {
errors.add("No UniqueUnit Entity for PartNo " + mi.partNo);
continue;
}
databaseLines++;
if (mi.getCostPrice() > 0.01 && !TwoDigits.equals(mi.getCostPrice(), p.getPrice(MANUFACTURER_COST))) {
if (p.hasPrice(MANUFACTURER_COST))
updatedPrices++;
else
newPrices++;
p.setPrice(PriceType.MANUFACTURER_COST, mi.costPrice, "Import by " + arranger);
}
}
m.finish();
String summary = "Zeilen, mit gefunden (db)Artikeln: " + databaseLines + " \n" + "Neue Preise hinterlegt: " + newPrices + "\n" + "Preise aktualisiert: " + updatedPrices;
StringBuilder details = new StringBuilder();
for (Object error : errors) {
details.append(error.toString()).append("\n");
}
m.finish();
if (newPrices + updatedPrices == 0)
return Reply.failure(summary, details.toString());
else
return Reply.success(null, summary, details.toString());
}
Aggregations