rerobe-js-orm 4.5.0 → 4.5.1
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.
|
@@ -3,6 +3,7 @@ import Product from '../../models/Product';
|
|
|
3
3
|
export default class ProductFormState extends FormState {
|
|
4
4
|
fields: ProductFormFields;
|
|
5
5
|
props: CompleteProduct;
|
|
6
|
+
private variantAxes?;
|
|
6
7
|
opts: {
|
|
7
8
|
featuredCollectionOpts: {
|
|
8
9
|
label: string;
|
|
@@ -59,8 +60,41 @@ export default class ProductFormState extends FormState {
|
|
|
59
60
|
private discountValueChangeHandler;
|
|
60
61
|
private calculateSalePrice;
|
|
61
62
|
private inventoryLocationsChangeHandler;
|
|
62
|
-
private
|
|
63
|
+
private isSameOptions;
|
|
64
|
+
private getExistingVariantByOptions;
|
|
63
65
|
private variantInventoryChangeHandler;
|
|
66
|
+
setVariantAxes(axes?: {
|
|
67
|
+
[axis: string]: string[];
|
|
68
|
+
}): void;
|
|
69
|
+
generateVariantsFromAxes(defaults?: Partial<VariantInventory>): void;
|
|
70
|
+
addAxis(axis: string): void;
|
|
71
|
+
removeAxis(axis: string): void;
|
|
72
|
+
addAxisValue(axis: string, value: string): void;
|
|
73
|
+
removeAxisValue(axis: string, value: string): void;
|
|
74
|
+
reorderAxes(order: string[]): void;
|
|
75
|
+
upsertVariantByOptions(options: {
|
|
76
|
+
[k: string]: string;
|
|
77
|
+
}, patch: Partial<VariantInventory>): void;
|
|
78
|
+
removeVariantByOptions(options: {
|
|
79
|
+
[k: string]: string;
|
|
80
|
+
}): void;
|
|
81
|
+
findVariantByOptions(options: {
|
|
82
|
+
[k: string]: string;
|
|
83
|
+
}): VariantInventory | undefined;
|
|
84
|
+
validateAxes(axes: {
|
|
85
|
+
[axis: string]: string[];
|
|
86
|
+
}): {
|
|
87
|
+
ok: boolean;
|
|
88
|
+
errors: string[];
|
|
89
|
+
};
|
|
90
|
+
diffVariantsFromAxes(nextAxes: {
|
|
91
|
+
[axis: string]: string[];
|
|
92
|
+
}): {
|
|
93
|
+
toAdd: {
|
|
94
|
+
[k: string]: string;
|
|
95
|
+
}[];
|
|
96
|
+
toRemove: string[];
|
|
97
|
+
};
|
|
64
98
|
private aggregateInventoryLocationsFromVariants;
|
|
65
99
|
private fieldFactory;
|
|
66
100
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
14
|
const FormState_1 = require("../FormState");
|
|
4
15
|
const options_1 = require("./options");
|
|
@@ -571,39 +582,55 @@ class ProductFormState extends FormState_1.default {
|
|
|
571
582
|
this.multiSelectChangeHandler('inventoryLocations', val);
|
|
572
583
|
}
|
|
573
584
|
}
|
|
574
|
-
|
|
575
|
-
const
|
|
576
|
-
|
|
585
|
+
isSameOptions(a = {}, b = {}) {
|
|
586
|
+
const aKeys = Object.keys(a || {});
|
|
587
|
+
const bKeys = Object.keys(b || {});
|
|
588
|
+
if (aKeys.length !== bKeys.length)
|
|
589
|
+
return false;
|
|
590
|
+
return aKeys.every((k) => String(a[k]) === String(b[k]));
|
|
591
|
+
}
|
|
592
|
+
getExistingVariantByOptions(options = {}) {
|
|
593
|
+
var _a;
|
|
594
|
+
return ((_a = this.fields.variantInventory) === null || _a === void 0 ? void 0 : _a.selectedValues).find((v) => this.isSameOptions(v.options, options));
|
|
577
595
|
}
|
|
578
596
|
variantInventoryChangeHandler(val) {
|
|
597
|
+
var _a;
|
|
579
598
|
const numAxes = (val === null || val === void 0 ? void 0 : val.options) ? Object.keys(val.options).length : 0;
|
|
580
599
|
if (numAxes > 3) {
|
|
581
600
|
return; // silently ignore invalid (>3 axes)
|
|
582
601
|
}
|
|
583
|
-
const id = (val === null || val === void 0 ? void 0 : val.id) ||
|
|
602
|
+
const id = (val === null || val === void 0 ? void 0 : val.id) ||
|
|
603
|
+
((val === null || val === void 0 ? void 0 : val.options) ? (_a = this.getExistingVariantByOptions(val.options)) === null || _a === void 0 ? void 0 : _a.id : undefined) ||
|
|
604
|
+
this.utilities.makeRandId(28);
|
|
605
|
+
const existingInd = this.fields.variantInventory.selectedValues.findIndex((i) => i.id === id);
|
|
606
|
+
const existing = existingInd !== -1 ? this.fields.variantInventory.selectedValues[existingInd] : {};
|
|
584
607
|
const next = {
|
|
585
608
|
id,
|
|
586
|
-
options: val.options || {},
|
|
587
|
-
locations: val === null || val === void 0 ? void 0 : val.locations,
|
|
609
|
+
options: val.options || existing.options || {},
|
|
610
|
+
locations: (val === null || val === void 0 ? void 0 : val.locations) !== undefined ? val.locations : existing.locations,
|
|
611
|
+
price: (val === null || val === void 0 ? void 0 : val.price) !== undefined ? val.price : existing.price,
|
|
612
|
+
compareAtPrice: (val === null || val === void 0 ? void 0 : val.compareAtPrice) !== undefined ? val.compareAtPrice : existing.compareAtPrice,
|
|
613
|
+
salePrice: (val === null || val === void 0 ? void 0 : val.salePrice) !== undefined ? val.salePrice : existing.salePrice,
|
|
614
|
+
isOnSale: (val === null || val === void 0 ? void 0 : val.isOnSale) !== undefined ? val.isOnSale : existing.isOnSale,
|
|
615
|
+
sku: (val === null || val === void 0 ? void 0 : val.sku) !== undefined ? val.sku : existing.sku,
|
|
616
|
+
taxable: (val === null || val === void 0 ? void 0 : val.taxable) !== undefined ? val.taxable : existing.taxable,
|
|
588
617
|
};
|
|
589
|
-
const
|
|
590
|
-
if (
|
|
591
|
-
const foundInd = this.fields.variantInventory.selectedValues.findIndex((i) => i.id === id);
|
|
618
|
+
const foundInd = this.fields.variantInventory.selectedValues.findIndex((i) => i.id === id);
|
|
619
|
+
if (foundInd !== -1) {
|
|
592
620
|
const foundI = this.fields.variantInventory.selectedValues[foundInd];
|
|
593
|
-
|
|
621
|
+
let shouldToggleRemove = false;
|
|
622
|
+
if ((val === null || val === void 0 ? void 0 : val.locations) !== undefined) {
|
|
594
623
|
const norm = (arr = []) => [...arr]
|
|
595
624
|
.filter((l) => l && l.id)
|
|
596
625
|
.sort((a, b) => (a.id > b.id ? 1 : a.id < b.id ? -1 : 0))
|
|
597
626
|
.map((l) => `${l.id}:${Number(l.availableAmount) || 0}:${Number(l.incomingAmount) || 0}`)
|
|
598
627
|
.join('|');
|
|
599
|
-
|
|
600
|
-
}
|
|
601
|
-
if (
|
|
602
|
-
// same locations => toggle remove
|
|
628
|
+
shouldToggleRemove = norm(foundI.locations) === norm(next.locations);
|
|
629
|
+
}
|
|
630
|
+
if (shouldToggleRemove) {
|
|
603
631
|
this.fields.variantInventory.selectedValues.splice(foundInd, 1);
|
|
604
632
|
}
|
|
605
633
|
else {
|
|
606
|
-
// update quantity/options
|
|
607
634
|
this.fields.variantInventory.selectedValues.splice(foundInd, 1, next);
|
|
608
635
|
}
|
|
609
636
|
}
|
|
@@ -621,6 +648,195 @@ class ProductFormState extends FormState_1.default {
|
|
|
621
648
|
// aggregate main inventoryLocations from variant locations (sum by location id)
|
|
622
649
|
this.aggregateInventoryLocationsFromVariants();
|
|
623
650
|
}
|
|
651
|
+
// Public: define axes (≤3) for generating combinations
|
|
652
|
+
setVariantAxes(axes = {}) {
|
|
653
|
+
const axisKeys = Object.keys(axes || {});
|
|
654
|
+
if (axisKeys.length > 3) {
|
|
655
|
+
// trim to first 3 axes to enforce limit
|
|
656
|
+
this.variantAxes = axisKeys.slice(0, 3).reduce((acc, k) => {
|
|
657
|
+
acc[k] = Array.from(new Set((axes[k] || []).map((v) => String(v).trim()).filter(Boolean)));
|
|
658
|
+
return acc;
|
|
659
|
+
}, {});
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
this.variantAxes = axisKeys.reduce((acc, k) => {
|
|
663
|
+
acc[k] = Array.from(new Set((axes[k] || []).map((v) => String(v).trim()).filter(Boolean)));
|
|
664
|
+
return acc;
|
|
665
|
+
}, {});
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
// Public: regenerate variants from axes, preserving existing per-variant fields where options match
|
|
669
|
+
generateVariantsFromAxes(defaults = {}) {
|
|
670
|
+
const axes = this.variantAxes || {};
|
|
671
|
+
const axisKeys = Object.keys(axes);
|
|
672
|
+
if (axisKeys.length === 0) {
|
|
673
|
+
this.fields.variantInventory.selectedValues = [];
|
|
674
|
+
this.fields.variantInventory.valid = false;
|
|
675
|
+
this.aggregateInventoryLocationsFromVariants();
|
|
676
|
+
this.fields.quantity.inputValue = 0;
|
|
677
|
+
this.fields.availableForSale.selectedValue = false;
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const cartesian = (keys, idx, cur, out) => {
|
|
681
|
+
if (idx >= keys.length) {
|
|
682
|
+
out.push(Object.assign({}, cur));
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
const key = keys[idx];
|
|
686
|
+
const values = axes[key] || [];
|
|
687
|
+
values.forEach((v) => {
|
|
688
|
+
cartesian(keys, idx + 1, Object.assign(Object.assign({}, cur), { [key]: v }), out);
|
|
689
|
+
});
|
|
690
|
+
};
|
|
691
|
+
const combos = [];
|
|
692
|
+
cartesian(axisKeys, 0, {}, combos);
|
|
693
|
+
const regenerated = combos.map((opts) => {
|
|
694
|
+
var _a, _b, _c, _d, _e, _f;
|
|
695
|
+
const prev = this.getExistingVariantByOptions(opts);
|
|
696
|
+
const id = (prev === null || prev === void 0 ? void 0 : prev.id) || this.utilities.makeRandId(28);
|
|
697
|
+
const merged = {
|
|
698
|
+
id,
|
|
699
|
+
options: opts,
|
|
700
|
+
locations: (prev === null || prev === void 0 ? void 0 : prev.locations) || defaults.locations,
|
|
701
|
+
price: (_a = prev === null || prev === void 0 ? void 0 : prev.price) !== null && _a !== void 0 ? _a : defaults.price,
|
|
702
|
+
compareAtPrice: (_b = prev === null || prev === void 0 ? void 0 : prev.compareAtPrice) !== null && _b !== void 0 ? _b : defaults.compareAtPrice,
|
|
703
|
+
salePrice: (_c = prev === null || prev === void 0 ? void 0 : prev.salePrice) !== null && _c !== void 0 ? _c : defaults.salePrice,
|
|
704
|
+
isOnSale: (_d = prev === null || prev === void 0 ? void 0 : prev.isOnSale) !== null && _d !== void 0 ? _d : defaults.isOnSale,
|
|
705
|
+
sku: (_e = prev === null || prev === void 0 ? void 0 : prev.sku) !== null && _e !== void 0 ? _e : defaults.sku,
|
|
706
|
+
taxable: (_f = prev === null || prev === void 0 ? void 0 : prev.taxable) !== null && _f !== void 0 ? _f : defaults.taxable,
|
|
707
|
+
};
|
|
708
|
+
return merged;
|
|
709
|
+
});
|
|
710
|
+
this.fields.variantInventory.selectedValues = regenerated;
|
|
711
|
+
this.fields.variantInventory.valid = regenerated.length > 0;
|
|
712
|
+
// Aggregate quantity and master locations
|
|
713
|
+
const totalQty = regenerated.reduce((acc, cur) => {
|
|
714
|
+
const locs = cur.locations;
|
|
715
|
+
const sum = Array.isArray(locs) ? locs.reduce((a, l) => a + (Number(l === null || l === void 0 ? void 0 : l.availableAmount) || 0), 0) : 0;
|
|
716
|
+
return acc + sum;
|
|
717
|
+
}, 0);
|
|
718
|
+
this.fields.quantity.inputValue = totalQty;
|
|
719
|
+
this.fields.availableForSale.selectedValue = totalQty > 0;
|
|
720
|
+
this.aggregateInventoryLocationsFromVariants();
|
|
721
|
+
}
|
|
722
|
+
// Convenience helpers for UI
|
|
723
|
+
addAxis(axis) {
|
|
724
|
+
const k = String(axis).trim();
|
|
725
|
+
if (!k)
|
|
726
|
+
return;
|
|
727
|
+
const current = this.variantAxes || {};
|
|
728
|
+
if (Object.keys(current).includes(k))
|
|
729
|
+
return;
|
|
730
|
+
const nextKeys = Object.keys(current).concat(k).slice(0, 3);
|
|
731
|
+
const next = {};
|
|
732
|
+
nextKeys.forEach((key) => (next[key] = current[key] || []));
|
|
733
|
+
if (!next[k])
|
|
734
|
+
next[k] = [];
|
|
735
|
+
this.variantAxes = next;
|
|
736
|
+
}
|
|
737
|
+
removeAxis(axis) {
|
|
738
|
+
const current = this.variantAxes || {};
|
|
739
|
+
if (!current[axis])
|
|
740
|
+
return;
|
|
741
|
+
const _a = current, _b = axis, _ = _a[_b], rest = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
|
|
742
|
+
this.variantAxes = rest;
|
|
743
|
+
// remove affected variants by regenerating from remaining axes
|
|
744
|
+
this.generateVariantsFromAxes();
|
|
745
|
+
}
|
|
746
|
+
addAxisValue(axis, value) {
|
|
747
|
+
const current = this.variantAxes || {};
|
|
748
|
+
if (!current[axis])
|
|
749
|
+
current[axis] = [];
|
|
750
|
+
const val = String(value).trim();
|
|
751
|
+
if (!val)
|
|
752
|
+
return;
|
|
753
|
+
if (!current[axis].includes(val))
|
|
754
|
+
current[axis].push(val);
|
|
755
|
+
this.variantAxes = current;
|
|
756
|
+
this.generateVariantsFromAxes();
|
|
757
|
+
}
|
|
758
|
+
removeAxisValue(axis, value) {
|
|
759
|
+
const current = this.variantAxes || {};
|
|
760
|
+
if (!current[axis])
|
|
761
|
+
return;
|
|
762
|
+
const val = String(value).trim();
|
|
763
|
+
current[axis] = current[axis].filter((v) => v !== val);
|
|
764
|
+
this.variantAxes = current;
|
|
765
|
+
this.generateVariantsFromAxes();
|
|
766
|
+
}
|
|
767
|
+
reorderAxes(order) {
|
|
768
|
+
const current = this.variantAxes || {};
|
|
769
|
+
const keys = order.filter((k) => current[k]).slice(0, 3);
|
|
770
|
+
const rest = Object.keys(current)
|
|
771
|
+
.filter((k) => !keys.includes(k))
|
|
772
|
+
.slice(0, Math.max(0, 3 - keys.length));
|
|
773
|
+
const nextOrder = keys.concat(rest);
|
|
774
|
+
const next = {};
|
|
775
|
+
nextOrder.forEach((k) => (next[k] = current[k]));
|
|
776
|
+
this.variantAxes = next;
|
|
777
|
+
// No regen required; only presentation order
|
|
778
|
+
}
|
|
779
|
+
upsertVariantByOptions(options, patch) {
|
|
780
|
+
const prev = this.getExistingVariantByOptions(options);
|
|
781
|
+
const id = (prev === null || prev === void 0 ? void 0 : prev.id) || this.utilities.makeRandId(28);
|
|
782
|
+
this.variantInventoryChangeHandler(Object.assign({ id,
|
|
783
|
+
options }, patch));
|
|
784
|
+
}
|
|
785
|
+
removeVariantByOptions(options) {
|
|
786
|
+
const prev = this.getExistingVariantByOptions(options);
|
|
787
|
+
if (!prev)
|
|
788
|
+
return;
|
|
789
|
+
const ind = this.fields.variantInventory.selectedValues.findIndex((v) => v.id === prev.id);
|
|
790
|
+
if (ind !== -1) {
|
|
791
|
+
this.fields.variantInventory.selectedValues.splice(ind, 1);
|
|
792
|
+
// re-aggregate
|
|
793
|
+
const totalQty = this.fields.variantInventory.selectedValues.reduce((acc, cur) => {
|
|
794
|
+
const locs = cur.locations;
|
|
795
|
+
const sum = Array.isArray(locs) ? locs.reduce((a, l) => a + (Number(l === null || l === void 0 ? void 0 : l.availableAmount) || 0), 0) : 0;
|
|
796
|
+
return acc + sum;
|
|
797
|
+
}, 0);
|
|
798
|
+
this.fields.quantity.inputValue = totalQty;
|
|
799
|
+
this.fields.availableForSale.selectedValue = totalQty > 0;
|
|
800
|
+
this.aggregateInventoryLocationsFromVariants();
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
findVariantByOptions(options) {
|
|
804
|
+
return this.getExistingVariantByOptions(options);
|
|
805
|
+
}
|
|
806
|
+
validateAxes(axes) {
|
|
807
|
+
const errors = [];
|
|
808
|
+
const keys = Object.keys(axes || {});
|
|
809
|
+
if (keys.length > 3)
|
|
810
|
+
errors.push('Too many axes (max 3).');
|
|
811
|
+
keys.forEach((k) => {
|
|
812
|
+
const vals = axes[k] || [];
|
|
813
|
+
const clean = vals.map((v) => String(v).trim()).filter(Boolean);
|
|
814
|
+
if (clean.length !== vals.length)
|
|
815
|
+
errors.push(`Axis "${k}" has empty/invalid values.`);
|
|
816
|
+
});
|
|
817
|
+
return { ok: errors.length === 0, errors };
|
|
818
|
+
}
|
|
819
|
+
diffVariantsFromAxes(nextAxes) {
|
|
820
|
+
const curRows = this.fields.variantInventory.selectedValues || [];
|
|
821
|
+
const curKeySet = new Set(curRows.map((r) => JSON.stringify(r.options || {})));
|
|
822
|
+
// build combos for nextAxes
|
|
823
|
+
const keys = Object.keys(nextAxes || {});
|
|
824
|
+
const out = [];
|
|
825
|
+
const cart = (i, acc) => {
|
|
826
|
+
if (i >= keys.length) {
|
|
827
|
+
out.push(Object.assign({}, acc));
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
const k = keys[i];
|
|
831
|
+
const vals = nextAxes[k] || [];
|
|
832
|
+
vals.forEach((v) => cart(i + 1, Object.assign(Object.assign({}, acc), { [k]: v })));
|
|
833
|
+
};
|
|
834
|
+
cart(0, {});
|
|
835
|
+
const nextKeySet = new Set(out.map((o) => JSON.stringify(o)));
|
|
836
|
+
const toAdd = out.filter((o) => !curKeySet.has(JSON.stringify(o)));
|
|
837
|
+
const toRemove = curRows.filter((r) => !nextKeySet.has(JSON.stringify(r.options || {}))).map((r) => r.id);
|
|
838
|
+
return { toAdd, toRemove };
|
|
839
|
+
}
|
|
624
840
|
aggregateInventoryLocationsFromVariants() {
|
|
625
841
|
var _a;
|
|
626
842
|
const variants = ((_a = this.fields.variantInventory) === null || _a === void 0 ? void 0 : _a.selectedValues) || [];
|