import { describe, expect, it } from 'vitest'; import { validatePartnerCityBinding, validatePartnerCommissionRates, } from './city-partner'; describe('validatePartnerCityBinding', () => { it('rejects duplicate partner', () => { const result = validatePartnerCityBinding( [{ id: '1', partnerAccountId: '10', scopeType: 'CITY_WIDE' }], { partnerAccountId: '10', scopeType: 'DISTRICT', districtCodes: ['410105'] }, ); expect(result.ok).toBe(false); }); it('rejects second city-wide partner', () => { const result = validatePartnerCityBinding( [{ id: '1', partnerAccountId: '10', scopeType: 'CITY_WIDE' }], { partnerAccountId: '11', scopeType: 'CITY_WIDE' }, ); expect(result.ok).toBe(false); }); it('allows overlapping district codes as labels', () => { const result = validatePartnerCityBinding( [ { id: '1', partnerAccountId: '10', scopeType: 'DISTRICT', districtCodes: ['410105'], companyName: '甲公司', }, ], { partnerAccountId: '11', scopeType: 'DISTRICT', districtCodes: ['410105'] }, ); expect(result.ok).toBe(true); }); it('allows district partner without district codes', () => { const result = validatePartnerCityBinding( [], { partnerAccountId: '11', scopeType: 'DISTRICT', districtCodes: [] }, ); expect(result.ok).toBe(true); }); it('allows valid district binding', () => { const result = validatePartnerCityBinding( [{ id: '1', partnerAccountId: '10', scopeType: 'DISTRICT', districtCodes: ['410105'] }], { partnerAccountId: '11', scopeType: 'DISTRICT', districtCodes: ['410106'] }, ); expect(result.ok).toBe(true); }); }); describe('validatePartnerCommissionRates', () => { it('allows sum within default 5% cap', () => { expect(validatePartnerCommissionRates(0.02, 0.03).ok).toBe(true); }); it('rejects sum above cap', () => { const result = validatePartnerCommissionRates(0.03, 0.03, 0.05); expect(result.ok).toBe(false); expect(result.message).toContain('5.00%'); }); it('respects custom city cap', () => { expect(validatePartnerCommissionRates(0.04, 0.04, 0.08).ok).toBe(true); expect(validatePartnerCommissionRates(0.05, 0.04, 0.08).ok).toBe(false); }); });