feat : add monthly
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { commissionIncomeDay, commissionIncomeMonth, commissionIncomeShares } from "./income";
|
||||
|
||||
describe("commission income periods", () => {
|
||||
it("uses Bangkok month boundaries and rolls across years", () => {
|
||||
const december = commissionIncomeMonth("2026-12");
|
||||
expect(december.from.toISOString()).toBe("2026-11-30T17:00:00.000Z");
|
||||
expect(december.to.toISOString()).toBe("2026-12-31T17:00:00.000Z");
|
||||
expect(december.next).toBe("2027-01");
|
||||
expect(commissionIncomeMonth("2027-01").previous).toBe("2026-12");
|
||||
});
|
||||
|
||||
it("defaults to the current Bangkok month for an invalid query", () => {
|
||||
expect(commissionIncomeMonth("2026-13", new Date("2026-09-30T18:00:00Z")).month).toBe("2026-10");
|
||||
});
|
||||
|
||||
it("assigns payments around midnight to the correct Bangkok day", () => {
|
||||
expect(commissionIncomeDay(new Date("2026-10-01T16:59:59Z"))).toBe(1);
|
||||
expect(commissionIncomeDay(new Date("2026-10-01T17:00:00Z"))).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
it("calculates Buzz and Gunshin shares in satang", () => {
|
||||
expect(commissionIncomeShares(101)).toEqual({ buzzSatang: 9090, gunshinSatang: 1010 });
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
const BANGKOK_OFFSET = "+07:00";
|
||||
|
||||
export function commissionIncomeMonth(value: string | string[] | undefined, now = new Date()) {
|
||||
const currentParts = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: "Asia/Bangkok", year: "numeric", month: "2-digit",
|
||||
}).formatToParts(now);
|
||||
const current = `${currentParts.find((part) => part.type === "year")!.value}-${currentParts.find((part) => part.type === "month")!.value}`;
|
||||
const month = typeof value === "string" && /^(20\d{2}|[3-9]\d{3})-(0[1-9]|1[0-2])$/.test(value) ? value : current;
|
||||
const [year, number] = month.split("-").map(Number);
|
||||
const next = number === 12 ? `${year + 1}-01` : `${year}-${String(number + 1).padStart(2, "0")}`;
|
||||
const previous = number === 1 ? `${year - 1}-12` : `${year}-${String(number - 1).padStart(2, "0")}`;
|
||||
return {
|
||||
month, year, number, previous, next,
|
||||
from: new Date(`${month}-01T00:00:00${BANGKOK_OFFSET}`),
|
||||
to: new Date(`${next}-01T00:00:00${BANGKOK_OFFSET}`),
|
||||
days: new Date(Date.UTC(year, number, 0)).getUTCDate(),
|
||||
leadingDays: (new Date(Date.UTC(year, number - 1, 1)).getUTCDay() + 6) % 7,
|
||||
};
|
||||
}
|
||||
|
||||
export function commissionIncomeDay(date: Date) {
|
||||
return Number(new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: "Asia/Bangkok", day: "numeric",
|
||||
}).format(date));
|
||||
}
|
||||
|
||||
export function commissionIncomeShares(amountBaht: number) {
|
||||
return { buzzSatang: amountBaht * 90, gunshinSatang: amountBaht * 10 };
|
||||
}
|
||||
Reference in New Issue
Block a user