Add catalog option sets
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "CatalogProductTypeSetting" ADD COLUMN "colorOptions" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "labelOptions" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "lengthOptionsM" INTEGER[] DEFAULT ARRAY[]::INTEGER[],
|
||||
ADD COLUMN "sleeveOptions" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "thicknessOptionsMicron" INTEGER[] DEFAULT ARRAY[]::INTEGER[],
|
||||
ADD COLUMN "widthOptionsMm" INTEGER[] DEFAULT ARRAY[]::INTEGER[];
|
||||
-- AlterTable
|
||||
ALTER TABLE "CatalogProductTypeSetting" ADD COLUMN "colorOptions" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "labelOptions" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "lengthOptionsM" INTEGER[] DEFAULT ARRAY[]::INTEGER[],
|
||||
ADD COLUMN "sleeveOptions" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "thicknessOptionsMicron" INTEGER[] DEFAULT ARRAY[]::INTEGER[],
|
||||
ADD COLUMN "widthOptionsMm" INTEGER[] DEFAULT ARRAY[]::INTEGER[];
|
||||
@@ -200,6 +200,12 @@ model CatalogProductTypeSetting {
|
||||
customLengthStepM Int?
|
||||
allowCustomSleeveBrand Boolean @default(false)
|
||||
allowCustomLabel Boolean @default(false)
|
||||
widthOptionsMm Int[] @default([])
|
||||
lengthOptionsM Int[] @default([])
|
||||
thicknessOptionsMicron Int[] @default([])
|
||||
sleeveOptions String[] @default([])
|
||||
colorOptions String[] @default([])
|
||||
labelOptions String[] @default([])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
113
src/resolvers.js
113
src/resolvers.js
@@ -441,6 +441,57 @@ function presentCatalogProductTypeSetting(setting) {
|
||||
customLengthStepM: setting.customLengthStepM ?? null,
|
||||
allowCustomSleeveBrand: Boolean(setting.allowCustomSleeveBrand),
|
||||
allowCustomLabel: Boolean(setting.allowCustomLabel),
|
||||
widthOptionsMm: [...(setting.widthOptionsMm ?? [])],
|
||||
lengthOptionsM: [...(setting.lengthOptionsM ?? [])],
|
||||
thicknessOptionsMicron: [...(setting.thicknessOptionsMicron ?? [])],
|
||||
sleeveOptions: [...(setting.sleeveOptions ?? [])],
|
||||
colorOptions: [...(setting.colorOptions ?? [])],
|
||||
labelOptions: [...(setting.labelOptions ?? [])],
|
||||
};
|
||||
}
|
||||
|
||||
function normalizePositiveIntList(values) {
|
||||
return [...new Set((values ?? [])
|
||||
.map((value) => normalizeOptionalPositiveInt(value))
|
||||
.filter((value) => value !== null))]
|
||||
.sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
function normalizeTextList(values) {
|
||||
return [...new Set((values ?? [])
|
||||
.map((value) => normalizeText(value))
|
||||
.filter(Boolean))]
|
||||
.sort((a, b) => a.localeCompare(b, 'ru'));
|
||||
}
|
||||
|
||||
function collectProductTypeOptionDefaults(products) {
|
||||
const colorOptions = [];
|
||||
const labelOptions = [];
|
||||
|
||||
for (const product of products) {
|
||||
for (const tag of product.tags ?? []) {
|
||||
const normalizedTag = normalizeText(tag);
|
||||
if (!normalizedTag) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (['прозрачный', 'коричневый', 'белый', 'черный', 'желтый', 'зеленый', 'красный', 'синий', 'оранжевый', 'красно-белый'].includes(normalizedTag)) {
|
||||
colorOptions.push(normalizedTag);
|
||||
}
|
||||
|
||||
if (['хрупкое', 'подарок', 'акция'].includes(normalizedTag)) {
|
||||
labelOptions.push(normalizedTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
widthOptionsMm: normalizePositiveIntList(products.map((product) => product.widthMm)),
|
||||
lengthOptionsM: normalizePositiveIntList(products.map((product) => product.lengthM)),
|
||||
thicknessOptionsMicron: normalizePositiveIntList(products.map((product) => product.thicknessMicron)),
|
||||
sleeveOptions: normalizeTextList(products.map((product) => product.sleeveBrand)),
|
||||
colorOptions: normalizeTextList(colorOptions),
|
||||
labelOptions: normalizeTextList(labelOptions),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -474,6 +525,12 @@ function normalizeCatalogProductTypeSettingInput(input) {
|
||||
customLengthStepM,
|
||||
allowCustomSleeveBrand: Boolean(input.allowCustomSleeveBrand),
|
||||
allowCustomLabel: Boolean(input.allowCustomLabel),
|
||||
widthOptionsMm: normalizePositiveIntList(input.widthOptionsMm),
|
||||
lengthOptionsM: normalizePositiveIntList(input.lengthOptionsM),
|
||||
thicknessOptionsMicron: normalizePositiveIntList(input.thicknessOptionsMicron),
|
||||
sleeveOptions: normalizeTextList(input.sleeveOptions),
|
||||
colorOptions: normalizeTextList(input.colorOptions),
|
||||
labelOptions: normalizeTextList(input.labelOptions),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -486,34 +543,60 @@ async function listCatalogProductTypeSettings(prisma) {
|
||||
productType: null,
|
||||
},
|
||||
},
|
||||
select: { productType: true },
|
||||
distinct: ['productType'],
|
||||
orderBy: { productType: 'asc' },
|
||||
select: {
|
||||
productType: true,
|
||||
widthMm: true,
|
||||
lengthM: true,
|
||||
thicknessMicron: true,
|
||||
sleeveBrand: true,
|
||||
tags: true,
|
||||
},
|
||||
orderBy: [{ productType: 'asc' }, { name: 'asc' }],
|
||||
}),
|
||||
prisma.catalogProductTypeSetting.findMany({
|
||||
orderBy: { productType: 'asc' },
|
||||
}),
|
||||
]);
|
||||
|
||||
const productsByType = new Map();
|
||||
for (const product of products) {
|
||||
const productType = normalizeText(product.productType);
|
||||
if (!productType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const existing = productsByType.get(productType);
|
||||
if (existing) {
|
||||
existing.push(product);
|
||||
} else {
|
||||
productsByType.set(productType, [product]);
|
||||
}
|
||||
}
|
||||
|
||||
const productTypes = new Set([
|
||||
...products.map((item) => normalizeText(item.productType)).filter(Boolean),
|
||||
...productsByType.keys(),
|
||||
...persistedSettings.map((item) => item.productType),
|
||||
]);
|
||||
const settingsByType = new Map(persistedSettings.map((item) => [item.productType, item]));
|
||||
|
||||
return [...productTypes]
|
||||
.sort((a, b) => a.localeCompare(b, 'ru'))
|
||||
.map((productType) => presentCatalogProductTypeSetting({
|
||||
productType,
|
||||
showQuantityPerBox: false,
|
||||
allowCustomLength: false,
|
||||
customLengthMinM: null,
|
||||
customLengthMaxM: null,
|
||||
customLengthStepM: null,
|
||||
allowCustomSleeveBrand: false,
|
||||
allowCustomLabel: false,
|
||||
...settingsByType.get(productType),
|
||||
}));
|
||||
.map((productType) => {
|
||||
const persisted = settingsByType.get(productType);
|
||||
const fallbackOptions = collectProductTypeOptionDefaults(productsByType.get(productType) ?? []);
|
||||
|
||||
return presentCatalogProductTypeSetting(persisted ?? {
|
||||
productType,
|
||||
showQuantityPerBox: false,
|
||||
allowCustomLength: false,
|
||||
customLengthMinM: null,
|
||||
customLengthMaxM: null,
|
||||
customLengthStepM: null,
|
||||
allowCustomSleeveBrand: false,
|
||||
allowCustomLabel: false,
|
||||
...fallbackOptions,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const cartInclude = {
|
||||
|
||||
@@ -257,6 +257,12 @@ type CatalogProductTypeSetting {
|
||||
customLengthStepM: Int
|
||||
allowCustomSleeveBrand: Boolean!
|
||||
allowCustomLabel: Boolean!
|
||||
widthOptionsMm: [Int!]!
|
||||
lengthOptionsM: [Int!]!
|
||||
thicknessOptionsMicron: [Int!]!
|
||||
sleeveOptions: [String!]!
|
||||
colorOptions: [String!]!
|
||||
labelOptions: [String!]!
|
||||
}
|
||||
|
||||
type CartItem {
|
||||
@@ -512,6 +518,12 @@ input UpsertCatalogProductTypeSettingInput {
|
||||
customLengthStepM: Int
|
||||
allowCustomSleeveBrand: Boolean!
|
||||
allowCustomLabel: Boolean!
|
||||
widthOptionsMm: [Int!]!
|
||||
lengthOptionsM: [Int!]!
|
||||
thicknessOptionsMicron: [Int!]!
|
||||
sleeveOptions: [String!]!
|
||||
colorOptions: [String!]!
|
||||
labelOptions: [String!]!
|
||||
}
|
||||
|
||||
input ReadyOrderItemInput {
|
||||
|
||||
Reference in New Issue
Block a user