InterviewDB Question

Dispute Status - State Machine for Payment Dispute Lifecycle

Question Details

Problem

A payment dispute follows this lifecycle:

OPENED -> EVIDENCE_SUBMITTED -> UNDER_REVIEW -> RESOLVED_WON
                                             -> RESOLVED_LOST
       -> WITHDRAWN

Invalid transitions (e.g., UNDER_REVIEW -> OPENED) must raise an error.

Implement:

python
class Dispute:
    def __init__(self, dispute_id: str):
        self.status = "OPENED"
    def transition(self, new_status: str) -> None:
        # raises ValueError if transition is invalid
    def is_resolved(self) -> bool:
    def history(self) -> list[str]:  # all statuses in order

Example

d = Dispute("d123")
d.transition("EVIDENCE_SUBMITTED")
d.transition("UNDER_REVIEW")
d.transition("RESOLVED_WON")
d.history() -> ["OPENED","EVIDENCE_SUBMITTED","UNDER_REVIEW","RESOLVED_WON"]
d.transition("WITHDRAWN")  # raises ValueError

Follow-ups

  1. How would you represent the valid transitions as a data structure rather than hard-coded conditionals?
  2. Add timestamps to each transition and a method time_in_state(status) that returns the duration.
  3. How would you persist dispute state to a database and handle concurrent updates?
  4. Extend to support automatic escalation: if UNDER_REVIEW for more than 30 days, auto-transition to RESOLVED_LOST.

Full Details

Problem

A payment dispute follows this lifecycle:

OPENED -> EVIDENCE_SUBMITTED -> UNDER_REVIEW -> RESOLVED_WON
                                             -> RESOLVED_LOST
       -> WITHDRAWN

Invalid transitions (e.g., UNDER_REVIEW -> OPENED) must raise an error.

Implement:

python
class Dispute:
    def __init__(self, dispute_id: str):
        self.status = "OPENED"
    def transition(self, new_status: str) -> None:
        # raises ValueError if transition is invalid
    def is_resolved(self) -> bool:
    def history(self) -> list[str]:  # all statuses in order

Example

d = Dispute("d123")
d.transition("EVIDENCE_SUBMITTED")
d.transition("UNDER_REVIEW")
d.transition("RESOLVED_WON")
d.history() -> ["OPENED","EVIDENCE_SUBMITTED","UNDER_REVIEW","RESOLVED_WON"]
d.transition("WITHDRAWN")  # raises ValueError

Follow-ups

  1. How would you represent the valid transitions as a data structure rather than hard-coded conditionals?
  2. Add timestamps to each transition and a method time_in_state(status) that returns the duration.
  3. How would you persist dispute state to a database and handle concurrent updates?
  4. Extend to support automatic escalation: if UNDER_REVIEW for more than 30 days, auto-transition to RESOLVED_LOST.

About This Question

This is a reported interview question from a affirm interview during the phone round.

It covers the following topics: Coding, Sql, Phone, Onsite .