CI / Generate TypeScript types (push) Successful in 14s
CI / Server unit tests (push) Successful in 20s
CI / Build server (push) Successful in 24s
CI / Build client (push) Successful in 33s
CI / Playwright E2E tests (push) Successful in 1m17s
CI / Build and push Docker image (push) Successful in 39s
CI / Notify (push) Successful in 2s
68 lines
2.8 KiB
TypeScript
68 lines
2.8 KiB
TypeScript
import { OrderGroup, OrderGroupMember } from "../../../types";
|
|
|
|
/**
|
|
* Pomocné funkce pro výpočet částek ve skupinových objednávkách.
|
|
*
|
|
* Klíčové pravidlo: poplatky (balné + doprava + spropitné) se rozpočítávají
|
|
* pouze mezi "aktivní" strávníky — tedy ty, kteří si reálně něco objednali.
|
|
* Kdo si nic neobjedná (typicky objednávající, který nakupuje jen pro ostatní),
|
|
* neplatí nic a nezapočítává se mu ani poměrná část poplatků.
|
|
*/
|
|
|
|
/** Parametry poplatků a slevy potřebné k výpočtu částky člena. */
|
|
export type GroupFeeParams = {
|
|
/** Celkové poplatky skupiny v haléřích (balné + doprava + spropitné). */
|
|
totalFees: number;
|
|
/** Typ slevy ('percent' = procenta, 'fixed' = pevná částka v haléřích). */
|
|
discountType?: string;
|
|
/** Hodnota slevy — procenta, nebo pevná částka v haléřích dle discountType. */
|
|
discountValue?: number;
|
|
};
|
|
|
|
/** Vrátí true, pokud si člen něco objednal (má kladnou částku nebo příplatek). */
|
|
export function isActiveMember(member: OrderGroupMember): boolean {
|
|
return (member.amount ?? 0) + (member.surchargeAmount ?? 0) > 0;
|
|
}
|
|
|
|
/** Počet aktivních strávníků — jen mezi ně se dělí poplatky. */
|
|
export function countActiveMembers(members: OrderGroup["members"]): number {
|
|
return Object.values(members).filter(isActiveMember).length;
|
|
}
|
|
|
|
/** Celkové poplatky skupiny (balné + doprava + spropitné) v haléřích. */
|
|
export function totalGroupFees(group: OrderGroup): number {
|
|
return (group.fees ?? 0) + (group.shipping ?? 0) + (group.tip ?? 0);
|
|
}
|
|
|
|
/** Poměrná část poplatků na jednoho aktivního strávníka v haléřích. */
|
|
export function computeFeeShare(totalFees: number, activeCount: number): number {
|
|
return activeCount > 0 ? Math.round(totalFees / activeCount) : 0;
|
|
}
|
|
|
|
/**
|
|
* Celková částka, kterou má člen zaplatit (v haléřích).
|
|
* Neaktivní člen (nic si neobjednal) platí 0 — nepodílí se ani na poplatcích.
|
|
*
|
|
* @param member člen skupiny
|
|
* @param params poplatky a sleva
|
|
* @param feeShare poměrná část poplatků na osobu (viz computeFeeShare)
|
|
* @param activeCount počet aktivních strávníků (dělitel pevné slevy)
|
|
*/
|
|
export function computeMemberTotal(
|
|
member: OrderGroupMember,
|
|
params: GroupFeeParams,
|
|
feeShare: number,
|
|
activeCount: number,
|
|
): number {
|
|
if (!isActiveMember(member)) return 0;
|
|
const base = member.amount ?? 0;
|
|
const surcharge = member.surchargeAmount ?? 0;
|
|
const discountValue = params.discountValue ?? 0;
|
|
const discount = discountValue > 0
|
|
? (params.discountType === 'percent'
|
|
? Math.round((base + surcharge) * discountValue / 100)
|
|
: Math.round(discountValue / activeCount))
|
|
: 0;
|
|
return base + surcharge + feeShare - discount;
|
|
}
|