Merge remote-tracking branch 'origin/dev' into feature/inam-platform-core-setup
This commit is contained in:
@@ -33,7 +33,7 @@ router.get(
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['settings.integrations']),
|
||||
authorize(['settings.integrations', 'products.items']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
|
||||
@@ -291,6 +291,32 @@ export class ProductService {
|
||||
return formatProductResponse(json);
|
||||
}
|
||||
|
||||
async generateSku(family, finalCode, transaction) {
|
||||
let familyPrefix = 'PRD';
|
||||
if (family) {
|
||||
familyPrefix = (family.name || family.code || 'PRD')
|
||||
.toUpperCase()
|
||||
.replace(/[^A-Z0-9]/g, '')
|
||||
.substring(0, 4);
|
||||
if (!familyPrefix || familyPrefix.length < 2) familyPrefix = 'PRD';
|
||||
}
|
||||
|
||||
let runningSeq = '00001';
|
||||
if (family) {
|
||||
const familyProductCount = await models.Product.count({
|
||||
where: { family_id: family.id },
|
||||
transaction
|
||||
});
|
||||
runningSeq = String(familyProductCount + 1).padStart(5, '0');
|
||||
} else {
|
||||
const totalProductCount = await models.Product.count({
|
||||
transaction
|
||||
});
|
||||
runningSeq = String(totalProductCount + 1).padStart(5, '0');
|
||||
}
|
||||
return `${familyPrefix}-${finalCode}-${runningSeq}`;
|
||||
}
|
||||
|
||||
async create(data, context = {}) {
|
||||
const transaction = await sequelize.transaction();
|
||||
try {
|
||||
@@ -384,31 +410,6 @@ export class ProductService {
|
||||
}
|
||||
data.code = finalCode;
|
||||
|
||||
// 4b. Autogenerate Master SKU (FAMILY_PREFIX-PRODUCT_CODE-SEQUENCE)
|
||||
let familyPrefix = 'PRD';
|
||||
if (family) {
|
||||
familyPrefix = (family.name || family.code || 'PRD')
|
||||
.toUpperCase()
|
||||
.replace(/[^A-Z0-9]/g, '')
|
||||
.substring(0, 4);
|
||||
if (!familyPrefix || familyPrefix.length < 2) familyPrefix = 'PRD';
|
||||
}
|
||||
|
||||
let runningSeq = '00001';
|
||||
if (family) {
|
||||
const familyProductCount = await models.Product.count({
|
||||
where: { family_id: family.id },
|
||||
transaction
|
||||
});
|
||||
runningSeq = String(familyProductCount + 1).padStart(5, '0');
|
||||
} else {
|
||||
const totalProductCount = await models.Product.count({
|
||||
transaction
|
||||
});
|
||||
runningSeq = String(totalProductCount + 1).padStart(5, '0');
|
||||
}
|
||||
const generatedSku = `${familyPrefix}-${finalCode}-${runningSeq}`;
|
||||
|
||||
// Setup default inherited channels and workflows
|
||||
const metadata = data.metadata || {};
|
||||
if (!metadata.channels) {
|
||||
@@ -438,7 +439,12 @@ export class ProductService {
|
||||
metadata.currentStage = currentStage;
|
||||
|
||||
// Pack general form fields into metadata since they aren't core columns
|
||||
metadata.sku = generatedSku;
|
||||
const initialStatus = data.status || 'draft';
|
||||
if (initialStatus === 'pending') {
|
||||
metadata.sku = await this.generateSku(family, finalCode, transaction);
|
||||
} else {
|
||||
metadata.sku = null;
|
||||
}
|
||||
metadata.price = data.price || '';
|
||||
metadata.stock = data.stock !== undefined ? data.stock : 0;
|
||||
metadata.barcode = data.barcode || '';
|
||||
@@ -478,7 +484,7 @@ export class ProductService {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Array.isArray(family.attributes)) {
|
||||
if (family && Array.isArray(family.attributes)) {
|
||||
for (const a of family.attributes) {
|
||||
if (a && a.id) familyAttributesMap.set(a.id, a);
|
||||
}
|
||||
@@ -486,12 +492,14 @@ export class ProductService {
|
||||
|
||||
const attrKeys = typeof bodyAttributes === 'object' && bodyAttributes !== null ? Object.keys(bodyAttributes) : [];
|
||||
if (familyAttributesMap.size === 0 && attrKeys.length > 0) {
|
||||
const uuidKeys = attrKeys.filter(k => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(k));
|
||||
const orConditions = [{ code: attrKeys }];
|
||||
if (uuidKeys.length > 0) {
|
||||
orConditions.push({ id: uuidKeys });
|
||||
}
|
||||
const dbAttrs = await models.Attribute.findAll({
|
||||
where: {
|
||||
[Op.or]: [
|
||||
{ code: attrKeys },
|
||||
{ id: attrKeys }
|
||||
]
|
||||
[Op.or]: orConditions
|
||||
},
|
||||
transaction
|
||||
});
|
||||
@@ -644,6 +652,13 @@ export class ProductService {
|
||||
metadata.currentStage = record.metadata?.currentStage || 'draft';
|
||||
}
|
||||
|
||||
const oldStatus = record.status || record.metadata?.currentStage || 'draft';
|
||||
const newStatus = data.status || metadata.currentStage || oldStatus;
|
||||
|
||||
if (!metadata.sku && oldStatus === 'draft' && newStatus === 'pending') {
|
||||
metadata.sku = await this.generateSku(family, record.code, transaction);
|
||||
}
|
||||
|
||||
// Keep general fields inside metadata up to date
|
||||
if (data.hasOwnProperty('sku')) metadata.sku = data.sku;
|
||||
if (data.hasOwnProperty('price')) metadata.price = data.price;
|
||||
@@ -697,12 +712,14 @@ export class ProductService {
|
||||
|
||||
const attrKeys = typeof bodyAttributes === 'object' && bodyAttributes !== null ? Object.keys(bodyAttributes) : [];
|
||||
if (familyAttributesMap.size === 0 && attrKeys.length > 0) {
|
||||
const uuidKeys = attrKeys.filter(k => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(k));
|
||||
const orConditions = [{ code: attrKeys }];
|
||||
if (uuidKeys.length > 0) {
|
||||
orConditions.push({ id: uuidKeys });
|
||||
}
|
||||
const dbAttrs = await models.Attribute.findAll({
|
||||
where: {
|
||||
[Op.or]: [
|
||||
{ code: attrKeys },
|
||||
{ id: attrKeys }
|
||||
]
|
||||
[Op.or]: orConditions
|
||||
},
|
||||
transaction
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user