use of eu.ggnet.dwoss.uniqueunit.ee.eao.ProductEao in project dwoss by gg-net.
the class UnitProcessorOperation method receiptUniqueUnit.
private UniqueUnit receiptUniqueUnit(UniqueUnit recieptUnit, Product product, Shipment shipment) {
UniqueUnit uniqueUnit = new UniqueUnitEao(uuEm).findByIdentifier(UniqueUnit.Identifier.SERIAL, recieptUnit.getIdentifier(UniqueUnit.Identifier.SERIAL));
product = new ProductEao(uuEm).findById(product.getId());
if (uniqueUnit == null) {
recieptUnit.setProduct(product);
L.debug("persisting {}", recieptUnit);
// TODO: Update in UI.
recieptUnit.setShipmentId(shipment.getId());
recieptUnit.setShipmentLabel(shipment.getShipmentId());
recieptUnit.setInputDate(new Date());
uuEm.persist(recieptUnit);
uniqueUnit = recieptUnit;
} else {
uniqueUnit.setIdentifier(UniqueUnit.Identifier.REFURBISHED_ID, recieptUnit.getIdentifier(UniqueUnit.Identifier.REFURBISHED_ID));
uniqueUnit.setComment(recieptUnit.getComment());
uniqueUnit.setComments(recieptUnit.getComments());
uniqueUnit.setCondition(recieptUnit.getCondition());
uniqueUnit.setInternalComment(recieptUnit.getInternalComment());
uniqueUnit.setInternalComments(recieptUnit.getInternalComments());
uniqueUnit.setEquipments(recieptUnit.getEquipments());
uniqueUnit.setProduct(product);
uniqueUnit.setContractor(shipment.getContractor());
uniqueUnit.setShipmentId(shipment.getId());
uniqueUnit.setShipmentLabel(shipment.getShipmentId());
uniqueUnit.setWarranty(recieptUnit.getWarranty());
uniqueUnit.setWarrentyValid(recieptUnit.getWarrentyValid());
// Allways set the InputDate on receipt.
uniqueUnit.setInputDate(new Date());
L.debug("updating {}", recieptUnit);
}
return uniqueUnit;
}
use of eu.ggnet.dwoss.uniqueunit.ee.eao.ProductEao in project dwoss by gg-net.
the class RedTapeCloserOperation method poluteReporting.
/**
* Actually creating reportLines from the reportable documents.
* For each position of a {@link Document} a {@link ReportLine} is created with all information supplied.
* <p>
* Exceptions are:
* <ul>
* <li>A {@link Document} with a {@link Condition#CANCELED} which is silently ignored</li>
* <li>A {@link Document} with a {@link DocumentType#COMPLAINT} which sets all prices on the {@link ReportLine} to 0 and
* <ul>
* <li>If the {@link Document} has the {@link Condition#WITHDRAWN} or {@link Condition#REJECTED}, set {@link ReportLine#workflowStatus} to
* {@link ReportLine.WorkflowStatus#DISCHARGED}</li>
* <li>If the {@link Document} has the {@link Condition#ACCEPTED}, set {@link ReportLine#workflowStatus} to
* {@link ReportLine.WorkflowStatus#CHARGED}</li>
* <li>Otherwise set {@link ReportLine#workflowStatus} to {@link ReportLine.WorkflowStatus#UNDER_PROGRESS}</li>
* </ul>
* </li>
* <li>A {@link Document} with a {@link DocumentType#CREDIT_MEMO} gets its prices inverted</li>
* </ul>
* <p/>
* @param reportable the documents to create lines from
* @param monitor a optional monitor.
* @return the amount of created lines.
*/
private int poluteReporting(Set<Document> reportable, Date reporting, IMonitor monitor) {
WarrantyService warrantyService = null;
if (!warrantyServiceInstance.isUnsatisfied()) {
warrantyService = warrantyServiceInstance.get();
}
SubMonitor m = SubMonitor.convert(monitor, reportable.size() + 10);
m.start();
ReportLineEao reportLineEao = new ReportLineEao(reportEm);
UniqueUnitEao uniqueUnitEao = new UniqueUnitEao(uuEm);
ProductEao productEao = new ProductEao(uuEm);
int amountCreate = 0;
List<ReportLine> newLines = new ArrayList<>(reportable.size());
for (Document document : reportable) {
m.worked(1, "reported " + document.getIdentifier());
// A canceled document must be closed, but must not create a reportline.
if (document.getConditions().contains(Condition.CANCELED))
continue;
ReportLine l;
for (Position position : document.getPositions().values()) {
amountCreate++;
l = new ReportLine();
l.setActual(document.getActual());
l.setAmount(position.getAmount());
l.setBookingAccount(position.getBookingAccount().map(Ledger::getValue).orElse(-1));
l.setCustomerId(document.getDossier().getCustomerId());
l.setDescription(normalizeSpace(position.getDescription()));
l.setDocumentId(document.getId());
l.setDocumentIdentifier(document.getIdentifier());
l.setDocumentType(document.getType());
l.setDossierId(document.getDossier().getId());
l.setDossierIdentifier(document.getDossier().getIdentifier());
// TODO: We could use something else for a separator, but keep in mind that we want to avoid name, , , something.
l.setInvoiceAddress(normalizeSpace(document.getInvoiceAddress().getDescription()));
l.setName(normalizeSpace(position.getName()));
l.setPositionType(position.getType());
l.setPrice(position.getPrice());
l.setReportingDate(reporting);
l.setTax(position.getTax());
// Set via Report afterwards
l.setMarginPercentage(0);
// Set via Report afterwards
l.setPurchasePrice(0);
UiCustomer c = customerService.asUiCustomer(document.getDossier().getCustomerId());
if (c != null) {
l.setCustomerCompany(c.getCompany());
l.setCustomerName(c.toTitleNameLine());
l.setCustomerEmail(c.getEmail());
}
// A Credit Memo gets its prices inverted
if (document.getType() == DocumentType.CREDIT_MEMO) {
l.setPrice(position.getPrice() * (-1));
}
// Special handling of complaints.
if (document.getType() == DocumentType.COMPLAINT) {
// A Complaint position has "tagging" effect, but shall never result in a plus or minus.
l.setPrice(0);
if (document.getConditions().contains(Condition.REJECTED) || document.getConditions().contains(Condition.WITHDRAWN)) {
l.setWorkflowStatus(ReportLine.WorkflowStatus.DISCHARGED);
} else if (document.getConditions().contains(Condition.ACCEPTED)) {
l.setWorkflowStatus(ReportLine.WorkflowStatus.CHARGED);
} else {
l.setWorkflowStatus(ReportLine.WorkflowStatus.UNDER_PROGRESS);
}
}
// Extra information for Type Position
if (position.getType() == PositionType.UNIT || position.getType() == PositionType.UNIT_ANNEX) {
UniqueUnit uu = Objects.requireNonNull(uniqueUnitEao.findById(position.getUniqueUnitId()), "No UniqueUnit with id=" + position.getUniqueUnitId());
Product p = uu.getProduct();
if (uu.getContractor() == p.getTradeName().getManufacturer()) {
l.setContractorPartNo(p.getPartNo());
l.setContractorReferencePrice(p.getPrice(MANUFACTURER_COST));
} else {
l.setContractorPartNo(p.getAdditionalPartNo(uu.getContractor()));
l.setContractorReferencePrice(p.getPrice(CONTRACTOR_REFERENCE));
}
l.setManufacturerCostPrice(p.getPrice(MANUFACTURER_COST));
l.setContractor(uu.getContractor());
l.setContractorReferencePrice(p.getPrice(CONTRACTOR_REFERENCE));
if (Math.abs(l.getContractorReferencePrice()) < 0.001)
l.setContractorReferencePrice(p.getPrice(MANUFACTURER_COST));
l.setMfgDate(uu.getMfgDate());
l.setRefurbishId(uu.getRefurbishId());
l.setSerial(uu.getSerial());
l.setUniqueUnitId(uu.getId());
l.setSalesChannel(uu.getSalesChannel());
l.setPartNo(p.getPartNo());
l.setProductBrand(p.getTradeName());
l.setProductName(p.getName());
l.setProductGroup(p.getGroup());
l.setProductId(p.getId());
l.setGtin(p.getGtin());
// Extra Information for Type Product Batch
} else if (position.getType() == PositionType.PRODUCT_BATCH) {
Product p = Objects.requireNonNull(productEao.findById(position.getUniqueUnitProductId()), "No Product for id=" + position.getUniqueUnitProductId());
l.setPartNo(p.getPartNo());
l.setProductBrand(p.getTradeName());
l.setProductGroup(p.getGroup());
l.setProductName(p.getName());
l.setProductId(p.getId());
l.setGtin(p.getGtin());
l.setUniqueUnitId(position.getUniqueUnitId());
l.setSerial(position.getSerial());
l.setRefurbishId(position.getRefurbishedId());
if (warrantyService != null) {
// If this is no warranty Partno, this will return null ;-)
l.setContractor(warrantyService.warrantyContractor(p.getPartNo()));
}
}
reportEm.persist(l);
newLines.add(l);
}
}
reportEm.flush();
m.message("Updateing References");
for (ReportLine newLine : newLines) {
// Not Refs for Product_Batches or Versandkosten jet.
if (newLine.getUniqueUnitId() < 1)
continue;
if (newLine.getPositionType() == PositionType.PRODUCT_BATCH) {
// TODO: also evaluate the productId.
newLine.addAll(reportLineEao.findBySerialAndPositionTypeAndDossierId(newLine.getSerial(), newLine.getPositionType(), newLine.getDossierId()));
} else {
newLine.addAll(reportLineEao.findUnitsAlike(newLine.getUniqueUnitId(), newLine.getDossierId()));
}
}
updateSingleReferences(newLines);
m.worked(5);
m.finish();
return amountCreate;
}
use of eu.ggnet.dwoss.uniqueunit.ee.eao.ProductEao in project dwoss by gg-net.
the class PriceCoreOperation method store.
/**
* Stores the supplied Prices to units and the manufacturerPartNoPriceFixeds
*
* @param pers results to store
* @param comment a comment for the price history
* @param arranger a arranger for the price history
* @param monitor an optional monitor
*/
public void store(final List<PriceEngineResult> pers, String comment, String arranger, IMonitor monitor) {
final SubMonitor m = SubMonitor.convert(monitor, pers.size() + 27);
UniqueUnitEao uniqueUnitEao = new UniqueUnitEao(uuEm);
ProductEao productEao = new ProductEao(uuEm);
// preload sopo and unique units
m.message("Preloading UniqueUnits");
NavigableMap<String, UniqueUnit> uniqueUnits = UniqueUnit.asMapByRefurbishId(uniqueUnitEao.findByIdentifiers(REFURBISHED_ID, PriceEngineResult.toRefurbishIds(pers)));
m.worked(5);
for (PriceEngineResult per : pers) {
String msg = "Storing Unit " + per.getRefurbishedId() + " HP:" + per.getRetailerPrice() + " EP:" + per.getCustomerPrice() + " UnitFix:" + per.getUnitPriceFixed() + " ProductFix:" + per.getManufacturerPartPriceFixed();
L.info(msg);
m.worked(1, msg);
update(uniqueUnits.get(per.getRefurbishedId()), per, arranger, comment);
}
// Inferenced filtering for fixprices
Map<String, PriceEngineResult> fixPriceImports = new HashMap<>();
for (PriceEngineResult per : pers) {
if (per.getManufacturerPartPriceFixed() == NO_CHANGE)
continue;
fixPriceImports.put(per.getManufacturerPartNo(), per);
}
m.worked(1, "Perloading Products");
NavigableMap<String, Product> products = Product.asMapByPartNos(productEao.findByPartNos(PriceEngineResult.toPartNos(pers)));
m.worked(3);
m.setWorkRemaining(fixPriceImports.size());
for (PriceEngineResult per : fixPriceImports.values()) {
update(products.get(per.getManufacturerPartNo()), per, arranger, comment);
String msg = "Storing ProductDescription Fixed Price " + per.getProductName() + " Retailer:" + per.getRetailerPrice() + " Customer:" + per.getCustomerPrice() + " Manual:" + per.getManufacturerPartPriceFixed();
L.info(msg);
m.worked(1, msg);
}
m.finish();
}
use of eu.ggnet.dwoss.uniqueunit.ee.eao.ProductEao in project dwoss by gg-net.
the class RedTapeWorkerOperation method createSalesProduct.
/**
* Creates a new SalesProduct for the PartNo.
* <p/>
* @param partNo the partNo to use.
* @return the new SalesProduct.
* @throws UserInfoException if the PartNo does not exist.
*/
@Override
public SalesProduct createSalesProduct(String partNo) throws UserInfoException {
ProductEao productEao = new ProductEao(uuEm);
Product findByPartNo = productEao.findByPartNo(partNo);
if (findByPartNo == null)
throw new UserInfoException("Part Nummer exestiert Nicht!");
SalesProduct salesProduct = new SalesProduct(partNo, findByPartNo.getName(), findByPartNo.getPrice(PriceType.SALE), findByPartNo.getId(), findByPartNo.getDescription());
redTapeEm.persist(salesProduct);
return salesProduct;
}
use of eu.ggnet.dwoss.uniqueunit.ee.eao.ProductEao 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());
}
Aggregations