Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save lmonkiewicz/a6ab100efc95f4ae68464398394bb47f to your computer and use it in GitHub Desktop.

Select an option

Save lmonkiewicz/a6ab100efc95f4ae68464398394bb47f to your computer and use it in GitHub Desktop.
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
import org.springframework.data.domain.AbstractAggregateRoot;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.util.UUID;
@Entity
@Table(name = "transactions")
@EntityListeners(AuditingEntityListener.class)
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Transaction extends AbstractAggregateRoot<Transaction> {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Version
private Long version;
@Embedded
private TransactionStatus status;
@Embedded
private AuditData audit = new AuditData();
@Embedded
private Brief brief;
@JdbcTypeCode(SqlTypes.JSON)
@Column(name = "json_data")
private Details details;
public Transaction(Brief brief, Details details) {
this.status = new TransactionStatus(TransactionStatus.MainStatus.NEW, TransactionStatus.SubStatus.IN_PROGRESS);
this.brief = brief;
this.details = details;
}
// --- WZORZEC STATE ---
public <T extends TransactionState> T state(Class<T> type) {
var state = switch (this.status.getMain()) {
case NEW -> new ReceivedState(this);
case ON_HOLD, AWAITING_VERIFICATION -> new ValidatedState(this);
case COMPLETED, FAILED -> throw new IllegalStateException("Transakcja w stanie końcowym: " + status.getMain());
default -> throw new IllegalStateException("Nieobsługiwany status: " + status.getMain());
};
// check czy jest to tej klasy
return (T) state;
}
void updateStatus(TransactionStatus.MainStatus newMain, TransactionStatus.SubStatus newSub) {
this.status = new TransactionStatus(newMain, newSub);
// Opcjonalnie: registerEvent(new TransactionStatusChangedEvent(this.id, newMain));
}
}
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
// 1. Polimorficzny JSON
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = TransactionDetails.class, name = "PAYMENT"),
@JsonSubTypes.Type(value = ReturnDetails.class, name = "RETURN")
})
public interface Details {}
public record TransactionDetails(String type, String extraField) implements Details {}
public record ReturnDetails(String type, String reasonCode) implements Details {}
// 2. Interfejs stanu
public interface TransactionState {
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment