mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 10:24:02 +00:00
feat(bot): quiet finance topics and support purchase payers
This commit is contained in:
@@ -355,6 +355,7 @@ export function createDbFinanceRepository(
|
||||
id: purchaseId,
|
||||
householdId,
|
||||
senderMemberId: input.payerMemberId,
|
||||
payerMemberId: input.payerMemberId,
|
||||
senderTelegramUserId: 'miniapp',
|
||||
senderDisplayName: member?.displayName ?? 'Mini App',
|
||||
telegramChatId: 'miniapp',
|
||||
@@ -388,7 +389,7 @@ export function createDbFinanceRepository(
|
||||
const rows = await db
|
||||
.select({
|
||||
id: schema.purchaseMessages.id,
|
||||
payerMemberId: schema.purchaseMessages.senderMemberId,
|
||||
payerMemberId: schema.purchaseMessages.payerMemberId,
|
||||
amountMinor: schema.purchaseMessages.parsedAmountMinor,
|
||||
currency: schema.purchaseMessages.parsedCurrency,
|
||||
description: schema.purchaseMessages.parsedItemDescription,
|
||||
@@ -443,7 +444,8 @@ export function createDbFinanceRepository(
|
||||
: {}),
|
||||
...(input.payerMemberId
|
||||
? {
|
||||
senderMemberId: input.payerMemberId
|
||||
senderMemberId: input.payerMemberId,
|
||||
payerMemberId: input.payerMemberId
|
||||
}
|
||||
: {}),
|
||||
needsReview: 0,
|
||||
@@ -458,7 +460,7 @@ export function createDbFinanceRepository(
|
||||
)
|
||||
.returning({
|
||||
id: schema.purchaseMessages.id,
|
||||
payerMemberId: schema.purchaseMessages.senderMemberId,
|
||||
payerMemberId: schema.purchaseMessages.payerMemberId,
|
||||
amountMinor: schema.purchaseMessages.parsedAmountMinor,
|
||||
currency: schema.purchaseMessages.parsedCurrency,
|
||||
description: schema.purchaseMessages.parsedItemDescription,
|
||||
@@ -763,7 +765,7 @@ export function createDbFinanceRepository(
|
||||
const rows = await db
|
||||
.select({
|
||||
id: schema.purchaseMessages.id,
|
||||
payerMemberId: schema.purchaseMessages.senderMemberId,
|
||||
payerMemberId: schema.purchaseMessages.payerMemberId,
|
||||
amountMinor: schema.purchaseMessages.parsedAmountMinor,
|
||||
currency: schema.purchaseMessages.parsedCurrency,
|
||||
description: schema.purchaseMessages.parsedItemDescription,
|
||||
@@ -774,7 +776,7 @@ export function createDbFinanceRepository(
|
||||
.where(
|
||||
and(
|
||||
eq(schema.purchaseMessages.householdId, householdId),
|
||||
isNotNull(schema.purchaseMessages.senderMemberId),
|
||||
isNotNull(schema.purchaseMessages.payerMemberId),
|
||||
isNotNull(schema.purchaseMessages.parsedAmountMinor),
|
||||
isNotNull(schema.purchaseMessages.parsedCurrency),
|
||||
or(
|
||||
|
||||
@@ -15,6 +15,23 @@ import type {
|
||||
|
||||
import { createFinanceCommandService } from './finance-command-service'
|
||||
|
||||
function expectedCurrentCyclePeriod(timezone: string, rentDueDay: number): string {
|
||||
const parts = new Intl.DateTimeFormat('en-CA', {
|
||||
timeZone: timezone,
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
}).formatToParts(new Date())
|
||||
const year = Number(parts.find((part) => part.type === 'year')?.value ?? '0')
|
||||
const month = Number(parts.find((part) => part.type === 'month')?.value ?? '1')
|
||||
const day = Number(parts.find((part) => part.type === 'day')?.value ?? '1')
|
||||
const carryMonth = day > rentDueDay ? month + 1 : month
|
||||
const normalizedYear = carryMonth > 12 ? year + 1 : year
|
||||
const normalizedMonth = carryMonth > 12 ? 1 : carryMonth
|
||||
|
||||
return `${normalizedYear}-${String(normalizedMonth).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
class FinanceRepositoryStub implements FinanceRepository {
|
||||
householdId = 'household-1'
|
||||
member: FinanceMemberRecord | null = null
|
||||
@@ -428,9 +445,10 @@ describe('createFinanceCommandService', () => {
|
||||
const service = createService(repository)
|
||||
|
||||
const result = await service.addUtilityBill('Electricity', '55.20', 'member-1')
|
||||
const expectedPeriod = expectedCurrentCyclePeriod('Asia/Tbilisi', 20)
|
||||
|
||||
expect(result).not.toBeNull()
|
||||
expect(result?.period).toBe('2026-03')
|
||||
expect(result?.period).toBe(expectedPeriod)
|
||||
expect(repository.lastUtilityBill).toEqual({
|
||||
cycleId: 'opened-cycle',
|
||||
billName: 'Electricity',
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"0018_nimble_kojori.sql": "818738e729119c6de8049dcfca562926a5dc6e321ecbbf9cf38e02bc70b5a0dc",
|
||||
"0019_faithful_madame_masque.sql": "38711341799b04a7c47fcc64fd19faf5b26e6f183d6a4c01d492b9929cd63641",
|
||||
"0020_natural_mauler.sql": "a80a4a0196a3b4931040850089346d1bc99b34a5afca77d6d62478ee4b8902c1",
|
||||
"0020_silver_payments.sql": "9686235c75453f1eaa016f2f4ab7fce8fe964c76a4e3515987a2b9f90bd7b1ad"
|
||||
"0020_silver_payments.sql": "9686235c75453f1eaa016f2f4ab7fce8fe964c76a4e3515987a2b9f90bd7b1ad",
|
||||
"0021_sharp_payer.sql": "973596e154382984ba7769979ea58298b6d93c5139540854be01e8b283ddb4f1"
|
||||
}
|
||||
}
|
||||
|
||||
7
packages/db/drizzle/0021_sharp_payer.sql
Normal file
7
packages/db/drizzle/0021_sharp_payer.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE "purchase_messages"
|
||||
ADD COLUMN "payer_member_id" uuid REFERENCES "members"("id") ON DELETE SET NULL;
|
||||
|
||||
UPDATE "purchase_messages"
|
||||
SET "payer_member_id" = "sender_member_id"
|
||||
WHERE "payer_member_id" IS NULL
|
||||
AND "sender_member_id" IS NOT NULL;
|
||||
@@ -148,6 +148,13 @@
|
||||
"when": 1773590603863,
|
||||
"tag": "0020_natural_mauler",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"version": "7",
|
||||
"when": 1774200000000,
|
||||
"tag": "0021_sharp_payer",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -417,6 +417,9 @@ export const purchaseMessages = pgTable(
|
||||
senderMemberId: uuid('sender_member_id').references(() => members.id, {
|
||||
onDelete: 'set null'
|
||||
}),
|
||||
payerMemberId: uuid('payer_member_id').references(() => members.id, {
|
||||
onDelete: 'set null'
|
||||
}),
|
||||
senderTelegramUserId: text('sender_telegram_user_id').notNull(),
|
||||
senderDisplayName: text('sender_display_name'),
|
||||
rawText: text('raw_text').notNull(),
|
||||
|
||||
Reference in New Issue
Block a user