feat(assoc): v4.0.1 合伙人关联码、分佣账单与 H5 用户管理
订单佣金只认关联用户;合伙人备注写入独立表;H5 增加用户管理与首页统计。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,49 +1,9 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
resolveOrderCityPartner,
|
||||
validatePartnerCityBinding,
|
||||
validatePartnerCommissionRates,
|
||||
} from './city-partner';
|
||||
|
||||
describe('resolveOrderCityPartner', () => {
|
||||
const bindings = [
|
||||
{
|
||||
id: '1',
|
||||
partnerAccountId: '10',
|
||||
scopeType: 'CITY_WIDE' as const,
|
||||
districtCodes: null,
|
||||
orderCommissionRate: 0,
|
||||
redeemCommissionRate: 0.03,
|
||||
bindingStatus: 'ACTIVE' as const,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
partnerAccountId: '20',
|
||||
scopeType: 'DISTRICT' as const,
|
||||
districtCodes: ['410105', '金水区'],
|
||||
orderCommissionRate: 0.01,
|
||||
redeemCommissionRate: 0.03,
|
||||
bindingStatus: 'ACTIVE' as const,
|
||||
},
|
||||
];
|
||||
|
||||
it('prefers district partner when district matches adcode', () => {
|
||||
const ref = resolveOrderCityPartner(bindings, '410105');
|
||||
expect(ref?.partnerAccountId).toBe('20');
|
||||
expect(ref?.scopeType).toBe('DISTRICT');
|
||||
});
|
||||
|
||||
it('falls back to city-wide partner', () => {
|
||||
const ref = resolveOrderCityPartner(bindings, '410102');
|
||||
expect(ref?.partnerAccountId).toBe('10');
|
||||
expect(ref?.scopeType).toBe('CITY_WIDE');
|
||||
});
|
||||
|
||||
it('returns null when no bindings', () => {
|
||||
expect(resolveOrderCityPartner([], '410105')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('validatePartnerCityBinding', () => {
|
||||
it('rejects duplicate partner', () => {
|
||||
const result = validatePartnerCityBinding(
|
||||
|
||||
@@ -11,72 +11,11 @@ export interface PartnerCityBindingInput {
|
||||
companyName?: string | null;
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user