Files
BarevClub/packages/services/src/payouts.ts
T

66 lines
2.6 KiB
TypeScript

import {
defaultParams,
paramsSchemaSchema,
payoutByRules,
payoutFor,
payoutRulesSchema,
pricingSchema,
quote,
type ParamValues,
type PriceBreakdown,
type RateType,
} from '@barev/core';
type Rate = { type: RateType; value: number };
export interface PayoutProvider {
rateType: RateType;
rateValue: number;
company: { rateType: RateType; rateValue: number } | null;
payoutPreset: { rules: unknown } | null;
}
export interface PayoutOrder {
totalPrice: number;
basePrice: number;
params: unknown;
priceBreakdown: unknown;
service: { pricing: unknown; paramsSchema: unknown };
}
/** Разбивка цены заказа: сохранённая при создании или пересчитанная по параметрам (старые заказы) */
export function breakdownOf(o: PayoutOrder): PriceBreakdown | null {
if (o.priceBreakdown && typeof o.priceBreakdown === 'object') return o.priceBreakdown as PriceBreakdown;
try {
const schema = paramsSchemaSchema.parse(o.service.paramsSchema);
const params = { ...defaultParams(schema), ...(o.params as ParamValues) };
return quote(pricingSchema.parse(o.service.pricing), params).breakdown;
} catch {
return null;
}
}
/**
* PRO-8: выплата исполнителю за заказ.
* - сотрудник компании — договорная ставка компании (от итоговой цены);
* - исполнитель с пресетом (джун / мидл / прайват) — фикс или % по каждой строке цены;
* - иначе — индивидуальная ставка (фикс за заказ или % от итога).
*/
export function orderPayout(o: PayoutOrder, p: PayoutProvider): number {
if (p.company) return payoutFor(o.totalPrice, { type: p.company.rateType, value: p.company.rateValue });
if (p.payoutPreset) {
const rules = payoutRulesSchema.safeParse(p.payoutPreset.rules);
const b = breakdownOf(o);
if (rules.success && b) return payoutByRules(b, rules.data).total;
}
const rate: Rate = { type: p.rateType, value: p.rateValue };
return payoutFor(o.totalPrice, rate);
}
/** Описание ставки для экрана «История» исполнителя */
export function rateLabel(p: PayoutProvider & { payoutPreset: { name: string; rules: unknown } | null }) {
if (p.company) return { kind: 'company' as const, type: p.company.rateType, value: p.company.rateValue };
if (p.payoutPreset) return { kind: 'preset' as const, name: p.payoutPreset.name };
return { kind: 'own' as const, type: p.rateType, value: p.rateValue };
}