@porulle/plugin-channel-connector 0.50.0 → 0.50.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.
- package/dist/service.js +35 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/service.ts +41 -6
package/dist/service.js
CHANGED
|
@@ -3,7 +3,7 @@ import { CommerceInvalidTransitionError, CommerceValidationError, Ok, PluginErr,
|
|
|
3
3
|
import { isValidFieldPath, requireUserId } from "@porulle/core";
|
|
4
4
|
import { CHANNEL_CONVERGENCE_CTX } from "./catalog-push-trigger.js";
|
|
5
5
|
import { and, desc, eq, inArray, isNull, lte, or, sql } from "@porulle/core/drizzle";
|
|
6
|
-
import { brands, categories, customerAddresses, customers, entityMedia, entityTags, inventoryLevels, mediaAssets, optionTypes, optionValues, orderLineItems, orders, prices, sellableAttributes, sellableCustomFields, sellableEntities, sellableEntityRevisions, entityFieldDefinitions, tags, variants, variantOptionValues, } from "@porulle/core/schema";
|
|
6
|
+
import { brands, categories, customerAddresses, customers, entityMedia, entityBrands, entityCategories, entityTags, inventoryLevels, mediaAssets, optionTypes, optionValues, orderLineItems, orders, prices, sellableAttributes, sellableCustomFields, sellableEntities, sellableEntityRevisions, entityFieldDefinitions, tags, variants, variantOptionValues, } from "@porulle/core/schema";
|
|
7
7
|
import { channelCatalogPushEvents, channelCatalogPushes, channelCatalogConflicts, channelCatalogConflictEvents, channelEntityMap, channelExportEvents, channelOrderExports, connectedStores, channelRefundEvents, channelRefundRequests, } from "./schema.js";
|
|
8
8
|
import { mergeCatalogFieldMapping, normalizeCatalogFieldMapping, selectCatalogFieldMapping, } from "./catalog-field-mapping.js";
|
|
9
9
|
export const CATALOG_PUSH_BATCH_SIZES = {
|
|
@@ -973,6 +973,14 @@ export class ChannelConnectorService {
|
|
|
973
973
|
existingOptionValues.set(row.variantId, list);
|
|
974
974
|
}
|
|
975
975
|
}
|
|
976
|
+
// The product's plain base prices, read once. `setBasePrice` upserts and fires its hook even at
|
|
977
|
+
// the same amount, so an unchanged price is skipped here — and a price that IS written is what
|
|
978
|
+
// makes the variant "changed", which is what `converged` counts.
|
|
979
|
+
const storedPrices = item.variants.some((variant) => (variant.prices ?? []).length > 0)
|
|
980
|
+
? await this.db.select({ variantId: prices.variantId, currency: prices.currency, amount: prices.amount, compareAtAmount: prices.compareAtAmount })
|
|
981
|
+
.from(prices)
|
|
982
|
+
.where(and(eq(prices.organizationId, orgId), eq(prices.entityId, entityId), isNull(prices.customerGroupId), isNull(prices.minQuantity), isNull(prices.maxQuantity), isNull(prices.validFrom), isNull(prices.validUntil)))
|
|
983
|
+
: [];
|
|
976
984
|
for (const sourceVariant of item.variants) {
|
|
977
985
|
const fullSourceVariant = fullItem.variants.find((variant) => variant.externalId === sourceVariant.externalId) ?? sourceVariant;
|
|
978
986
|
let mapping = mappings.find((row) => row.externalId === sourceVariant.externalId);
|
|
@@ -1081,6 +1089,10 @@ export class ChannelConnectorService {
|
|
|
1081
1089
|
}
|
|
1082
1090
|
}
|
|
1083
1091
|
for (const price of sourceVariant.prices ?? []) {
|
|
1092
|
+
const currency = price.currency.trim().toUpperCase();
|
|
1093
|
+
const stored = storedPrices.find((row) => row.variantId === variantId && row.currency === currency);
|
|
1094
|
+
if (stored && stored.amount === price.amount && stored.compareAtAmount === (price.compareAtAmount ?? null))
|
|
1095
|
+
continue;
|
|
1084
1096
|
const priced = await this.pricing.setBasePrice({
|
|
1085
1097
|
entityId,
|
|
1086
1098
|
variantId,
|
|
@@ -1090,6 +1102,7 @@ export class ChannelConnectorService {
|
|
|
1090
1102
|
}, actor);
|
|
1091
1103
|
if (!priced.ok)
|
|
1092
1104
|
return PluginErr(priced.error.message);
|
|
1105
|
+
changed = true;
|
|
1093
1106
|
}
|
|
1094
1107
|
// Was UNCONDITIONAL: one UPDATE per variant on every import, including a re-sync where the
|
|
1095
1108
|
// variant is byte-identical. `mapping.syncHash` is already in hand from the select above, so
|
|
@@ -1141,6 +1154,13 @@ export class ChannelConnectorService {
|
|
|
1141
1154
|
}
|
|
1142
1155
|
async applyTaxonomy(orgId, entityId, item, actor, warnings) {
|
|
1143
1156
|
const taxonomy = await this.taxonomyFor(orgId);
|
|
1157
|
+
// The links this entity already has, read only for the classes the item names. A link already
|
|
1158
|
+
// there is not re-written, and a link that is added is what reports the taxonomy as changed.
|
|
1159
|
+
const linkedCategories = new Set((item.categories ?? []).length === 0 ? [] : (await this.db
|
|
1160
|
+
.select({ id: entityCategories.categoryId }).from(entityCategories).where(eq(entityCategories.entityId, entityId))).map((row) => row.id));
|
|
1161
|
+
const linkedBrands = new Set(!item.brand ? [] : (await this.db
|
|
1162
|
+
.select({ id: entityBrands.brandId }).from(entityBrands).where(eq(entityBrands.entityId, entityId))).map((row) => row.id));
|
|
1163
|
+
let changed = false;
|
|
1144
1164
|
const categoryRows = taxonomy.categories;
|
|
1145
1165
|
for (const slug of new Set(item.categories ?? [])) {
|
|
1146
1166
|
let category = categoryRows.find((row) => row.slug === slug);
|
|
@@ -1158,9 +1178,12 @@ export class ChannelConnectorService {
|
|
|
1158
1178
|
category = createdCategory;
|
|
1159
1179
|
categoryRows.push(category);
|
|
1160
1180
|
}
|
|
1181
|
+
if (linkedCategories.has(category.id))
|
|
1182
|
+
continue;
|
|
1161
1183
|
const linked = await this.catalog.addToCategory(entityId, category.id, actor);
|
|
1162
1184
|
if (!linked.ok)
|
|
1163
1185
|
return PluginErr(linked.error.message);
|
|
1186
|
+
changed = true;
|
|
1164
1187
|
}
|
|
1165
1188
|
const brandRows = taxonomy.brands;
|
|
1166
1189
|
if (item.brand) {
|
|
@@ -1175,9 +1198,12 @@ export class ChannelConnectorService {
|
|
|
1175
1198
|
brand = createdBrand;
|
|
1176
1199
|
brandRows.push(brand);
|
|
1177
1200
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1201
|
+
if (!linkedBrands.has(brand.id)) {
|
|
1202
|
+
const linked = await this.catalog.addToBrand(entityId, brand.id, actor);
|
|
1203
|
+
if (!linked.ok)
|
|
1204
|
+
return PluginErr(linked.error.message);
|
|
1205
|
+
changed = true;
|
|
1206
|
+
}
|
|
1181
1207
|
}
|
|
1182
1208
|
const tagRows = taxonomy.tags;
|
|
1183
1209
|
for (const slug of new Set(item.tags ?? [])) {
|
|
@@ -1189,9 +1215,11 @@ export class ChannelConnectorService {
|
|
|
1189
1215
|
return PluginErr(`Tag "${slug}" was not persisted.`);
|
|
1190
1216
|
tagRows.push(tag);
|
|
1191
1217
|
}
|
|
1192
|
-
await this.db.insert(entityTags).values({ entityId, tagId: tag.id }).onConflictDoNothing();
|
|
1218
|
+
const added = await this.db.insert(entityTags).values({ entityId, tagId: tag.id }).onConflictDoNothing().returning({ tagId: entityTags.tagId });
|
|
1219
|
+
if (added.length > 0)
|
|
1220
|
+
changed = true;
|
|
1193
1221
|
}
|
|
1194
|
-
return Ok(
|
|
1222
|
+
return Ok({ changed });
|
|
1195
1223
|
}
|
|
1196
1224
|
async applyMedia(orgId, entityId, item, variantIds, actor, warnings, owners) {
|
|
1197
1225
|
const images = item.images ?? [];
|
|
@@ -2886,7 +2914,7 @@ export class ChannelConnectorService {
|
|
|
2886
2914
|
mediaImported += media.value.imported;
|
|
2887
2915
|
variantsGivenOptionValues += variantIds.value.repaired;
|
|
2888
2916
|
skipped.push(...media.value.skipped.map((fieldPath) => ({ entityId, fieldPath })));
|
|
2889
|
-
entityTouched = entityTouched || optionAxes.value.changed || variantIds.value.changed || media.value.changed || attributes.value.changed;
|
|
2917
|
+
entityTouched = entityTouched || optionAxes.value.changed || variantIds.value.changed || taxonomy.value.changed || media.value.changed || attributes.value.changed;
|
|
2890
2918
|
if (entityTouched)
|
|
2891
2919
|
entitiesTouched += 1;
|
|
2892
2920
|
// Counted from what was written, not from the stored hash: a hash that moved while the
|