smithery/avifenesh

expense-sharing

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.

Installation

$ npx skills add smithery/avifenesh --skill expense-sharing

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/avifenesh.

npx skills add smithery/avifenesh

Browse all from smithery/avifenesh

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,087 B
  • docs SUMMARY.md 256 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

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 (REMINDERCOOLDOWNHOURS = 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