fix(types fixed of status, method)
This commit is contained in:
@@ -8,6 +8,9 @@ import {
|
||||
NewTransactionPayload,
|
||||
newTransactionPayloadSchema,
|
||||
paymentMethodOptions,
|
||||
PaymentStatus,
|
||||
paymentStatusOptions,
|
||||
claimStatusOptions,
|
||||
} from "@repo/db/types";
|
||||
import { prisma } from "@repo/db/client";
|
||||
import { PaymentStatusSchema } from "@repo/db/types";
|
||||
@@ -283,7 +286,7 @@ router.put(
|
||||
serviceLineId: line.id,
|
||||
paidAmount: line.totalDue.toNumber(),
|
||||
adjustedAmount: 0,
|
||||
method: paymentMethodOptions[1],
|
||||
method: paymentMethodOptions.CHECK,
|
||||
receivedDate: new Date(),
|
||||
notes: "Full claim payment",
|
||||
}));
|
||||
@@ -338,7 +341,7 @@ router.put(
|
||||
serviceLineId: line.id,
|
||||
paidAmount: line.totalPaid.negated().toNumber(), // negative to undo
|
||||
adjustedAmount: line.totalAdjusted.negated().toNumber(),
|
||||
method: paymentMethodOptions[4],
|
||||
method: paymentMethodOptions.OTHER,
|
||||
receivedDate: new Date(),
|
||||
notes: "Reverted full claim",
|
||||
}));
|
||||
@@ -374,18 +377,51 @@ router.patch(
|
||||
|
||||
const paymentId = parseIntOrError(req.params.id, "Payment ID");
|
||||
|
||||
const status = PaymentStatusSchema.parse(req.body.data.status);
|
||||
// Parse & coerce to PaymentStatus enum
|
||||
const rawStatus = PaymentStatusSchema.parse(req.body.data.status);
|
||||
if (
|
||||
!Object.values(paymentStatusOptions).includes(
|
||||
rawStatus as PaymentStatus
|
||||
)
|
||||
) {
|
||||
return res.status(400).json({ message: "Invalid payment status" });
|
||||
}
|
||||
const status = rawStatus as PaymentStatus;
|
||||
|
||||
const updatedPayment = await prisma.payment.update({
|
||||
where: { id: paymentId },
|
||||
data: { status, updatedById: userId },
|
||||
});
|
||||
// Load existing payment
|
||||
const existingPayment = await storage.getPayment(paymentId);
|
||||
if (!existingPayment) {
|
||||
return res.status(404).json({ message: "Payment not found" });
|
||||
}
|
||||
|
||||
res.json(updatedPayment);
|
||||
// If changing to VOID and linked to a claim -> update both atomically
|
||||
if (status === paymentStatusOptions.VOID && existingPayment.claimId) {
|
||||
const [updatedPayment, updatedClaim] = await prisma.$transaction([
|
||||
prisma.payment.update({
|
||||
where: { id: paymentId },
|
||||
data: { status, updatedById: userId },
|
||||
}),
|
||||
prisma.claim.update({
|
||||
where: { id: existingPayment.claimId },
|
||||
data: { status: claimStatusOptions.VOID },
|
||||
}),
|
||||
]);
|
||||
|
||||
return res.json(updatedPayment);
|
||||
}
|
||||
|
||||
// Otherwise just update payment (use storage helper)
|
||||
const updatedPayment = await storage.updatePaymentStatus(
|
||||
paymentId,
|
||||
{ status } as any,
|
||||
userId
|
||||
);
|
||||
|
||||
return res.json(updatedPayment);
|
||||
} catch (err: unknown) {
|
||||
const message =
|
||||
err instanceof Error ? err.message : "Failed to update payment status";
|
||||
res.status(500).json({ message });
|
||||
return res.status(500).json({ message });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
Claim,
|
||||
ClaimStatus,
|
||||
ClaimWithServiceLines,
|
||||
InsertClaim,
|
||||
UpdateClaim,
|
||||
@@ -13,13 +14,13 @@ export interface IStorage {
|
||||
limit: number,
|
||||
offset: number
|
||||
): Promise<ClaimWithServiceLines[]>;
|
||||
|
||||
getTotalClaimCountByPatient(patientId: number): Promise<number>;
|
||||
getClaimsByAppointmentId(appointmentId: number): Promise<Claim[]>;
|
||||
getRecentClaims(limit: number, offset: number): Promise<Claim[]>;
|
||||
getTotalClaimCount(): Promise<number>;
|
||||
createClaim(claim: InsertClaim): Promise<Claim>;
|
||||
updateClaim(id: number, updates: UpdateClaim): Promise<Claim>;
|
||||
updateClaimStatus(id: number, status: ClaimStatus): Promise<Claim>;
|
||||
deleteClaim(id: number): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -88,6 +89,18 @@ export const claimsStorage: IStorage = {
|
||||
}
|
||||
},
|
||||
|
||||
async updateClaimStatus(id: number, status: ClaimStatus): Promise<Claim> {
|
||||
const existing = await db.claim.findUnique({ where: { id } });
|
||||
if (!existing) {
|
||||
throw new Error("Claim not found");
|
||||
}
|
||||
|
||||
return db.claim.update({
|
||||
where: { id },
|
||||
data: { status },
|
||||
});
|
||||
},
|
||||
|
||||
async deleteClaim(id: number): Promise<void> {
|
||||
try {
|
||||
await db.claim.delete({ where: { id } });
|
||||
|
||||
@@ -11,6 +11,11 @@ export interface IStorage {
|
||||
getPayment(id: number): Promise<Payment | undefined>;
|
||||
createPayment(data: InsertPayment): Promise<Payment>;
|
||||
updatePayment(id: number, updates: UpdatePayment): Promise<Payment>;
|
||||
updatePaymentStatus(
|
||||
id: number,
|
||||
updates: UpdatePayment,
|
||||
updatedById?: number
|
||||
): Promise<Payment>;
|
||||
deletePayment(id: number, userId: number): Promise<void>;
|
||||
getPaymentById(id: number): Promise<PaymentWithExtras | null>;
|
||||
getRecentPaymentsByPatientId(
|
||||
@@ -51,6 +56,25 @@ export const paymentsStorage: IStorage = {
|
||||
});
|
||||
},
|
||||
|
||||
async updatePaymentStatus(
|
||||
id: number,
|
||||
updates: UpdatePayment,
|
||||
updatedById?: number
|
||||
): Promise<Payment> {
|
||||
const existing = await db.payment.findFirst({ where: { id } });
|
||||
if (!existing) {
|
||||
throw new Error("Payment not found");
|
||||
}
|
||||
|
||||
const data: any = { ...updates };
|
||||
if (typeof updatedById === "number") data.updatedById = updatedById;
|
||||
|
||||
return db.payment.update({
|
||||
where: { id },
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
async deletePayment(id: number, userId: number): Promise<void> {
|
||||
const existing = await db.payment.findFirst({ where: { id, userId } });
|
||||
if (!existing) {
|
||||
|
||||
@@ -14,11 +14,12 @@ import {
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
PaymentStatus,
|
||||
paymentStatusOptions,
|
||||
PaymentMethod,
|
||||
paymentMethodOptions,
|
||||
PaymentWithExtras,
|
||||
NewTransactionPayload,
|
||||
paymentStatusArray,
|
||||
paymentMethodArray,
|
||||
} from "@repo/db/types";
|
||||
import {
|
||||
Select,
|
||||
@@ -90,7 +91,7 @@ export default function PaymentEditModal({
|
||||
transactionId: "",
|
||||
paidAmount: 0,
|
||||
adjustedAmount: 0,
|
||||
method: paymentMethodOptions[1] as PaymentMethod,
|
||||
method: paymentMethodOptions.CHECK as PaymentMethod,
|
||||
receivedDate: formatLocalDate(new Date()),
|
||||
payerName: "",
|
||||
notes: "",
|
||||
@@ -298,7 +299,7 @@ export default function PaymentEditModal({
|
||||
transactionId: "",
|
||||
paidAmount: Number(line.totalDue) > 0 ? Number(line.totalDue) : 0,
|
||||
adjustedAmount: 0,
|
||||
method: paymentMethodOptions[1] as PaymentMethod,
|
||||
method: paymentMethodOptions.CHECK as PaymentMethod,
|
||||
receivedDate: formatLocalDate(new Date()),
|
||||
payerName: "",
|
||||
notes: "",
|
||||
@@ -431,7 +432,7 @@ export default function PaymentEditModal({
|
||||
serviceLineId: line.id,
|
||||
paidAmount: dueAmount,
|
||||
adjustedAmount: 0,
|
||||
method: paymentMethodOptions[1] as PaymentMethod, // Maybe make dynamic later
|
||||
method: paymentMethodOptions.CHECK as PaymentMethod, // Maybe make dynamic later
|
||||
receivedDate: new Date(),
|
||||
},
|
||||
],
|
||||
@@ -565,7 +566,7 @@ export default function PaymentEditModal({
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{paymentStatusOptions.map((status) => (
|
||||
{paymentStatusArray.map((status) => (
|
||||
<SelectItem key={status} value={status}>
|
||||
{status}
|
||||
</SelectItem>
|
||||
@@ -727,7 +728,7 @@ export default function PaymentEditModal({
|
||||
<SelectValue placeholder="Select a payment method" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{paymentMethodOptions.map((methodOption) => (
|
||||
{paymentMethodArray.map((methodOption) => (
|
||||
<SelectItem
|
||||
key={methodOption}
|
||||
value={methodOption}
|
||||
|
||||
Reference in New Issue
Block a user