u
This commit is contained in:
@@ -95,6 +95,11 @@ Creates a new article under a given parent category, allocating a SKU and a defa
|
|||||||
| `input.googleAuthId` | `number` | The id of the Google auth user. |
|
| `input.googleAuthId` | `number` | The id of the Google auth user. |
|
||||||
| `input.parentId` | `number` | The id of the parent category. |
|
| `input.parentId` | `number` | The id of the parent category. |
|
||||||
| `input.name` | `string` | The article name. |
|
| `input.name` | `string` | The article name. |
|
||||||
|
| `[input.description]` | `string` | The article description. |
|
||||||
|
| `[input.desc]` | `string` | Alias for description. |
|
||||||
|
| `[input.seo]` | `object|string` | The SEO configuration or JSON string. |
|
||||||
|
| `[input.seoTitle]` | `string` | The SEO title. |
|
||||||
|
| `[input.seoDescription]` | `string` | The SEO meta description. |
|
||||||
| `[input.track_stock=true]` | `boolean|number` | Whether inventory stock is tracked. |
|
| `[input.track_stock=true]` | `boolean|number` | Whether inventory stock is tracked. |
|
||||||
| `[tx]` | `object` | Optional transaction to run within. |
|
| `[tx]` | `object` | Optional transaction to run within. |
|
||||||
|
|
||||||
@@ -184,7 +189,7 @@ Returns the full detail of an article by its SKU, including unit, brand, categor
|
|||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
|
|
||||||
`Promise<{article: {id: number, sku: string, name: string, slug: string, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, price: {net: number, taxId: number, taxRate?: number}|null}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>` — The full article detail.
|
`Promise<{article: {id: number, sku: string, name: string, slug: string, description: string|null, seo: string|null, seoTitle: string|null, seoDescription: string|null, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, price: {net: number, taxId: number, taxRate?: number}|null}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>` — The full article detail.
|
||||||
|
|
||||||
**Throws**
|
**Throws**
|
||||||
|
|
||||||
@@ -664,6 +669,11 @@ Updates an article's name and/or unit (SI and amount), recording history.
|
|||||||
| `sku` | `string` | The article SKU. |
|
| `sku` | `string` | The article SKU. |
|
||||||
| `patch` | `object` | The update patch. |
|
| `patch` | `object` | The update patch. |
|
||||||
| `[patch.name]` | `string` | The new article name. |
|
| `[patch.name]` | `string` | The new article name. |
|
||||||
|
| `[patch.description]` | `string` | The article description. |
|
||||||
|
| `[patch.desc]` | `string` | Alias for description. |
|
||||||
|
| `[patch.seo]` | `object|string` | The SEO configuration or JSON string. |
|
||||||
|
| `[patch.seoTitle]` | `string` | The SEO title. |
|
||||||
|
| `[patch.seoDescription]` | `string` | The SEO meta description. |
|
||||||
| `[patch.unitSi]` | `string` | The new unit SI code. |
|
| `[patch.unitSi]` | `string` | The new unit SI code. |
|
||||||
| `[patch.unitamount]` | `number` | The new unit amount (must be > 0). |
|
| `[patch.unitamount]` | `number` | The new unit amount (must be > 0). |
|
||||||
| `[patch.track_stock]` | `boolean|number` | Whether inventory stock is tracked. |
|
| `[patch.track_stock]` | `boolean|number` | Whether inventory stock is tracked. |
|
||||||
|
|||||||
6
API.md
6
API.md
@@ -88,10 +88,10 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
|
|||||||
- `addChild(googleAuthId: number, parentSku: string, options: {attach?: boolean, attributeValueId?: number, value?: string, name?: string, unitamount?: number, weight?: number, track_stock?: boolean|number}, tx?: object): Promise<object>`
|
- `addChild(googleAuthId: number, parentSku: string, options: {attach?: boolean, attributeValueId?: number, value?: string, name?: string, unitamount?: number, weight?: number, track_stock?: boolean|number}, tx?: object): Promise<object>`
|
||||||
- `addImage(googleAuthId: number, sku: string, image: Buffer, tx?: object): Promise<{picId: number, sort: number, full: {w: number, h: number, size: number}, thumb: {w: number, h: number}, fullHash: string, thumbHash: string}>`
|
- `addImage(googleAuthId: number, sku: string, image: Buffer, tx?: object): Promise<{picId: number, sort: number, full: {w: number, h: number, size: number}, thumb: {w: number, h: number}, fullHash: string, thumbHash: string}>`
|
||||||
- `attachChild(googleAuthId: number, parentSku: string, options: {sku: string, childSku?: string, attributeValueId?: number, value?: string, reparent?: boolean, unitamount?: number, weight?: number, track_stock?: boolean|number}, tx?: object): Promise<{article: object, children: Array<object>}>`
|
- `attachChild(googleAuthId: number, parentSku: string, options: {sku: string, childSku?: string, attributeValueId?: number, value?: string, reparent?: boolean, unitamount?: number, weight?: number, track_stock?: boolean|number}, tx?: object): Promise<{article: object, children: Array<object>}>`
|
||||||
- `createUnderParent(input: {googleAuthId: number, parentId: number, name: string, track_stock?: boolean|number}, tx?: object): Promise<{id: number, parentId: number, name: string, sku: string, track_stock: boolean}>`
|
- `createUnderParent(input: {googleAuthId: number, parentId: number, name: string, description?: string, desc?: string, seo?: object|string, seoTitle?: string, seoDescription?: string, track_stock?: boolean|number}, tx?: object): Promise<{id: number, parentId: number, name: string, sku: string, track_stock: boolean}>`
|
||||||
- `delete(googleAuthId: number, sku: string, optionsOrTx?: object|*, maybeTx?: object): Promise<void>`
|
- `delete(googleAuthId: number, sku: string, optionsOrTx?: object|*, maybeTx?: object): Promise<void>`
|
||||||
- `deleteImage(googleAuthId: number, sku: string, fullHash: string, tx?: object): Promise<void>`
|
- `deleteImage(googleAuthId: number, sku: string, fullHash: string, tx?: object): Promise<void>`
|
||||||
- `getBySku(googleAuthId: number, sku: string, tx?: object): Promise<{article: {id: number, sku: string, name: string, slug: string, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, price: {net: number, taxId: number, taxRate?: number}|null}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>`
|
- `getBySku(googleAuthId: number, sku: string, tx?: object): Promise<{article: {id: number, sku: string, name: string, slug: string, description: string|null, seo: string|null, seoTitle: string|null, seoDescription: string|null, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, price: {net: number, taxId: number, taxRate?: number}|null}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>`
|
||||||
- `getHistoryBySku(googleAuthId: number, sku: string, opts?: {limit?: number}, tx?: object): Promise<Array<{id: number, companyuserId: number|null, date: string, text: string}>>`
|
- `getHistoryBySku(googleAuthId: number, sku: string, opts?: {limit?: number}, tx?: object): Promise<Array<{id: number, companyuserId: number|null, date: string, text: string}>>`
|
||||||
- `importRows(input: {googleAuthId: number, rows: Array<object>}, tx?: object): Promise<{imported: Array<object>, skipped: Array<object>, errors: Array<object>}>`
|
- `importRows(input: {googleAuthId: number, rows: Array<object>}, tx?: object): Promise<{imported: Array<object>, skipped: Array<object>, errors: Array<object>}>`
|
||||||
- `listChildren(googleAuthId: number, parentSku: string, tx?: object): Promise<Array<{id: number, sku: string, parentsort: number, trackStock: boolean, unitamount: number, weight: number, name: string|null, slug: string|null, attributeValueId: number|null, attributeValue: string|null}>>`
|
- `listChildren(googleAuthId: number, parentSku: string, tx?: object): Promise<Array<{id: number, sku: string, parentsort: number, trackStock: boolean, unitamount: number, weight: number, name: string|null, slug: string|null, attributeValueId: number|null, attributeValue: string|null}>>`
|
||||||
@@ -108,7 +108,7 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
|
|||||||
- `setTrackStockBySku(googleAuthId: number, sku: string, trackStock: boolean|number, tx?: object): Promise<object>`
|
- `setTrackStockBySku(googleAuthId: number, sku: string, trackStock: boolean|number, tx?: object): Promise<object>`
|
||||||
- `setWeightBySku(googleAuthId: number, sku: string, weight: number, tx?: object): Promise<object>`
|
- `setWeightBySku(googleAuthId: number, sku: string, weight: number, tx?: object): Promise<object>`
|
||||||
- `toggleParent(googleAuthId: number, sku: string, options: {isParent: boolean, attributeNameId?: number, parentAttributeNameId?: number}, tx?: object): Promise<object>`
|
- `toggleParent(googleAuthId: number, sku: string, options: {isParent: boolean, attributeNameId?: number, parentAttributeNameId?: number}, tx?: object): Promise<object>`
|
||||||
- `updateBySku(googleAuthId: number, sku: string, patch: {name?: string, unitSi?: string, unitamount?: number, track_stock?: boolean|number}, tx?: object): Promise<object>`
|
- `updateBySku(googleAuthId: number, sku: string, patch: {name?: string, description?: string, desc?: string, seo?: object|string, seoTitle?: string, seoDescription?: string, unitSi?: string, unitamount?: number, track_stock?: boolean|number}, tx?: object): Promise<object>`
|
||||||
- [lang](API.lang.md)
|
- [lang](API.lang.md)
|
||||||
- `create(iso639: string, tx?: object): Promise<number>`
|
- `create(iso639: string, tx?: object): Promise<number>`
|
||||||
- `delete(id: number): Promise<void>`
|
- `delete(id: number): Promise<void>`
|
||||||
|
|||||||
@@ -432,6 +432,8 @@ SELECT
|
|||||||
a.sku,
|
a.sku,
|
||||||
at.name,
|
at.name,
|
||||||
at.slug,
|
at.slug,
|
||||||
|
at.[desc] AS description,
|
||||||
|
at.seo AS seo,
|
||||||
a.unitamount,
|
a.unitamount,
|
||||||
a.weight,
|
a.weight,
|
||||||
a.track_stock,
|
a.track_stock,
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ export const ARTICLE_DETAIL_COLUMNS = `
|
|||||||
a.sku,
|
a.sku,
|
||||||
at.name,
|
at.name,
|
||||||
at.slug,
|
at.slug,
|
||||||
|
at.[desc] AS description,
|
||||||
|
at.seo,
|
||||||
a.unitamount,
|
a.unitamount,
|
||||||
a.weight,
|
a.weight,
|
||||||
a.track_stock,
|
a.track_stock,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
export const CREATE = `
|
export const CREATE = `
|
||||||
INSERT INTO articletext (article_id, language_id, name, slug)
|
INSERT INTO articletext (article_id, language_id, name, slug, [desc], seo)
|
||||||
VALUES (@articleId, @languageId, @name, @slug)
|
VALUES (@articleId, @languageId, @name, @slug, @desc, @seo)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const UPDATE_BY_ARTICLE_AND_LANGUAGE = `
|
export const UPDATE_BY_ARTICLE_AND_LANGUAGE = `
|
||||||
UPDATE articletext
|
UPDATE articletext
|
||||||
SET name = @name, slug = @slug
|
SET name = @name, slug = @slug, [desc] = @desc, seo = @seo
|
||||||
WHERE article_id = @articleId AND language_id = @languageId
|
WHERE article_id = @articleId AND language_id = @languageId
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ WITH auth AS (
|
|||||||
SELECT auth.*,
|
SELECT auth.*,
|
||||||
json_object(
|
json_object(
|
||||||
'id', a.id, 'sku', a.sku, 'name', at.name, 'slug', at.slug,
|
'id', a.id, 'sku', a.sku, 'name', at.name, 'slug', at.slug,
|
||||||
|
'description', at."desc", 'seo', at.seo,
|
||||||
'unitamount', a.unitamount, 'weight', a.weight,
|
'unitamount', a.unitamount, 'weight', a.weight,
|
||||||
'track_stock', a.track_stock,
|
'track_stock', a.track_stock,
|
||||||
'unitSi', u.si, 'unitBasesi', u.basesi,
|
'unitSi', u.si, 'unitBasesi', u.basesi,
|
||||||
|
|||||||
@@ -237,6 +237,8 @@ export default function addChild(provider) {
|
|||||||
languageId,
|
languageId,
|
||||||
name: childName,
|
name: childName,
|
||||||
slug: childSlug,
|
slug: childSlug,
|
||||||
|
desc: null,
|
||||||
|
seo: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
// History on child
|
// History on child
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ export default function createUnderParent(provider) {
|
|||||||
* @param {number} input.googleAuthId - The id of the Google auth user.
|
* @param {number} input.googleAuthId - The id of the Google auth user.
|
||||||
* @param {number} input.parentId - The id of the parent category.
|
* @param {number} input.parentId - The id of the parent category.
|
||||||
* @param {string} input.name - The article name.
|
* @param {string} input.name - The article name.
|
||||||
|
* @param {string} [input.description] - The article description.
|
||||||
|
* @param {string} [input.desc] - Alias for description.
|
||||||
|
* @param {object|string} [input.seo] - The SEO configuration or JSON string.
|
||||||
|
* @param {string} [input.seoTitle] - The SEO title.
|
||||||
|
* @param {string} [input.seoDescription] - The SEO meta description.
|
||||||
* @param {boolean|number} [input.track_stock=true] - Whether inventory stock is tracked.
|
* @param {boolean|number} [input.track_stock=true] - Whether inventory stock is tracked.
|
||||||
* @param {object} [tx] - Optional transaction to run within.
|
* @param {object} [tx] - Optional transaction to run within.
|
||||||
* @returns {Promise<{id: number, parentId: number, name: string, sku: string, track_stock: boolean}>} The created article.
|
* @returns {Promise<{id: number, parentId: number, name: string, sku: string, track_stock: boolean}>} The created article.
|
||||||
@@ -41,7 +46,7 @@ export default function createUnderParent(provider) {
|
|||||||
* const article = await store.article.createUnderParent({ googleAuthId: 42, parentId: 5, name: 'Cola' });
|
* const article = await store.article.createUnderParent({ googleAuthId: 42, parentId: 5, name: 'Cola' });
|
||||||
* // => { id, parentId, name, sku, track_stock }
|
* // => { id, parentId, name, sku, track_stock }
|
||||||
*/
|
*/
|
||||||
return async ({ googleAuthId, parentId, name, track_stock, trackStock, sku: inputSku }, tx) => {
|
return async ({ googleAuthId, parentId, name, description, desc, shortDescription, seo, seoTitle, seoDescription, track_stock, trackStock, sku: inputSku }, tx) => {
|
||||||
const rawTrack = track_stock ?? trackStock;
|
const rawTrack = track_stock ?? trackStock;
|
||||||
const finalTrackStock = rawTrack == null ? 1 : (rawTrack ? 1 : 0);
|
const finalTrackStock = rawTrack == null ? 1 : (rawTrack ? 1 : 0);
|
||||||
|
|
||||||
@@ -80,11 +85,31 @@ export default function createUnderParent(provider) {
|
|||||||
articleId: id,
|
articleId: id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const rawDesc = description !== undefined ? description : desc;
|
||||||
|
const finalDesc = rawDesc != null && rawDesc !== '' ? String(rawDesc) : null;
|
||||||
|
let finalSeo = null;
|
||||||
|
if (shortDescription !== undefined) {
|
||||||
|
finalSeo = shortDescription != null && shortDescription !== '' ? String(shortDescription) : null;
|
||||||
|
} else if (typeof seo === 'string') {
|
||||||
|
finalSeo = seo !== '' ? seo : null;
|
||||||
|
} else if (seoDescription && !seoTitle) {
|
||||||
|
finalSeo = String(seoDescription);
|
||||||
|
} else if (seo != null) {
|
||||||
|
finalSeo = typeof seo === 'string' ? seo : JSON.stringify(seo);
|
||||||
|
} else if (seoTitle || seoDescription) {
|
||||||
|
finalSeo = JSON.stringify({
|
||||||
|
title: seoTitle != null && seoTitle !== '' ? String(seoTitle) : '',
|
||||||
|
description: seoDescription != null && seoDescription !== '' ? String(seoDescription) : '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await runner.query(createArticleTextSql, {
|
await runner.query(createArticleTextSql, {
|
||||||
articleId: id,
|
articleId: id,
|
||||||
languageId,
|
languageId,
|
||||||
name,
|
name,
|
||||||
slug,
|
slug,
|
||||||
|
desc: finalDesc,
|
||||||
|
seo: finalSeo,
|
||||||
});
|
});
|
||||||
|
|
||||||
await runner.query(insertHistorySql, {
|
await runner.query(insertHistorySql, {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default function getBySku(provider) {
|
|||||||
* @param {number} googleAuthId - The id of the Google auth user.
|
* @param {number} googleAuthId - The id of the Google auth user.
|
||||||
* @param {string} sku - The article SKU.
|
* @param {string} sku - The article SKU.
|
||||||
* @param {object} [tx] - Optional transaction.
|
* @param {object} [tx] - Optional transaction.
|
||||||
* @returns {Promise<{article: {id: number, sku: string, name: string, slug: string, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, price: {net: number, taxId: number, taxRate?: number}|null}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>} The full article detail.
|
* @returns {Promise<{article: {id: number, sku: string, name: string, slug: string, description: string|null, seo: string|null, seoTitle: string|null, seoDescription: string|null, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, price: {net: number, taxId: number, taxRate?: number}|null}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>} The full article detail.
|
||||||
* @throws {Error} If the article is not found or the user is not authorized.
|
* @throws {Error} If the article is not found or the user is not authorized.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -48,12 +48,33 @@ export default function getBySku(provider) {
|
|||||||
|
|
||||||
const a = typeof row.articleJson === 'string' ? JSON.parse(row.articleJson) : row.articleJson;
|
const a = typeof row.articleJson === 'string' ? JSON.parse(row.articleJson) : row.articleJson;
|
||||||
|
|
||||||
|
let seoTitle = null;
|
||||||
|
let seoDescription = null;
|
||||||
|
if (a.seo) {
|
||||||
|
try {
|
||||||
|
const parsed = typeof a.seo === 'string' ? JSON.parse(a.seo) : a.seo;
|
||||||
|
if (parsed && typeof parsed === 'object') {
|
||||||
|
seoTitle = parsed.title ?? parsed.seoTitle ?? null;
|
||||||
|
seoDescription = parsed.description ?? parsed.seoDescription ?? null;
|
||||||
|
} else {
|
||||||
|
seoDescription = String(a.seo);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
seoDescription = String(a.seo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
article: {
|
article: {
|
||||||
id: a.id,
|
id: a.id,
|
||||||
sku: a.sku,
|
sku: a.sku,
|
||||||
name: a.name,
|
name: a.name,
|
||||||
slug: a.slug,
|
slug: a.slug,
|
||||||
|
description: a.description ?? null,
|
||||||
|
shortDescription: a.seo ?? null,
|
||||||
|
seo: a.seo ?? null,
|
||||||
|
seoTitle,
|
||||||
|
seoDescription: seoDescription ?? (a.seo ? String(a.seo) : null),
|
||||||
unitamount: a.unitamount,
|
unitamount: a.unitamount,
|
||||||
weight: a.weight,
|
weight: a.weight,
|
||||||
track_stock: Boolean(a.track_stock ?? 1),
|
track_stock: Boolean(a.track_stock ?? 1),
|
||||||
|
|||||||
@@ -206,6 +206,8 @@ export default function importRows(provider) {
|
|||||||
languageId,
|
languageId,
|
||||||
name,
|
name,
|
||||||
slug,
|
slug,
|
||||||
|
desc: row.description ?? row.desc ?? null,
|
||||||
|
seo: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
await runner.query(insertHistorySql, {
|
await runner.query(insertHistorySql, {
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ export default function updateBySku(provider) {
|
|||||||
* @param {string} sku - The article SKU.
|
* @param {string} sku - The article SKU.
|
||||||
* @param {object} patch - The update patch.
|
* @param {object} patch - The update patch.
|
||||||
* @param {string} [patch.name] - The new article name.
|
* @param {string} [patch.name] - The new article name.
|
||||||
|
* @param {string} [patch.description] - The article description.
|
||||||
|
* @param {string} [patch.desc] - Alias for description.
|
||||||
|
* @param {object|string} [patch.seo] - The SEO configuration or JSON string.
|
||||||
|
* @param {string} [patch.seoTitle] - The SEO title.
|
||||||
|
* @param {string} [patch.seoDescription] - The SEO meta description.
|
||||||
* @param {string} [patch.unitSi] - The new unit SI code.
|
* @param {string} [patch.unitSi] - The new unit SI code.
|
||||||
* @param {number} [patch.unitamount] - The new unit amount (must be > 0).
|
* @param {number} [patch.unitamount] - The new unit amount (must be > 0).
|
||||||
* @param {boolean|number} [patch.track_stock] - Whether inventory stock is tracked.
|
* @param {boolean|number} [patch.track_stock] - Whether inventory stock is tracked.
|
||||||
@@ -58,8 +63,15 @@ export default function updateBySku(provider) {
|
|||||||
const hasTrackStock =
|
const hasTrackStock =
|
||||||
Object.prototype.hasOwnProperty.call(patch, 'track_stock') ||
|
Object.prototype.hasOwnProperty.call(patch, 'track_stock') ||
|
||||||
Object.prototype.hasOwnProperty.call(patch, 'trackStock');
|
Object.prototype.hasOwnProperty.call(patch, 'trackStock');
|
||||||
|
const hasDescription =
|
||||||
|
Object.prototype.hasOwnProperty.call(patch, 'description') ||
|
||||||
|
Object.prototype.hasOwnProperty.call(patch, 'desc');
|
||||||
|
const hasShortDescription = Object.prototype.hasOwnProperty.call(patch, 'shortDescription');
|
||||||
|
const hasSeo = Object.prototype.hasOwnProperty.call(patch, 'seo');
|
||||||
|
const hasSeoTitle = Object.prototype.hasOwnProperty.call(patch, 'seoTitle');
|
||||||
|
const hasSeoDescription = Object.prototype.hasOwnProperty.call(patch, 'seoDescription');
|
||||||
|
|
||||||
if (!hasName && !hasUnitamount && !hasUnitSi && !hasTrackStock) {
|
if (!hasName && !hasUnitamount && !hasUnitSi && !hasTrackStock && !hasDescription && !hasShortDescription && !hasSeo && !hasSeoTitle && !hasSeoDescription) {
|
||||||
throw new Error('Name required');
|
throw new Error('Name required');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,19 +155,67 @@ export default function updateBySku(provider) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (hasDescription) {
|
||||||
|
const oldDesc = current.description ?? current.desc ?? '';
|
||||||
|
const rawDesc = patch.description !== undefined ? patch.description : patch.desc;
|
||||||
|
const newDesc = rawDesc != null ? String(rawDesc) : '';
|
||||||
|
if (oldDesc !== newDesc) {
|
||||||
|
historyLines.push('Beschreibung geändert');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const needsTextUpdate = hasName || hasDescription || hasSeo || hasSeoTitle || hasSeoDescription;
|
||||||
|
if (needsTextUpdate) {
|
||||||
|
const finalName = hasName ? patch.name.trim() : (current.name || '');
|
||||||
|
const slug = hasName
|
||||||
|
? await resolveSlug(runner, {
|
||||||
|
companyId,
|
||||||
|
languageId,
|
||||||
|
name: patch.name,
|
||||||
|
excludeArticleId: articleId,
|
||||||
|
})
|
||||||
|
: (current.slug || '');
|
||||||
|
|
||||||
|
let finalDesc = current.description ?? current.desc ?? null;
|
||||||
|
if (hasDescription) {
|
||||||
|
const rawDesc = patch.description !== undefined ? patch.description : patch.desc;
|
||||||
|
finalDesc = rawDesc != null && rawDesc !== '' ? String(rawDesc) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let finalSeo = current.seo ?? null;
|
||||||
|
if (hasShortDescription) {
|
||||||
|
finalSeo = patch.shortDescription != null && patch.shortDescription !== '' ? String(patch.shortDescription) : null;
|
||||||
|
} else if (hasSeo && typeof patch.seo === 'string') {
|
||||||
|
finalSeo = patch.seo !== '' ? patch.seo : null;
|
||||||
|
} else if (hasSeoDescription && !hasSeoTitle) {
|
||||||
|
finalSeo = patch.seoDescription != null && patch.seoDescription !== '' ? String(patch.seoDescription) : null;
|
||||||
|
} else if (hasSeo || hasSeoTitle || hasSeoDescription) {
|
||||||
|
let seoObj = {};
|
||||||
|
if (current.seo) {
|
||||||
|
try {
|
||||||
|
const parsed = typeof current.seo === 'string' ? JSON.parse(current.seo) : current.seo;
|
||||||
|
if (parsed && typeof parsed === 'object') seoObj = parsed;
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
if (hasSeo && patch.seo && typeof patch.seo === 'object') {
|
||||||
|
seoObj = { ...seoObj, ...patch.seo };
|
||||||
|
}
|
||||||
|
if (hasSeoTitle) {
|
||||||
|
seoObj.title = patch.seoTitle != null && patch.seoTitle !== '' ? String(patch.seoTitle) : '';
|
||||||
|
}
|
||||||
|
if (hasSeoDescription) {
|
||||||
|
seoObj.description = patch.seoDescription != null && patch.seoDescription !== '' ? String(patch.seoDescription) : '';
|
||||||
|
}
|
||||||
|
finalSeo = Object.keys(seoObj).length > 0 ? JSON.stringify(seoObj) : null;
|
||||||
|
}
|
||||||
|
|
||||||
if (hasName) {
|
|
||||||
const slug = await resolveSlug(runner, {
|
|
||||||
companyId,
|
|
||||||
languageId,
|
|
||||||
name: patch.name,
|
|
||||||
excludeArticleId: articleId,
|
|
||||||
});
|
|
||||||
const update = await runner.query(updateTextSql, {
|
const update = await runner.query(updateTextSql, {
|
||||||
articleId,
|
articleId,
|
||||||
languageId,
|
languageId,
|
||||||
name: patch.name.trim(),
|
name: finalName,
|
||||||
slug,
|
slug,
|
||||||
|
desc: finalDesc,
|
||||||
|
seo: finalSeo,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!update.rowsAffected) {
|
if (!update.rowsAffected) {
|
||||||
|
|||||||
Reference in New Issue
Block a user