This commit is contained in:
Mario Zechner 2023-06-01 14:40:36 +02:00
commit 8c202de9a6
4 changed files with 78 additions and 50 deletions

View File

@ -3,51 +3,33 @@ const utils = require("./utils");
const conversions = { const conversions = {
"": {unit: "stk", factor: 1}, "": {unit: "stk", factor: 1},
"Blatt": {unit: "stk", factor: 1}, "blatt": {unit: "stk", factor: 1},
"g": {unit: "g", factor: 1}, "g": {unit: "g", factor: 1},
"gg": {unit: "g", factor: 1}, "gg": {unit: "g", factor: 1},
"gramm": {unit: "g", factor: 1}, "gramm": {unit: "g", factor: 1},
"kg": {unit: "g", factor: 1000}, "kg": {unit: "g", factor: 1000},
"KG": {unit: "g", factor: 1000},
"cl": {unit: "ml", factor: 100}, "cl": {unit: "ml", factor: 100},
"l": {unit: "ml", factor: 1000}, "l": {unit: "ml", factor: 1000},
"L": {unit: "ml", factor: 1000},
"ml": {unit: "ml", factor: 1}, "ml": {unit: "ml", factor: 1},
"Paar": {unit: "stk", factor: 1}, "paar": {unit: "stk", factor: 1},
"Stk.": {unit: "stk", factor: 1}, "stk.": {unit: "stk", factor: 1},
"stück": {unit: "stk", factor: 1}, "stück": {unit: "stk", factor: 1},
"Stück": {unit: "stk", factor: 1},
"er": {unit: "stk", factor: 1}, "er": {unit: "stk", factor: 1},
"Teebeutel": {unit: "stk", factor: 1}, "teebeutel": {unit: "stk", factor: 1},
}; };
exports.getCanonical = function(item, today) { exports.getCanonical = function(item, today) {
// try to read quantity and unit from product name // try to read quantity and unit from product name
let unit, quantity = 1;
const name = item.ProductName; const name = item.ProductName;
const nameTokens = name.trim().replaceAll('(','').replaceAll(')','').replaceAll(',', '.').split(' '); let [quantity, unit] = utils.parseUnitAndQuantityAtEnd(name);
const lastToken = nameTokens[nameTokens.length-1]; if(conversions[unit] === undefined) {
const secondLastToken = nameTokens.length > 2 ? nameTokens[nameTokens.length-2] : null;
const regex = /^([0-9.x]+)(.*)$/;
const matches = lastToken.match(regex);
if(matches) {
matches[1].split('x').forEach( (q)=> {
quantity = quantity * parseFloat(q)
})
unit = matches[2];
}
else if(secondLastToken !== null && secondLastToken.match(/^([0-9.]+)$/)) {
quantity = parseFloat(secondLastToken)
unit = lastToken;
}
else {
// fallback: use given quantity and unit (including packaging) // fallback: use given quantity and unit (including packaging)
quantity = item.Unit quantity = item.Unit
unit= item.UnitType unit= item.UnitType
} }
return utils.convertUnit({ return utils.convertUnit({
id: item.ProductID, id: item.ProductID,
name: item.ProductName, name,
price: item.Price, price: item.Price,
priceHistory: [{ date: today, price: item.Price }], priceHistory: [{ date: today, price: item.Price }],
isWeighted: item.IsBulk, isWeighted: item.IsBulk,

View File

@ -2,22 +2,41 @@ const axios = require("axios");
const utils = require("./utils"); const utils = require("./utils");
const conversions = { const conversions = {
'CM': { unit: 'cm', factor: 1 }, 'cm': { unit: 'cm', factor: 1 },
'DAG': { unit: 'g', factor: 10 }, 'dag': { unit: 'g', factor: 10 },
'DL': { unit: 'ml', factor: 10 }, 'dl': { unit: 'ml', factor: 10 },
'GRM': { unit: 'g', factor: 1 }, 'grm': { unit: 'g', factor: 1 },
'H87': { unit: 'ml', factor: 1000 }, 'kgm': { unit: 'g', factor: 1000 },
'HLT': { unit: 'ml', factor: 1000 }, 'ltr': { unit: 'ml', factor: 1000 },
'KGM': { unit: 'g', factor: 1000 }, 'mlt': { unit: 'ml', factor: 1 },
'LTR': { unit: 'ml', factor: 1000 }, 'mtr': { unit: 'm', factor: 1 },
'MLT': { unit: 'ml', factor: 1 }, 'stk': { unit: 'stk', factor: 1 },
'MTR': { unit: 'm', factor: 1 }, 'stk.': { unit: 'stk', factor: 1 },
'XRO': { unit: 'stk', factor: 1 }, 'g': { unit: 'g', factor: 1 },
'anw': { unit: 'stk', factor: 1 },
'l': { unit: 'ml', factor: 1000 },
'm': { unit: 'cm', factor: 100 },
'ml': { unit: 'ml', factor: 1 },
'kg': { unit: 'g', factor: 1000 },
'paar': { unit: 'stk', factor: 1 },
'stück': { unit: 'stk', factor: 1 },
'bl.': { unit: 'stk', factor: 1 },
'pkg': { unit: 'stk', factor: 1 },
'gr': { unit: 'g', factor: 1 },
'er': { unit: 'stk', factor: 1 },
}; };
exports.getCanonical = function(item, today) { exports.getCanonical = function(item, today) {
let quantity = item.prices[0].presentationPrice.measurementUnit.quantity let quantity = item.prices[0].presentationPrice.measurementUnit.quantity
let unit = item.prices[0].presentationPrice.measurementUnit.unitCode let unit = item.prices[0].presentationPrice.measurementUnit.unitCode.toLowerCase()
if(['xro', 'h87', 'hlt'].indexOf(unit)!=-1) {
const q = utils.parseUnitAndQuantityAtEnd(item.mixins.productCustomAttributes.packagingUnit)
quantity = q[0] ?? quantity;
unit = q[1];
}
if (!(unit in conversions)) {
unit = 'stk';
}
const isWeighted = (item.mixins.productCustomAttributes?.packagingDescription ?? "").startsWith("Gewichtsware"); const isWeighted = (item.mixins.productCustomAttributes?.packagingDescription ?? "").startsWith("Gewichtsware");
return utils.convertUnit({ return utils.convertUnit({
id: item.code, id: item.code,

View File

@ -3,23 +3,28 @@ const utils = require("./utils");
const HITS = Math.floor(30000 + Math.random() * 2000); const HITS = Math.floor(30000 + Math.random() * 2000);
const conversions = { const conversions = {
'G': { unit: 'g', factor: 1 }, 'g': { unit: 'g', factor: 1 },
'KG': { unit: 'g', factor: 1000 },
'L': { unit: 'ml', factor: 1000 },
'ML': { unit: 'ml', factor: 1 },
'STK': { unit: 'stk', factor: 1 },
'Stück': { unit: 'stk', factor: 1 },
'kg': { unit: 'g', factor: 1000 }, 'kg': { unit: 'g', factor: 1000 },
'l': { unit: 'ml', factor: 1000 }, 'l': { unit: 'ml', factor: 1000 },
'ml': { unit: 'ml', factor: 1 },
'stk': { unit: 'stk', factor: 1 },
'stück': { unit: 'stk', factor: 1 },
'100ml': { unit: 'ml', factor: 100 }, '100ml': { unit: 'ml', factor: 100 },
'WG': { unit: 'wg', factor: 1 }, 'wg': { unit: 'wg', factor: 1 },
'100g': { unit: 'g', factor: 100 }, '100g': { unit: 'g', factor: 100 },
'm': { unit: 'cm', factor: 100 }, 'm': { unit: 'cm', factor: 100 },
'cm': { unit: 'cm', factor: 100 },
'ml': { unit: 'ml', factor: 1 }, 'ml': { unit: 'ml', factor: 1 },
'meter': { unit: 'cm', factor: 100 },
'mm': { unit: 'cm', factor: .1 },
'stk.': { unit: 'cm', factor: .1 },
'cl': { unit: 'ml', factor: 10 },
'blatt': { unit: 'stk', factor: 1 },
}; };
exports.getCanonical = function(item, today) { exports.getCanonical = function(item, today) {
let price, unit, quantity; let price, unit, quantity;
const description = item.masterValues["short-description-3"] ?? item.masterValues["short-description-2"];
if (item.masterValues["quantity-selector"]) { if (item.masterValues["quantity-selector"]) {
const [str_price, str_unit] = item.masterValues["price-per-unit"].split('/'); const [str_price, str_unit] = item.masterValues["price-per-unit"].split('/');
price = parseFloat(str_price.replace("€", "")); price = parseFloat(str_price.replace("€", ""));
@ -27,15 +32,18 @@ exports.getCanonical = function(item, today) {
else { else {
price = item.masterValues.price; price = item.masterValues.price;
} }
if("short-description-3" in item.masterValues) { if(description) {
[quantity, unit] = item.masterValues["short-description-3"].replace(" EINWEG", "").replace(" MEHRWEG", "").trim().split(' '); const s = description.replace(" EINWEG", "").replace(" MEHRWEG", "").trim();
const q = utils.parseUnitAndQuantityAtEnd(s);
quantity = q[0]
unit = q[1]
} }
else{ if(conversions[unit]===undefined) {
// use price per unit to calculate quantity (less accurate) // use price per unit to calculate quantity (less accurate)
let [unitPrice, unit_] = item.masterValues['price-per-unit'].split('/'); let [unitPrice, unit_] = item.masterValues['price-per-unit'].split('/');
unitPrice = parseFloat(unitPrice.replace("€", "")); unitPrice = parseFloat(unitPrice.replace("€", ""));
quantity = Math.round(price / unitPrice) quantity = parseFloat((price / unitPrice).toFixed(3));
unit = unit_; unit = unit_.toLowerCase();
} }
return utils.convertUnit({ return utils.convertUnit({
id: item.masterValues["code-internal"], id: item.masterValues["code-internal"],

View File

@ -1,7 +1,7 @@
exports.convertUnit = function (item, units, store) { exports.convertUnit = function (item, units, store) {
if(!(item.unit in units)) { if(!(item.unit in units)) {
console.error(`Unknown unit in ${store}: '${item.unit}`); console.error(`Unknown unit in ${store}: '${item.unit}' in item ${item.name}`);
return item; return item;
} }
@ -18,3 +18,22 @@ exports.convertUnit = function (item, units, store) {
} }
return item; return item;
} }
exports.parseUnitAndQuantityAtEnd = function (name) {
let unit, quantity = 1;
const nameTokens = name.trim().replaceAll('(','').replaceAll(')','').replaceAll(',', '.').split(' ');
const lastToken = nameTokens[nameTokens.length-1];
const secondLastToken = nameTokens.length >= 2 ? nameTokens[nameTokens.length-2] : null;
const token = parseFloat(lastToken) ? lastToken : secondLastToken + lastToken;
const regex = /^([0-9.x]+)(.*)$/;
const matches = token.match(regex);
if(matches) {
matches[1].split('x').forEach( (q)=> {
quantity = quantity * parseFloat(q)
})
unit = matches[2];
return [quantity, unit.toLowerCase()];
}
return [undefined, undefined];
}