From 6c9fd8aec231ee4b818f1820cc72d9c58f423a5f Mon Sep 17 00:00:00 2001 From: jackiettran <41605212+jackiettran@users.noreply.github.com> Date: Mon, 12 Jan 2026 17:00:08 -0500 Subject: [PATCH] have the right dispute statuses --- ...260112000001-expand-dispute-status-enum.js | 67 +++++++++++++++++++ backend/models/Rental.js | 11 ++- backend/services/disputeService.js | 4 +- 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 backend/migrations/20260112000001-expand-dispute-status-enum.js diff --git a/backend/migrations/20260112000001-expand-dispute-status-enum.js b/backend/migrations/20260112000001-expand-dispute-status-enum.js new file mode 100644 index 0000000..772c081 --- /dev/null +++ b/backend/migrations/20260112000001-expand-dispute-status-enum.js @@ -0,0 +1,67 @@ +"use strict"; + +/** + * Replaces stripeDisputeStatus enum with all valid Stripe dispute statuses. + * Previous enum had: open, won, lost, warning_closed + * Stripe uses: needs_response, under_review, won, lost, + * warning_needs_response, warning_under_review, warning_closed + */ +module.exports = { + up: async (queryInterface) => { + // Create new enum type with correct Stripe statuses + await queryInterface.sequelize.query(` + CREATE TYPE "enum_Rentals_stripeDisputeStatus_new" AS ENUM ( + 'needs_response', + 'under_review', + 'won', + 'lost', + 'warning_needs_response', + 'warning_under_review', + 'warning_closed' + ); + `); + + // Alter column to use new type + await queryInterface.sequelize.query(` + ALTER TABLE "Rentals" + ALTER COLUMN "stripeDisputeStatus" + TYPE "enum_Rentals_stripeDisputeStatus_new" + USING "stripeDisputeStatus"::text::"enum_Rentals_stripeDisputeStatus_new"; + `); + + // Drop old enum type + await queryInterface.sequelize.query(` + DROP TYPE "enum_Rentals_stripeDisputeStatus"; + `); + + // Rename new type to original name + await queryInterface.sequelize.query(` + ALTER TYPE "enum_Rentals_stripeDisputeStatus_new" + RENAME TO "enum_Rentals_stripeDisputeStatus"; + `); + }, + + down: async (queryInterface) => { + await queryInterface.sequelize.query(` + CREATE TYPE "enum_Rentals_stripeDisputeStatus_old" AS ENUM ( + 'open', 'won', 'lost', 'warning_closed' + ); + `); + + await queryInterface.sequelize.query(` + ALTER TABLE "Rentals" + ALTER COLUMN "stripeDisputeStatus" + TYPE "enum_Rentals_stripeDisputeStatus_old" + USING "stripeDisputeStatus"::text::"enum_Rentals_stripeDisputeStatus_old"; + `); + + await queryInterface.sequelize.query(` + DROP TYPE "enum_Rentals_stripeDisputeStatus"; + `); + + await queryInterface.sequelize.query(` + ALTER TYPE "enum_Rentals_stripeDisputeStatus_old" + RENAME TO "enum_Rentals_stripeDisputeStatus"; + `); + }, +}; diff --git a/backend/models/Rental.js b/backend/models/Rental.js index 265e972..35db2f8 100644 --- a/backend/models/Rental.js +++ b/backend/models/Rental.js @@ -95,8 +95,17 @@ const Rental = sequelize.define("Rental", { type: DataTypes.STRING, }, // Dispute tracking fields (for tracking Stripe payment disputes/chargebacks) + // Stripe dispute statuses: https://docs.stripe.com/api/disputes/object#dispute_object-status stripeDisputeStatus: { - type: DataTypes.ENUM("open", "won", "lost", "warning_closed"), + type: DataTypes.ENUM( + "needs_response", + "under_review", + "won", + "lost", + "warning_needs_response", + "warning_under_review", + "warning_closed" + ), allowNull: true, }, stripeDisputeId: { diff --git a/backend/services/disputeService.js b/backend/services/disputeService.js index ffe0a29..48a26d5 100644 --- a/backend/services/disputeService.js +++ b/backend/services/disputeService.js @@ -38,7 +38,7 @@ class DisputeService { // Update rental with dispute info await rental.update({ - stripeDisputeStatus: "open", + stripeDisputeStatus: dispute.status, stripeDisputeId: dispute.id, stripeDisputeReason: dispute.reason, stripeDisputeAmount: dispute.amount, @@ -106,7 +106,7 @@ class DisputeService { const won = dispute.status === "won"; await rental.update({ - stripeDisputeStatus: dispute.status, // 'won', 'lost', 'warning_closed' + stripeDisputeStatus: dispute.status, stripeDisputeClosedAt: new Date(), });