diff --git a/CLAUDE.md b/CLAUDE.md index 10b866d..48f18c8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,6 +48,7 @@ src/ update.ts - Update loan by ID pay.ts - Make a loan payment mark-paid.ts - Pay the next pending installment + unmark-paid.ts - Reverse a loan payment (default: most recent) delete.ts - Delete loan by ID stats/ summary.ts - Financial summary @@ -161,6 +162,7 @@ Login flow writes human-readable output to stderr (not JSON) since it is interac | GET | /api/loans | loans list | | POST | /api/loans | loans create | | POST | /api/loans/:id/pay | loans pay | +| POST | /api/loans/:id/reverse-payment | loans unmark-paid | | PUT | /api/loans/:id | loans update | | DELETE | /api/loans/:id | loans delete | | GET | /api/stats/summary | stats summary | diff --git a/src/commands/loans/unmark-paid.ts b/src/commands/loans/unmark-paid.ts new file mode 100644 index 0000000..eb4d6b6 --- /dev/null +++ b/src/commands/loans/unmark-paid.ts @@ -0,0 +1,44 @@ +import { Command } from "commander"; +import { apiRequest } from "../../lib/api-client.js"; +import { output } from "../../lib/output.js"; + +interface LoanPayment { + id: string; + paidAt: string; + payAmount: number; + loanAmount: number; + payCurrency: string; +} + +interface LoanDetails { + id: string; + payments: LoanPayment[]; +} + +export const unmarkPaidLoanCommand = new Command("unmark-paid") + .description("Reverse a loan payment (default: most recent)") + .argument("", "Loan ID") + .option("--payment-id ", "Specific payment ID to reverse") + .addHelpText( + "after", + "\nExamples:\n lucas loans unmark-paid \n lucas loans unmark-paid --payment-id \n", + ) + .action(async (id: string, opts: { paymentId?: string }) => { + let paymentId = opts.paymentId; + + if (!paymentId) { + const loan = await apiRequest("GET", `/api/loans/${id}`); + if (!loan.payments || loan.payments.length === 0) { + output.error("No payments found for this loan", 404, { loanId: id }); + } + const sorted = [...loan.payments].sort( + (a, b) => new Date(b.paidAt).getTime() - new Date(a.paidAt).getTime(), + ); + paymentId = sorted[0].id; + } + + const data = await apiRequest("POST", `/api/loans/${id}/reverse-payment`, { + paymentId, + }); + output.success(data); + }); diff --git a/src/index.ts b/src/index.ts index 2d7242e..1b73a38 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,6 +39,7 @@ import { createLoanCommand } from "./commands/loans/create.js"; import { updateLoanCommand } from "./commands/loans/update.js"; import { payLoanCommand } from "./commands/loans/pay.js"; import { markPaidLoanCommand } from "./commands/loans/mark-paid.js"; +import { unmarkPaidLoanCommand } from "./commands/loans/unmark-paid.js"; import { deleteLoanCommand } from "./commands/loans/delete.js"; // Stats @@ -107,6 +108,7 @@ loans.addCommand(createLoanCommand); loans.addCommand(updateLoanCommand); loans.addCommand(payLoanCommand); loans.addCommand(markPaidLoanCommand); +loans.addCommand(unmarkPaidLoanCommand); loans.addCommand(deleteLoanCommand); // Grupo: stats