スキル一覧に戻る
avifenesh

expense-sharing

by avifenesh

0🍴 0📅 2026年1月25日
GitHubで見るManusで実行

SKILL.md


name: expense-sharing description: Expense sharing calculations, split types (EQUAL/PERCENTAGE/FIXED), participant state management, and settlement tracking. Use when working with shared expenses, split calculations, payment status transitions, or settlement balances.

Expense Sharing Domain Knowledge

Schema Overview

SharedExpense Model

model SharedExpense {
  id            String               @id @default(cuid())
  transactionId String               @unique
  ownerId       String
  splitType     SplitType            @default(EQUAL)
  totalAmount   Decimal              @db.Decimal(12, 2)
  currency      Currency             @default(USD)
  description   String?

  transaction   Transaction          @relation(...)
  owner         User                 @relation("SharedExpensesOwned", ...)
  participants  ExpenseParticipant[]
}

ExpenseParticipant Model

model ExpenseParticipant {
  id              String        @id @default(cuid())
  sharedExpenseId String
  userId          String
  shareAmount     Decimal       @db.Decimal(12, 2)
  sharePercentage Decimal?      @db.Decimal(5, 2)
  status          PaymentStatus @default(PENDING)
  paidAt          DateTime?
  reminderSentAt  DateTime?

  @@unique([sharedExpenseId, userId])
}

Split Types

enum SplitType {
  EQUAL      // Divide total equally among all participants + owner
  PERCENTAGE // Each participant gets a specified percentage
  FIXED      // Each participant gets a fixed amount
}

calculateShares Function

Location: src/app/actions/expense-sharing.ts

export function calculateShares(
  splitType: SplitType,
  totalAmount: number,
  participants: Array<{ email: string; shareAmount?: number; sharePercentage?: number }>,
  validEmails: string[],
): Map<string, { amount: number; percentage: number | null }>

EQUAL Split Logic

// Divide among (numParticipants + 1) to include owner
const equalShare = Math.round((totalAmount / (numParticipants + 1)) * 100) / 100

PERCENTAGE Split Logic

// Validation: total percentage must not exceed 100%
const amount = Math.round(totalAmount * (percentage / 100) * 100) / 100

FIXED Split Logic

// Validation: total fixed amounts cannot exceed totalAmount
// Each participant gets their specified shareAmount

Payment Status Transitions

PENDING → PAID      (owner marks as received)
PENDING → DECLINED  (participant declines)
PAID → (terminal)
DECLINED → (terminal)

Transition Rules:

  • Only owner can mark PENDING → PAID via markSharePaidAction
  • Only participant can DECLINE their own share via declineShareAction
  • Cannot mark DECLINED share as PAID

Action Pipeline

All expense sharing actions follow:

1. parseInput(schema, input)      // Zod validation
2. requireCsrfToken(csrfToken)    // CSRF protection
3. requireActiveSubscription()    // Subscription gate
4. requireAuthUser()              // Authentication
5. Authorization check            // Ownership/participant verification
6. Business logic
7. revalidatePath('/')            // Cache invalidation
8. return success/error

Email Notifications

  • sendExpenseSharedEmail: Sent to each participant when expense is shared
  • sendPaymentReminderEmail: 24-hour cooldown (REMINDER_COOLDOWN_HOURS = 24)

Settlement Balance Calculation

Location: src/lib/finance.ts (getSettlementBalances)

Groups by user AND currency to avoid mixing currencies:

// Returns for each user:
{
  userId: string
  youOwe: number    // What you owe them (PENDING expenses they shared with you)
  theyOwe: number   // What they owe you (PENDING expenses you shared with them)
  netBalance: number // theyOwe - youOwe
}

Key Files

  • src/app/actions/expense-sharing.ts - All sharing actions
  • src/lib/finance.ts - calculateShares, getSettlementBalances
  • src/schemas/index.ts - shareExpenseSchema, participantSchema
  • tests/calculate-shares.test.ts - Unit tests for split calculations

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です