export type CityPartnerScopeType = 'CITY_WIDE' | 'DISTRICT'; export type CityPartnerStatus = 'ACTIVE' | 'PAUSED'; export interface PartnerCityBindingInput { id?: string; partnerAccountId: string; scopeType: CityPartnerScopeType; districtCodes?: string[] | null; bindingStatus?: CityPartnerStatus; } export interface PartnerCityResolveRef { id: string; partnerAccountId: string; scopeType: CityPartnerScopeType; orderCommissionRate: number; redeemCommissionRate: number; } export interface PartnerCityValidationResult { ok: boolean; message?: string; } function normalizeDistrictCodes(codes?: string[] | null): string[] { if (!codes?.length) return []; return [...new Set(codes.map((c) => String(c).trim()).filter(Boolean))]; } /** 区县 adcode 或名称命中区域合伙;否则全城合伙 */ export function resolveOrderCityPartner( bindings: Array<{ id: string; partnerAccountId: string; scopeType: CityPartnerScopeType; districtCodes?: string[] | null; orderCommissionRate: number; redeemCommissionRate: number; bindingStatus?: CityPartnerStatus; }>, receiverDistrict?: string | null, ): PartnerCityResolveRef | null { const active = bindings.filter((b) => b.bindingStatus !== 'PAUSED'); if (!active.length) return null; const districtKey = receiverDistrict?.trim(); if (districtKey) { const districtHit = active.find((b) => { if (b.scopeType !== 'DISTRICT') return false; const codes = normalizeDistrictCodes(b.districtCodes); return codes.some((code) => code === districtKey || districtKey.includes(code) || code.includes(districtKey)); }); if (districtHit) { return { id: districtHit.id, partnerAccountId: districtHit.partnerAccountId, scopeType: districtHit.scopeType, orderCommissionRate: districtHit.orderCommissionRate, redeemCommissionRate: districtHit.redeemCommissionRate, }; } } const cityWide = active.find((b) => b.scopeType === 'CITY_WIDE'); if (cityWide) { return { id: cityWide.id, partnerAccountId: cityWide.partnerAccountId, scopeType: cityWide.scopeType, orderCommissionRate: cityWide.orderCommissionRate, redeemCommissionRate: cityWide.redeemCommissionRate, }; } return null; } export function validatePartnerCityBinding( existing: PartnerCityBindingInput[], input: PartnerCityBindingInput, excludeId?: string, ): PartnerCityValidationResult { const others = existing.filter((b) => b.id !== excludeId); if (others.some((b) => b.partnerAccountId === input.partnerAccountId)) { return { ok: false, message: '该合伙人已绑定此城市' }; } if (input.scopeType === 'CITY_WIDE') { if (others.some((b) => b.scopeType === 'CITY_WIDE')) { return { ok: false, message: '每城最多 1 名全城合伙人' }; } return { ok: true }; } const districts = normalizeDistrictCodes(input.districtCodes); if (!districts.length) { return { ok: false, message: '区域合伙人须至少选择一个区县' }; } const occupied = new Set(); for (const row of others) { if (row.scopeType !== 'DISTRICT') continue; for (const code of normalizeDistrictCodes(row.districtCodes)) { occupied.add(code); } } for (const code of districts) { if (occupied.has(code)) { return { ok: false, message: `区县 ${code} 已被其他区域合伙人占用` }; } } return { ok: true }; } /** @deprecated use validatePartnerCityBinding */ export const validateCityPartnerBinding = validatePartnerCityBinding; export const DEFAULT_MAX_PARTNER_COMMISSION_RATE = 0.05; export function resolveMaxPartnerCommissionRate(maxRate?: number | null): number { if (maxRate == null || Number.isNaN(Number(maxRate))) { return DEFAULT_MAX_PARTNER_COMMISSION_RATE; } return Number(maxRate); } /** 订单佣金 + 核销佣金不得超过城市配置上限(默认 5%) */ export function validatePartnerCommissionRates( orderCommissionRate: number, redeemCommissionRate: number, maxSumRate = DEFAULT_MAX_PARTNER_COMMISSION_RATE, ): PartnerCityValidationResult { const sum = orderCommissionRate + redeemCommissionRate; const max = resolveMaxPartnerCommissionRate(maxSumRate); if (sum > max + 1e-9) { return { ok: false, message: `订单佣金与核销佣金合计不得超过 ${(max * 100).toFixed(2)}%(当前 ${(sum * 100).toFixed(2)}%)`, }; } return { ok: true }; }