main create
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
/**
|
||||
* Engine tính toán chi phí dựa trên công thức trong ARCHITECTURE.md
|
||||
* T = N_adult * X + N_child * (X * (1 - P_child_discount))
|
||||
*/
|
||||
export class ExpenseEngine {
|
||||
/**
|
||||
* Tính toán phân chia chi phí giữa người lớn và trẻ em
|
||||
* @param totalCost Tổng chi phí (T)
|
||||
* @param adultCount Số lượng người lớn (N_adult)
|
||||
* @param childCount Số lượng trẻ em (N_child)
|
||||
* @param childDiscountPercent Phần trăm giảm giá trẻ em (P_child_discount, ví dụ: 30)
|
||||
*/
|
||||
calculateSplit(
|
||||
totalCost: number,
|
||||
adultCount: number,
|
||||
childCount: number,
|
||||
childDiscountPercent: number
|
||||
) {
|
||||
// 1. Validation: Kiểm tra dữ liệu đầu vào âm
|
||||
if (totalCost < 0 || adultCount < 0 || childCount < 0 || childDiscountPercent < 0) {
|
||||
throw new BadRequestException('Dữ liệu đầu vào không được là số âm.');
|
||||
}
|
||||
|
||||
if (childDiscountPercent > 100) {
|
||||
throw new BadRequestException('Phần trăm giảm giá không thể vượt quá 100%.');
|
||||
}
|
||||
|
||||
// 2. Handle division by zero: Không có người tham gia
|
||||
if (adultCount + childCount === 0) {
|
||||
throw new BadRequestException('Số lượng người tham gia phải lớn hơn 0.');
|
||||
}
|
||||
|
||||
const discountRate = childDiscountPercent / 100;
|
||||
const childRateFactor = 1 - discountRate;
|
||||
|
||||
/**
|
||||
* Giải phương trình:
|
||||
* T = X * N_adult + X * (1 - P) * N_child
|
||||
* T = X * (N_adult + N_child * (1 - P))
|
||||
* => X = T / (N_adult + N_child * (1 - P))
|
||||
*/
|
||||
const weightedParticipantCount = adultCount + (childCount * childRateFactor);
|
||||
|
||||
const adultPriceRaw = totalCost / weightedParticipantCount;
|
||||
const childPriceRaw = adultPriceRaw * childRateFactor;
|
||||
|
||||
// Làm tròn để thực tế thanh toán (ví dụ: làm tròn đến hàng đơn vị)
|
||||
const perAdult = Math.round(adultPriceRaw);
|
||||
const perChild = Math.round(childPriceRaw);
|
||||
|
||||
const adultsTotal = perAdult * adultCount;
|
||||
const childrenTotal = perChild * childCount;
|
||||
const actualSum = adultsTotal + childrenTotal;
|
||||
|
||||
return {
|
||||
targetTotal: totalCost,
|
||||
actualTotal: actualSum,
|
||||
perAdult,
|
||||
perChild,
|
||||
roundingDifference: totalCost - actualSum, // Chênh lệch do làm tròn (nếu có)
|
||||
adultsTotal,
|
||||
childrenTotal,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user