From e61d0033429938d969f5aa43c55dadb26e8cd45d Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sun, 25 Oct 2026 16:03:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(cost-center):=20=E5=B0=86=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8F=91=E8=B4=A7=E4=BB=B7=E6=A0=BC=E5=9F=BA=E7=BA=BF=E8=BD=AC?= =?UTF-8?q?=E4=B8=BA=E5=86=85=E5=BB=BA=E5=B8=B8=E9=87=8F=E5=B9=B6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=8F=82=E6=95=B0=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 提取并内建 38 条自动发货采购成本基线常量,消除生产镜像缺失 scripts 目录的 ENOENT 问题 - 在 jsonb_build_object 中增加 $5::text 类型显式强转,避免 Postgres 参数类型推断错误 - 增加同生效日期的版本就地更新逻辑,保障基线可重复无损导入 - 验证方式:npm run typecheck、npm test、生产镜像容器内真实触发导入接口返回 200 --- .../affiliate-dash-prices-baseline.ts | 47 +++++++++++++++++++ .../cost-center/affiliate-product-service.ts | 29 +++++++----- 2 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 apps/backend/src/services/cost-center/affiliate-dash-prices-baseline.ts diff --git a/apps/backend/src/services/cost-center/affiliate-dash-prices-baseline.ts b/apps/backend/src/services/cost-center/affiliate-dash-prices-baseline.ts new file mode 100644 index 00000000..9d965203 --- /dev/null +++ b/apps/backend/src/services/cost-center/affiliate-dash-prices-baseline.ts @@ -0,0 +1,47 @@ +export interface AffiliateDashPriceBaselineItem { + sku: string + name: string + category: string + costAmountFen: number +} + +export const AFFILIATE_DASH_PRICES_BASELINE: AffiliateDashPriceBaselineItem[] = [ + { sku: 'rock_blue_sportswear', name: '蓝色运动服上衣', category: '服饰', costAmountFen: 2100 }, + { sku: 'rock_black_tshirt', name: '黑色ROCK长袖T恤', category: '服饰', costAmountFen: 2100 }, + { sku: 'suit_jester_face', name: '套装-花面小丑', category: '套装', costAmountFen: 20000 }, + { sku: 'suit_dune_song', name: '套装-沙丘之歌', category: '套装', costAmountFen: 10200 }, + { sku: 'pack_dragon_palace', name: '龙宫之主大礼包', category: '礼包', costAmountFen: 80000 }, + { sku: 'lucky_coin_x90', name: '幸运币90个', category: '道具', costAmountFen: 9000 }, + { sku: 'lucky_coin_x30', name: '幸运币30个', category: '道具', costAmountFen: 3000 }, + { sku: 'lucky_coin_x2', name: '幸运币2个', category: '道具', costAmountFen: 200 }, + { sku: 'honor_medal_x90', name: '荣耀勋章90个', category: '道具', costAmountFen: 9000 }, + { sku: 'honor_medal_x30', name: '荣耀勋章30个', category: '道具', costAmountFen: 3000 }, + { sku: 'honor_medal_x2', name: '荣耀勋章2个', category: '道具', costAmountFen: 200 }, + { sku: 'suit_cloud_bear', name: '套装-绵云熊熊', category: '套装', costAmountFen: 13480 }, + { sku: 'pack_star_roam_weapon', name: '星际漫游枪械礼包', category: '礼包', costAmountFen: 51600 }, + { sku: 'pack_star_roam_outfit', name: '星际漫游服装礼包', category: '礼包', costAmountFen: 83600 }, + { sku: 'suit_sand_dancer', name: '套装-狂沙舞者', category: '套装', costAmountFen: 8400 }, + { sku: 'pack_lava_ranger', name: '熔岩游骑兵礼包', category: '礼包', costAmountFen: 9600 }, + { sku: 'suit_panda_tuan', name: '套装-胖达团团', category: '套装', costAmountFen: 23400 }, + { sku: 'suit_panda_round', name: '套装-胖达圆圆', category: '套装', costAmountFen: 23400 }, + { sku: 'helmet_panda_treasure', name: '国宝胖达头盔', category: '头盔', costAmountFen: 23400 }, + { sku: 'suit_western_mystery', name: '套装-西部谜踪', category: '套装', costAmountFen: 11500 }, + { sku: 'helmet_hamster_gray', name: '仓鼠灰灰头盔', category: '头盔', costAmountFen: 16800 }, + { sku: 'bag_hamster_gray', name: '仓鼠灰灰背包', category: '背包', costAmountFen: 16800 }, + { sku: 'helmet_pink_sheep', name: '糯粉咩咩头盔', category: '头盔', costAmountFen: 16800 }, + { sku: 'bag_pink_sheep', name: '糯粉咩咩背包', category: '背包', costAmountFen: 16800 }, + { sku: 'suit_cute_bear', name: '套装-萌熊伴侣', category: '套装', costAmountFen: 16800 }, + { sku: 'suit_hamster_gray', name: '套装-仓鼠灰灰', category: '套装', costAmountFen: 12800 }, + { sku: 'frag_pink_sheep', name: '破片手榴弹-糯粉咩咩', category: '投掷物', costAmountFen: 4880 }, + { sku: 'smoke_pink_sheep', name: '烟雾弹-糯粉咩咩', category: '投掷物', costAmountFen: 4880 }, + { sku: 'pack_western_cowboy', name: '西部牛仔大礼包', category: '礼包', costAmountFen: 32000 }, + { sku: 'suit_romantic_destiny', name: '套装-浪漫天命', category: '套装', costAmountFen: 3600 }, + { sku: 'suit_first_peach', name: '套装-恋恋初桃', category: '套装', costAmountFen: 9880 }, + { sku: 'suit_pink_sheep', name: '套装-糯粉咩咩', category: '套装', costAmountFen: 18800 }, + { sku: 'suit_dual_fluffy', name: '套装-双彩绵绵', category: '套装', costAmountFen: 11240 }, + { sku: 'bag_cute_bear', name: '萌熊伴侣背包', category: '背包', costAmountFen: 28800 }, + { sku: 'm416_hamster_gray', name: 'M416-仓鼠灰灰', category: '枪械', costAmountFen: 16800 }, + { sku: 'top_black_elite_trainer', name: '黑色高级特训官上衣', category: '上衣', costAmountFen: 3600 }, + { sku: 'suit_shadow_gothic', name: '套装-暗影哥特', category: '套装', costAmountFen: 8880 }, + { sku: 'suit_alan_walker', name: '套装-Alan Walker', category: '套装', costAmountFen: 3600 }, +] diff --git a/apps/backend/src/services/cost-center/affiliate-product-service.ts b/apps/backend/src/services/cost-center/affiliate-product-service.ts index 0582060d..574b1486 100644 --- a/apps/backend/src/services/cost-center/affiliate-product-service.ts +++ b/apps/backend/src/services/cost-center/affiliate-product-service.ts @@ -1,5 +1,3 @@ -import fs from 'node:fs' - import { query } from '../../db/client.js' import type { AdminSession } from '../admin/admin-auth-service.js' import type { JsonObject } from '../../types/json.js' @@ -8,6 +6,7 @@ import { shiftDate } from '../../utils/finance-date-range.js' import { nowIso } from '../../utils/time.js' import { rebuildSalesDailyFacts } from '../finance/sales-facts-service.js' import { syncEstimatedOrderItemCostSnapshots } from './cost-snapshot-sync-service.js' +import { AFFILIATE_DASH_PRICES_BASELINE } from './affiliate-dash-prices-baseline.js' export async function syncAdminAffiliateDashProducts() { const now = nowIso() @@ -348,14 +347,7 @@ export async function setAdminAffiliateProductPrice( * 批量从上游基线导入 38 条自动发货采购成本。 */ export async function importAdminAffiliateDashPricesBaseline(session: AdminSession) { - const filePath = new URL('../../../scripts/data/affiliate-dash-prices.json', import.meta.url) - const rawData = fs.readFileSync(filePath, 'utf8') - const rows = JSON.parse(rawData) as Array<{ - sku: string - name: string - category: string - costAmountFen: number - }> + const rows = AFFILIATE_DASH_PRICES_BASELINE const costItemResult = await query<{ id: number }>( "SELECT id FROM cost_items WHERE code = 'sys_affiliate_purchase' OR cost_model = 'affiliate_purchase' ORDER BY (code = 'sys_affiliate_purchase') DESC LIMIT 1", @@ -381,7 +373,7 @@ export async function importAdminAffiliateDashPricesBaseline(session: AdminSessi attributes_json, created_at, updated_at ) VALUES ( $1, $2, $3, $4, 'active', - jsonb_build_object('source', 'affiliate_dash_price_import', 'skuCode', $5), + jsonb_build_object('source', 'affiliate_dash_price_import', 'skuCode', $5::text), $6, $6 ) ON CONFLICT (canonical_sku) DO UPDATE @@ -417,6 +409,21 @@ export async function importAdminAffiliateDashPricesBaseline(session: AdminSessi continue } + if (current && Date.parse(effectiveFrom) <= Date.parse(current.effective_from)) { + await query( + `UPDATE cost_versions + SET amount_fen = $1, + change_reason = '从上游价格基线导入', + created_by_admin_user_id = $2, + approved_by_admin_user_id = $2, + updated_at = $3 + WHERE id = $4`, + [row.costAmountFen, session.userId, now, current.id], + ) + updatedVersionCount += 1 + continue + } + if (current) { await query( "UPDATE cost_versions SET status = 'retired', effective_to = $1, updated_at = $2 WHERE id = $3",