Payment Flow + Access Flow Change
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
package refund
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"cloud.o-forge.io/core/oc-lib/models/common/pricing"
|
||||
"cloud.o-forge.io/core/oc-lib/models/utils"
|
||||
"cloud.o-forge.io/core/oc-lib/tools"
|
||||
)
|
||||
|
||||
type RefundStatus int
|
||||
|
||||
const (
|
||||
REFUND_PENDING RefundStatus = iota
|
||||
REFUND_APPROVED // approuvé, en attente de traitement
|
||||
REFUND_REJECTED // rejeté
|
||||
REFUND_PROCESSING // en cours de virement/blockchain
|
||||
REFUND_COMPLETED // remboursé
|
||||
REFUND_CANCELLED // annulé avant approbation
|
||||
)
|
||||
|
||||
func (s RefundStatus) String() string {
|
||||
return [...]string{"pending", "approved", "rejected", "processing", "completed", "cancelled"}[s]
|
||||
}
|
||||
|
||||
func RefundStatusList() []RefundStatus {
|
||||
return []RefundStatus{REFUND_PENDING, REFUND_APPROVED, REFUND_REJECTED, REFUND_PROCESSING, REFUND_COMPLETED, REFUND_CANCELLED}
|
||||
}
|
||||
|
||||
// Refund représente une demande de remboursement sur un paiement validé.
|
||||
type Refund struct {
|
||||
utils.AbstractObject
|
||||
PaymentID string `json:"payment_id" bson:"payment_id" validate:"required"`
|
||||
BillID string `json:"bill_id,omitempty" bson:"bill_id,omitempty"`
|
||||
InvoiceID string `json:"invoice_id,omitempty" bson:"invoice_id,omitempty"`
|
||||
RefundType pricing.RefundType `json:"refund_type" bson:"refund_type"`
|
||||
Amount float64 `json:"amount" bson:"amount" validate:"required"`
|
||||
Currency string `json:"currency" bson:"currency" default:"EUR"`
|
||||
Reason string `json:"reason,omitempty" bson:"reason,omitempty"`
|
||||
Status RefundStatus `json:"status" bson:"status"`
|
||||
RequestedAt time.Time `json:"requested_at" bson:"requested_at"`
|
||||
ProcessedAt *time.Time `json:"processed_at,omitempty" bson:"processed_at,omitempty"`
|
||||
ProcessedByID string `json:"processed_by_id,omitempty" bson:"processed_by_id,omitempty"`
|
||||
TransactionID string `json:"transaction_id,omitempty" bson:"transaction_id,omitempty"`
|
||||
Notes string `json:"notes,omitempty" bson:"notes,omitempty"`
|
||||
// ratio appliqué sur le montant original (0-100). 0 = non renseigné (remboursement total).
|
||||
RefundRatio float64 `json:"refund_ratio,omitempty" bson:"refund_ratio,omitempty"`
|
||||
}
|
||||
|
||||
// NewRefund crée une demande de remboursement total.
|
||||
func NewRefund(paymentID, billID string, amount float64, currency string, refundType pricing.RefundType, reason string) *Refund {
|
||||
return &Refund{
|
||||
PaymentID: paymentID,
|
||||
BillID: billID,
|
||||
Amount: amount,
|
||||
Currency: currency,
|
||||
RefundType: refundType,
|
||||
Reason: reason,
|
||||
Status: REFUND_PENDING,
|
||||
RequestedAt: time.Now().UTC(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewPartialRefund crée une demande de remboursement partiel selon un ratio pourcentage.
|
||||
func NewPartialRefund(paymentID, billID string, originalAmount, ratioPercent float64, currency string, refundType pricing.RefundType, reason string) *Refund {
|
||||
amount := originalAmount * ratioPercent / 100
|
||||
r := NewRefund(paymentID, billID, amount, currency, refundType, reason)
|
||||
r.RefundRatio = ratioPercent
|
||||
return r
|
||||
}
|
||||
|
||||
// Approve approuve la demande de remboursement.
|
||||
func (r *Refund) Approve(processedByID string) {
|
||||
r.Status = REFUND_APPROVED
|
||||
r.ProcessedByID = processedByID
|
||||
}
|
||||
|
||||
// Reject rejette la demande de remboursement.
|
||||
func (r *Refund) Reject(processedByID, notes string) {
|
||||
now := time.Now().UTC()
|
||||
r.Status = REFUND_REJECTED
|
||||
r.ProcessedByID = processedByID
|
||||
r.ProcessedAt = &now
|
||||
r.Notes = notes
|
||||
}
|
||||
|
||||
// Process passe le remboursement en cours de traitement.
|
||||
func (r *Refund) Process() bool {
|
||||
if r.Status != REFUND_APPROVED {
|
||||
return false
|
||||
}
|
||||
r.Status = REFUND_PROCESSING
|
||||
return true
|
||||
}
|
||||
|
||||
// Complete finalise le remboursement avec l'identifiant de transaction.
|
||||
func (r *Refund) Complete(transactionID string) {
|
||||
now := time.Now().UTC()
|
||||
r.Status = REFUND_COMPLETED
|
||||
r.TransactionID = transactionID
|
||||
r.ProcessedAt = &now
|
||||
}
|
||||
|
||||
// Cancel annule la demande si elle est encore en attente.
|
||||
func (r *Refund) Cancel() bool {
|
||||
if r.Status != REFUND_PENDING {
|
||||
return false
|
||||
}
|
||||
r.Status = REFUND_CANCELLED
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Refund) GetAccessor(request *tools.APIRequest) utils.Accessor {
|
||||
return NewAccessor(request)
|
||||
}
|
||||
|
||||
func (r *Refund) StoreDraftDefault() {
|
||||
r.IsDraft = true
|
||||
}
|
||||
|
||||
func (r *Refund) CanUpdate(set utils.DBObject) (bool, utils.DBObject) {
|
||||
incoming := set.(*Refund)
|
||||
if !r.IsDraft && r.Status != incoming.Status {
|
||||
return true, &Refund{
|
||||
Status: incoming.Status,
|
||||
TransactionID: incoming.TransactionID,
|
||||
Notes: incoming.Notes,
|
||||
ProcessedByID: incoming.ProcessedByID,
|
||||
}
|
||||
}
|
||||
return r.IsDraft, set
|
||||
}
|
||||
|
||||
func (r *Refund) CanDelete() bool {
|
||||
return r.IsDraft || r.Status == REFUND_PENDING
|
||||
}
|
||||
Reference in New Issue
Block a user