@softwear/latestcollectioncore 1.0.163 → 1.0.165
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/articleStatus.d.ts +1 -0
- package/dist/articleStatus.js +4 -1
- package/dist/ensureImpliedProperties.d.ts +7 -0
- package/dist/ensureImpliedProperties.js +34 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/transaction.d.ts +1 -0
- package/dist/transaction.js +1 -0
- package/dist/types.d.ts +2 -3
- package/package.json +2 -4
- package/src/articleStatus.ts +4 -0
- package/src/ensureImpliedProperties.ts +23 -0
- package/src/index.ts +1 -0
- package/src/transaction.ts +1 -0
- package/src/types.ts +2 -3
- package/test/articleStatus.spec.js +25 -0
- package/test/ensureImpliedProperties.spec.ts +95 -0
- package/metabrandsetting.json +0 -1
package/dist/articleStatus.d.ts
CHANGED
package/dist/articleStatus.js
CHANGED
|
@@ -13,7 +13,7 @@ const { QTY_TRANSACTION, QTY_STOCK, AMOUNT_STOCK, QTY_SHELF_STOCK, AMOUNT_SHELF_
|
|
|
13
13
|
// Derived fields
|
|
14
14
|
AMOUNT_SOLD_MAX, AMOUNT_SOLD_DISCOUNT, MAX_RECIEVE_TIMESTAMP, STOCK_TIME_PRODUCT, STOCKAMOUNT_TIME_PRODUCT, QTY_RETURN, AMOUNT_RETURN,
|
|
15
15
|
// Post aggregation fields
|
|
16
|
-
SELLOUT_PERCENTAGE, ROI, QTY_AVG_STOCK, VALUE_AVG_STOCK, QTY_TURNOVER_VELOCITY, AMOUNT_TURNOVER_VELOCITY, PROFITABILITY, MARGIN, PROFIT, QTY_END_SHELF_STOCK, AMOUNT_END_SHELF_STOCK, QTY_END_STOCK, AMOUNT_END_STOCK, RETURN_PERCENTAGE, QTY_SOLD_BEFORE_RETURNS, } = transaction_1.default.dbTransactionVector;
|
|
16
|
+
SELLOUT_PERCENTAGE, ROI, QTY_AVG_STOCK, VALUE_AVG_STOCK, QTY_TURNOVER_VELOCITY, AMOUNT_TURNOVER_VELOCITY, PROFITABILITY, MARGIN, PROFIT, QTY_END_SHELF_STOCK, AMOUNT_END_SHELF_STOCK, QTY_END_STOCK, AMOUNT_END_STOCK, RETURN_PERCENTAGE, QTY_SOLD_BEFORE_RETURNS, ROI_PERCENTAGE, } = transaction_1.default.dbTransactionVector;
|
|
17
17
|
// Vector length to allocate for aggregation
|
|
18
18
|
const VECTOR_LENGTH = 50;
|
|
19
19
|
const BEGIN_STOCK_VECTOR_START = QTY_STOCK;
|
|
@@ -290,6 +290,8 @@ function postAgg(v, timeFrame) {
|
|
|
290
290
|
v[MARGIN] = (v[PROFIT] / totalAmountSold) * 100;
|
|
291
291
|
v[RETURN_PERCENTAGE] = (v[QTY_RETURN] / v[QTY_RECIEVED]) * 100;
|
|
292
292
|
v[QTY_SOLD_BEFORE_RETURNS] = totalQtySold + Math.abs(v[QTY_RETURN]);
|
|
293
|
+
const investmentBase = v[AMOUNT_RECIEVED] - v[AMOUNT_TRANSIT];
|
|
294
|
+
v[ROI_PERCENTAGE] = investmentBase <= 0 ? NaN : ((v[ROI] + investmentBase) / investmentBase) * 100;
|
|
293
295
|
v[QTY_SOLD] = totalQtySold;
|
|
294
296
|
v[AMOUNT_SOLD_EXCL] = totalAmountSold;
|
|
295
297
|
v[COSTPRICE_SOLD] = totalCostSold;
|
|
@@ -522,6 +524,7 @@ exports.default = {
|
|
|
522
524
|
QTY_B2B_RETURN,
|
|
523
525
|
RETURN_PERCENTAGE,
|
|
524
526
|
ROI,
|
|
527
|
+
ROI_PERCENTAGE,
|
|
525
528
|
SELLOUT_PERCENTAGE,
|
|
526
529
|
STOCKAMOUNT_TIME_PRODUCT,
|
|
527
530
|
STOCK_TIME_PRODUCT,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SkuI } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Fills missing SKU fields from redundant sources (supplier mirrors, articleCode, id, etc.).
|
|
4
|
+
* Then sets UI-only `PRODUCT` to the clustering key (phase 1: same as `articleCodeSupplier` after normalization).
|
|
5
|
+
* Mutates the sku in place.
|
|
6
|
+
*/
|
|
7
|
+
export default function ensureImpliedProperties(sku: SkuI): void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Fills missing SKU fields from redundant sources (supplier mirrors, articleCode, id, etc.).
|
|
5
|
+
* Then sets UI-only `PRODUCT` to the clustering key (phase 1: same as `articleCodeSupplier` after normalization).
|
|
6
|
+
* Mutates the sku in place.
|
|
7
|
+
*/
|
|
8
|
+
function ensureImpliedProperties(sku) {
|
|
9
|
+
var _a;
|
|
10
|
+
if (!sku.articleGroupSupplier)
|
|
11
|
+
sku.articleGroupSupplier = sku.articleGroup;
|
|
12
|
+
if (!sku.collectionSupplier)
|
|
13
|
+
sku.collectionSupplier = sku.collection;
|
|
14
|
+
if (!sku.colorCodeSupplier)
|
|
15
|
+
sku.colorCodeSupplier = sku.colorCode;
|
|
16
|
+
if (!sku.sizeSupplier)
|
|
17
|
+
sku.sizeSupplier = sku.size;
|
|
18
|
+
if (!sku.brandSupplier)
|
|
19
|
+
sku.brandSupplier = sku.brand;
|
|
20
|
+
if (!sku.colorFamily && sku.colorSupplier)
|
|
21
|
+
sku.colorFamily = '' + sku.colorSupplier;
|
|
22
|
+
if (!sku.colorFamily && sku.colorDescription)
|
|
23
|
+
sku.colorFamily = '' + sku.colorDescription;
|
|
24
|
+
if (!sku.colorFamily && sku.mainColorDescription)
|
|
25
|
+
sku.colorFamily = '' + sku.mainColorDescription;
|
|
26
|
+
if (!sku.articleCodeSupplier)
|
|
27
|
+
sku.articleCodeSupplier = sku.articleCode;
|
|
28
|
+
if (!sku.size && sku.sizeSupplier)
|
|
29
|
+
sku.size = sku.sizeSupplier;
|
|
30
|
+
if (!sku.barcode)
|
|
31
|
+
sku.barcode = sku.id;
|
|
32
|
+
sku.PRODUCT = (_a = sku.articleCodeSupplier) !== null && _a !== void 0 ? _a : '';
|
|
33
|
+
}
|
|
34
|
+
exports.default = ensureImpliedProperties;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { default as deepCopy } from './deepCopy';
|
|
|
4
4
|
export { default as ean13 } from './ean13';
|
|
5
5
|
export { default as edifact } from './edifact';
|
|
6
6
|
export { default as ensureArray } from './ensureArray';
|
|
7
|
+
export { default as ensureImpliedProperties } from './ensureImpliedProperties';
|
|
7
8
|
export { default as findSkuByBarcode } from './findSkuByBarcode';
|
|
8
9
|
export { default as getBrandName } from './getBrandName';
|
|
9
10
|
export { default as getPreferedPropertyMappings } from './getPreferedPropertyMappings';
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.isAxiosError = exports.exponentialDelay = exports.axiosRetry = exports.createAxiosInstance = exports.lcAxios = exports.transaction = exports.sizeToMap = exports.round2 = exports.pivotTable = exports.isean13 = exports.imageBinder = exports.hasOnlyDigits = exports.hashBrand = exports.getPreferedPropertyMappings = exports.getBrandName = exports.findSkuByBarcode = exports.ensureArray = exports.edifact = exports.ean13 = exports.deepCopy = exports.buildPropertyMappingFn = exports.articleStatus = void 0;
|
|
20
|
+
exports.isAxiosError = exports.exponentialDelay = exports.axiosRetry = exports.createAxiosInstance = exports.lcAxios = exports.transaction = exports.sizeToMap = exports.round2 = exports.pivotTable = exports.isean13 = exports.imageBinder = exports.hasOnlyDigits = exports.hashBrand = exports.getPreferedPropertyMappings = exports.getBrandName = exports.findSkuByBarcode = exports.ensureImpliedProperties = exports.ensureArray = exports.edifact = exports.ean13 = exports.deepCopy = exports.buildPropertyMappingFn = exports.articleStatus = void 0;
|
|
21
21
|
var articleStatus_1 = require("./articleStatus");
|
|
22
22
|
Object.defineProperty(exports, "articleStatus", { enumerable: true, get: function () { return __importDefault(articleStatus_1).default; } });
|
|
23
23
|
var buildPropertyMappingFn_1 = require("./buildPropertyMappingFn");
|
|
@@ -30,6 +30,8 @@ var edifact_1 = require("./edifact");
|
|
|
30
30
|
Object.defineProperty(exports, "edifact", { enumerable: true, get: function () { return __importDefault(edifact_1).default; } });
|
|
31
31
|
var ensureArray_1 = require("./ensureArray");
|
|
32
32
|
Object.defineProperty(exports, "ensureArray", { enumerable: true, get: function () { return __importDefault(ensureArray_1).default; } });
|
|
33
|
+
var ensureImpliedProperties_1 = require("./ensureImpliedProperties");
|
|
34
|
+
Object.defineProperty(exports, "ensureImpliedProperties", { enumerable: true, get: function () { return __importDefault(ensureImpliedProperties_1).default; } });
|
|
33
35
|
var findSkuByBarcode_1 = require("./findSkuByBarcode");
|
|
34
36
|
Object.defineProperty(exports, "findSkuByBarcode", { enumerable: true, get: function () { return __importDefault(findSkuByBarcode_1).default; } });
|
|
35
37
|
var getBrandName_1 = require("./getBrandName");
|
package/dist/transaction.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ declare const _default: {
|
|
|
66
66
|
AMOUNT_END_STOCK: number;
|
|
67
67
|
RETURN_PERCENTAGE: number;
|
|
68
68
|
QTY_SOLD_BEFORE_RETURNS: number;
|
|
69
|
+
ROI_PERCENTAGE: number;
|
|
69
70
|
};
|
|
70
71
|
buildTransaction: (transaction: TransactionI) => dbTransactionI | undefined;
|
|
71
72
|
buildVector: (transaction: TransactionI) => Float64Array;
|
package/dist/transaction.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -131,6 +131,8 @@ interface SkuI {
|
|
|
131
131
|
IMAGES?: Array<ImageI>;
|
|
132
132
|
SIZES?: unknown;
|
|
133
133
|
FOOTPRINT?: number;
|
|
134
|
+
/** UI-only clustering key for product tiles / matrices; not persisted. Phase 1 mirrors articleCodeSupplier after ensureImpliedProperties. */
|
|
135
|
+
PRODUCT?: string;
|
|
134
136
|
quickPick?: number;
|
|
135
137
|
gln?: string;
|
|
136
138
|
set?: string;
|
|
@@ -225,9 +227,6 @@ interface BrandSettingI {
|
|
|
225
227
|
gln?: string;
|
|
226
228
|
ownerTenantId?: string;
|
|
227
229
|
orderMethods?: string[];
|
|
228
|
-
whiteListTenants?: string[];
|
|
229
|
-
associates?: object[];
|
|
230
|
-
authGroups?: string[];
|
|
231
230
|
propertyMapping?: PropertyMappingI[];
|
|
232
231
|
fashionCloudId?: string;
|
|
233
232
|
sizeSystemPrefix?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softwear/latestcollectioncore",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.165",
|
|
4
4
|
"description": "Core functions for LatestCollections applications",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
"build": "tsc -p tsconfig.json",
|
|
19
19
|
"build:watch": "tsc -p tsconfig.json --watch",
|
|
20
20
|
"test": "vitest run",
|
|
21
|
-
"test:watch": "vitest"
|
|
22
|
-
"dev": "concurrently \"npm:build:watch\" \"npm:test:watch\""
|
|
21
|
+
"test:watch": "vitest"
|
|
23
22
|
},
|
|
24
23
|
"repository": {
|
|
25
24
|
"type": "git",
|
|
@@ -33,7 +32,6 @@
|
|
|
33
32
|
"homepage": "https://gitlab.com/softwearconnect/latestcollectioncore#readme",
|
|
34
33
|
"devDependencies": {
|
|
35
34
|
"@types/node": "^18.11.17",
|
|
36
|
-
"concurrently": "^9.2.1",
|
|
37
35
|
"typescript": "^4.9.4",
|
|
38
36
|
"vitest": "^1.0.0"
|
|
39
37
|
},
|
package/src/articleStatus.ts
CHANGED
|
@@ -75,6 +75,7 @@ const {
|
|
|
75
75
|
AMOUNT_END_STOCK,
|
|
76
76
|
RETURN_PERCENTAGE,
|
|
77
77
|
QTY_SOLD_BEFORE_RETURNS,
|
|
78
|
+
ROI_PERCENTAGE,
|
|
78
79
|
} = transactionFunctions.dbTransactionVector
|
|
79
80
|
|
|
80
81
|
// Vector length to allocate for aggregation
|
|
@@ -375,6 +376,8 @@ function postAgg(v: any, timeFrame: number): void {
|
|
|
375
376
|
v[MARGIN] = (v[PROFIT] / totalAmountSold) * 100
|
|
376
377
|
v[RETURN_PERCENTAGE] = (v[QTY_RETURN] / v[QTY_RECIEVED]) * 100
|
|
377
378
|
v[QTY_SOLD_BEFORE_RETURNS] = totalQtySold + Math.abs(v[QTY_RETURN])
|
|
379
|
+
const investmentBase = v[AMOUNT_RECIEVED] - v[AMOUNT_TRANSIT]
|
|
380
|
+
v[ROI_PERCENTAGE] = investmentBase <= 0 ? NaN : ((v[ROI] + investmentBase) / investmentBase) * 100
|
|
378
381
|
v[QTY_SOLD] = totalQtySold
|
|
379
382
|
v[AMOUNT_SOLD_EXCL] = totalAmountSold
|
|
380
383
|
v[COSTPRICE_SOLD] = totalCostSold
|
|
@@ -616,6 +619,7 @@ export default {
|
|
|
616
619
|
QTY_B2B_RETURN,
|
|
617
620
|
RETURN_PERCENTAGE,
|
|
618
621
|
ROI,
|
|
622
|
+
ROI_PERCENTAGE,
|
|
619
623
|
SELLOUT_PERCENTAGE,
|
|
620
624
|
STOCKAMOUNT_TIME_PRODUCT,
|
|
621
625
|
STOCK_TIME_PRODUCT,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SkuI } from './types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fills missing SKU fields from redundant sources (supplier mirrors, articleCode, id, etc.).
|
|
5
|
+
* Then sets UI-only `PRODUCT` to the clustering key (phase 1: same as `articleCodeSupplier` after normalization).
|
|
6
|
+
* Mutates the sku in place.
|
|
7
|
+
*/
|
|
8
|
+
export default function ensureImpliedProperties(sku: SkuI): void {
|
|
9
|
+
if (!sku.articleGroupSupplier) sku.articleGroupSupplier = sku.articleGroup
|
|
10
|
+
if (!sku.collectionSupplier) sku.collectionSupplier = sku.collection
|
|
11
|
+
if (!sku.colorCodeSupplier) sku.colorCodeSupplier = sku.colorCode
|
|
12
|
+
if (!sku.sizeSupplier) sku.sizeSupplier = sku.size
|
|
13
|
+
if (!sku.brandSupplier) sku.brandSupplier = sku.brand
|
|
14
|
+
|
|
15
|
+
if (!sku.colorFamily && sku.colorSupplier) sku.colorFamily = '' + sku.colorSupplier
|
|
16
|
+
if (!sku.colorFamily && sku.colorDescription) sku.colorFamily = '' + sku.colorDescription
|
|
17
|
+
if (!sku.colorFamily && sku.mainColorDescription) sku.colorFamily = '' + sku.mainColorDescription
|
|
18
|
+
if (!sku.articleCodeSupplier) sku.articleCodeSupplier = sku.articleCode
|
|
19
|
+
if (!sku.size && sku.sizeSupplier) sku.size = sku.sizeSupplier
|
|
20
|
+
if (!sku.barcode) sku.barcode = sku.id
|
|
21
|
+
|
|
22
|
+
sku.PRODUCT = sku.articleCodeSupplier ?? ''
|
|
23
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { default as deepCopy } from './deepCopy'
|
|
|
4
4
|
export { default as ean13 } from './ean13'
|
|
5
5
|
export { default as edifact } from './edifact'
|
|
6
6
|
export { default as ensureArray } from './ensureArray'
|
|
7
|
+
export { default as ensureImpliedProperties } from './ensureImpliedProperties'
|
|
7
8
|
export { default as findSkuByBarcode } from './findSkuByBarcode'
|
|
8
9
|
export { default as getBrandName } from './getBrandName'
|
|
9
10
|
export { default as getPreferedPropertyMappings } from './getPreferedPropertyMappings'
|
package/src/transaction.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -140,6 +140,8 @@ interface SkuI {
|
|
|
140
140
|
IMAGES?: Array<ImageI>
|
|
141
141
|
SIZES?: unknown
|
|
142
142
|
FOOTPRINT?: number
|
|
143
|
+
/** UI-only clustering key for product tiles / matrices; not persisted. Phase 1 mirrors articleCodeSupplier after ensureImpliedProperties. */
|
|
144
|
+
PRODUCT?: string
|
|
143
145
|
quickPick?: number
|
|
144
146
|
gln?: string
|
|
145
147
|
set?: string
|
|
@@ -239,9 +241,6 @@ interface BrandSettingI {
|
|
|
239
241
|
gln?: string
|
|
240
242
|
ownerTenantId?: string
|
|
241
243
|
orderMethods?: string[]
|
|
242
|
-
whiteListTenants?: string[]
|
|
243
|
-
associates?: object[]
|
|
244
|
-
authGroups?: string[]
|
|
245
244
|
propertyMapping?: PropertyMappingI[]
|
|
246
245
|
fashionCloudId?: string
|
|
247
246
|
sizeSystemPrefix?: string
|
|
@@ -123,6 +123,9 @@ describe('articleStatus', () => {
|
|
|
123
123
|
it('QTY_SOLD_BEFORE_RETURNS should be 64', () => {
|
|
124
124
|
expect(articleStatus.QTY_SOLD_BEFORE_RETURNS).toBe(64)
|
|
125
125
|
})
|
|
126
|
+
it('ROI_PERCENTAGE should be 65', () => {
|
|
127
|
+
expect(articleStatus.ROI_PERCENTAGE).toBe(65)
|
|
128
|
+
})
|
|
126
129
|
it('AMOUNT_RETURN should be 49', () => {
|
|
127
130
|
expect(articleStatus.AMOUNT_RETURN).toBe(49)
|
|
128
131
|
})
|
|
@@ -414,5 +417,27 @@ describe('articleStatus', () => {
|
|
|
414
417
|
expect(dateRange.hrDay).toBe('2024-01-01')
|
|
415
418
|
expect(dateRange.timeFrame).toBe(367 * 24 * 3600 * 1000)
|
|
416
419
|
})
|
|
420
|
+
|
|
421
|
+
it('should calculate ROI percentage from post-aggregated values', () => {
|
|
422
|
+
const vector = new Array(articleStatus.ROI_PERCENTAGE + 1).fill(0)
|
|
423
|
+
vector[articleStatus.AMOUNT_RECIEVED] = 8700
|
|
424
|
+
vector[articleStatus.AMOUNT_SOLD_EXCL] = 5900
|
|
425
|
+
|
|
426
|
+
articleStatus.postAgg(vector, msYear)
|
|
427
|
+
|
|
428
|
+
expect(vector[articleStatus.ROI]).toBe(-2800)
|
|
429
|
+
expect(vector[articleStatus.ROI_PERCENTAGE]).toBeCloseTo(67.81609195402298, 10)
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
it('should set ROI percentage to NaN when investment base is zero or negative', () => {
|
|
433
|
+
const vector = new Array(articleStatus.ROI_PERCENTAGE + 1).fill(0)
|
|
434
|
+
vector[articleStatus.AMOUNT_RECIEVED] = 100
|
|
435
|
+
vector[articleStatus.AMOUNT_TRANSIT] = 100
|
|
436
|
+
vector[articleStatus.AMOUNT_SOLD_EXCL] = 150
|
|
437
|
+
|
|
438
|
+
articleStatus.postAgg(vector, msYear)
|
|
439
|
+
|
|
440
|
+
expect(Number.isNaN(vector[articleStatus.ROI_PERCENTAGE])).toBe(true)
|
|
441
|
+
})
|
|
417
442
|
})
|
|
418
443
|
})
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import ensureImpliedProperties from '../src/ensureImpliedProperties'
|
|
3
|
+
import type { SkuI } from '../src/types'
|
|
4
|
+
|
|
5
|
+
function baseSku(overrides: Partial<SkuI> = {}): SkuI {
|
|
6
|
+
return {
|
|
7
|
+
articleCode: 'AC-1',
|
|
8
|
+
articleDescription: 'Desc',
|
|
9
|
+
brand: 'BrandX',
|
|
10
|
+
colorFamily: 'Black',
|
|
11
|
+
size: 'M',
|
|
12
|
+
...overrides,
|
|
13
|
+
} as SkuI
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('ensureImpliedProperties', () => {
|
|
17
|
+
it('fills articleCodeSupplier from articleCode and sets PRODUCT to match', () => {
|
|
18
|
+
const sku = baseSku({ articleCode: 'SUP-99' })
|
|
19
|
+
delete (sku as { articleCodeSupplier?: string }).articleCodeSupplier
|
|
20
|
+
|
|
21
|
+
ensureImpliedProperties(sku)
|
|
22
|
+
|
|
23
|
+
expect(sku.articleCodeSupplier).toBe('SUP-99')
|
|
24
|
+
expect(sku.PRODUCT).toBe('SUP-99')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('sets PRODUCT from existing articleCodeSupplier without overwriting', () => {
|
|
28
|
+
const sku = baseSku({
|
|
29
|
+
articleCode: 'AC-1',
|
|
30
|
+
articleCodeSupplier: 'ALREADY-SET',
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
ensureImpliedProperties(sku)
|
|
34
|
+
|
|
35
|
+
expect(sku.articleCodeSupplier).toBe('ALREADY-SET')
|
|
36
|
+
expect(sku.PRODUCT).toBe('ALREADY-SET')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('sets barcode from id when barcode is missing', () => {
|
|
40
|
+
const sku = baseSku({
|
|
41
|
+
id: 'ID-12345',
|
|
42
|
+
barcode: undefined,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
ensureImpliedProperties(sku)
|
|
46
|
+
|
|
47
|
+
expect(sku.barcode).toBe('ID-12345')
|
|
48
|
+
expect(sku.PRODUCT).toBe('AC-1')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('fills colorFamily from colorSupplier when colorFamily is missing', () => {
|
|
52
|
+
const sku = baseSku({
|
|
53
|
+
colorFamily: undefined as unknown as string,
|
|
54
|
+
colorSupplier: 'Navy',
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
ensureImpliedProperties(sku)
|
|
58
|
+
|
|
59
|
+
expect(sku.colorFamily).toBe('Navy')
|
|
60
|
+
expect(sku.PRODUCT).toBe('AC-1')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('fills supplier mirror fields from primary fields', () => {
|
|
64
|
+
const sku = baseSku({
|
|
65
|
+
articleGroup: 'G1',
|
|
66
|
+
collection: 'C1',
|
|
67
|
+
colorCode: 'CC',
|
|
68
|
+
brand: 'B1',
|
|
69
|
+
})
|
|
70
|
+
delete (sku as { articleGroupSupplier?: string }).articleGroupSupplier
|
|
71
|
+
delete (sku as { collectionSupplier?: string }).collectionSupplier
|
|
72
|
+
delete (sku as { colorCodeSupplier?: string }).colorCodeSupplier
|
|
73
|
+
delete (sku as { brandSupplier?: string }).brandSupplier
|
|
74
|
+
|
|
75
|
+
ensureImpliedProperties(sku)
|
|
76
|
+
|
|
77
|
+
expect(sku.articleGroupSupplier).toBe('G1')
|
|
78
|
+
expect(sku.collectionSupplier).toBe('C1')
|
|
79
|
+
expect(sku.colorCodeSupplier).toBe('CC')
|
|
80
|
+
expect(sku.brandSupplier).toBe('B1')
|
|
81
|
+
expect(sku.PRODUCT).toBe('AC-1')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('sets PRODUCT to empty string when articleCodeSupplier is still missing after fallbacks', () => {
|
|
85
|
+
const sku = baseSku({
|
|
86
|
+
articleCode: '',
|
|
87
|
+
articleCodeSupplier: undefined,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
ensureImpliedProperties(sku)
|
|
91
|
+
|
|
92
|
+
expect(sku.articleCodeSupplier).toBe('')
|
|
93
|
+
expect(sku.PRODUCT).toBe('')
|
|
94
|
+
})
|
|
95
|
+
})
|