refactor/checkout (#8)
Co-authored-by: matst80 <mats.tornberg@gmail.com> Reviewed-on: #8 Co-authored-by: Mats Törnberg <mats@tornberg.me> Co-committed-by: Mats Törnberg <mats@tornberg.me>
This commit was merged in pull request #8.
This commit is contained in:
@@ -2,11 +2,9 @@ package cart
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
messages "git.k6n.net/go-cart-actor/pkg/messages"
|
||||
"git.k6n.net/go-cart-actor/pkg/voucher"
|
||||
"github.com/matst80/go-redis-inventory/pkg/inventory"
|
||||
)
|
||||
@@ -55,14 +53,6 @@ type CartItem struct {
|
||||
ReservationEndTime *time.Time `json:"reservationEndTime,omitempty"`
|
||||
}
|
||||
|
||||
type CartDelivery struct {
|
||||
Id uint32 `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
Price Price `json:"price"`
|
||||
Items []uint32 `json:"items"`
|
||||
PickupPoint *messages.PickupPoint `json:"pickupPoint,omitempty"`
|
||||
}
|
||||
|
||||
type CartNotification struct {
|
||||
LinkedId int `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
@@ -84,103 +74,46 @@ type Notice struct {
|
||||
Code *string `json:"code,omitempty"`
|
||||
}
|
||||
|
||||
type PaymentStatus string
|
||||
type CartPaymentStatus PaymentStatus
|
||||
type CartPaymentStatus string
|
||||
|
||||
const (
|
||||
PaymentStatusPending PaymentStatus = "pending"
|
||||
PaymentStatusFailed PaymentStatus = "failed"
|
||||
PaymentStatusSuccess PaymentStatus = "success"
|
||||
CartPaymentStatusPending CartPaymentStatus = "pending"
|
||||
CartPaymentStatusFailed CartPaymentStatus = "failed"
|
||||
CartPaymentStatusSuccess CartPaymentStatus = "success"
|
||||
CartPaymentStatusCancelled CartPaymentStatus = "partial"
|
||||
)
|
||||
|
||||
type CartPayment struct {
|
||||
PaymentId string `json:"paymentId"`
|
||||
Status PaymentStatus `json:"status"`
|
||||
Amount int64 `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Method *string `json:"method,omitempty"`
|
||||
Events []*PaymentEvent `json:"events,omitempty"`
|
||||
ProcessorReference *string `json:"processorReference,omitempty"`
|
||||
StartedAt *time.Time `json:"startedAt,omitempty"`
|
||||
CompletedAt *time.Time `json:"completedAt,omitempty"`
|
||||
}
|
||||
|
||||
type PaymentEvent struct {
|
||||
Name string `json:"name"`
|
||||
Success bool `json:"success"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
func (p *CartPayment) IsSettled() bool {
|
||||
if p == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch p.Status {
|
||||
case PaymentStatusSuccess:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type Marking struct {
|
||||
Type uint32 `json:"type"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type GiftcardItem struct {
|
||||
Id uint32 `json:"id"`
|
||||
Value Price `json:"value"`
|
||||
DeliveryDate string `json:"deliveryDate"`
|
||||
Recipient string `json:"recipient"`
|
||||
RecipientType string `json:"recipientType"`
|
||||
Message string `json:"message"`
|
||||
DesignConfig json.RawMessage `json:"designConfig,omitempty"`
|
||||
}
|
||||
|
||||
type CartGrain struct {
|
||||
mu sync.RWMutex
|
||||
lastItemId uint32
|
||||
lastDeliveryId uint32
|
||||
lastVoucherId uint32
|
||||
lastGiftcardId uint32
|
||||
lastAccess time.Time
|
||||
lastChange time.Time // unix seconds of last successful mutation (replay sets from event ts)
|
||||
userId string
|
||||
Version uint `json:"version"`
|
||||
InventoryReserved bool `json:"inventoryReserved"`
|
||||
Id CartId `json:"id"`
|
||||
Items []*CartItem `json:"items"`
|
||||
Giftcards []*GiftcardItem `json:"giftcards,omitempty"`
|
||||
TotalPrice *Price `json:"totalPrice"`
|
||||
TotalDiscount *Price `json:"totalDiscount"`
|
||||
Deliveries []*CartDelivery `json:"deliveries,omitempty"`
|
||||
Processing bool `json:"processing"`
|
||||
PaymentInProgress uint16 `json:"paymentInProgress"`
|
||||
OrderReference string `json:"orderReference,omitempty"`
|
||||
PaymentStatus PaymentStatus `json:"paymentStatus,omitempty"`
|
||||
PaidInFull bool `json:"paidInFull"`
|
||||
Vouchers []*Voucher `json:"vouchers,omitempty"`
|
||||
Notifications []CartNotification `json:"cartNotification,omitempty"`
|
||||
SubscriptionDetails map[string]*SubscriptionDetails `json:"subscriptionDetails,omitempty"`
|
||||
PaymentDeclinedNotices []Notice `json:"paymentDeclinedNotices,omitempty"`
|
||||
Payments []*CartPayment `json:"payments,omitempty"`
|
||||
Confirmation *ConfirmationStatus `json:"confirmation,omitempty"`
|
||||
//CheckoutOrderId string `json:"checkoutOrderId,omitempty"`
|
||||
CheckoutStatus CartPaymentStatus `json:"checkoutStatus,omitempty"`
|
||||
//CheckoutCountry string `json:"checkoutCountry,omitempty"`
|
||||
}
|
||||
mu sync.RWMutex
|
||||
lastItemId uint32
|
||||
lastVoucherId uint32
|
||||
lastAccess time.Time
|
||||
lastChange time.Time // unix seconds of last successful mutation (replay sets from event ts)
|
||||
userId string
|
||||
Currency string `json:"currency"`
|
||||
Language string `json:"language"`
|
||||
Version uint `json:"version"`
|
||||
InventoryReserved bool `json:"inventoryReserved"`
|
||||
Id CartId `json:"id"`
|
||||
Items []*CartItem `json:"items"`
|
||||
TotalPrice *Price `json:"totalPrice"`
|
||||
TotalDiscount *Price `json:"totalDiscount"`
|
||||
Processing bool `json:"processing"`
|
||||
//PaymentInProgress uint16 `json:"paymentInProgress"`
|
||||
OrderReference string `json:"orderReference,omitempty"`
|
||||
|
||||
type ConfirmationStatus struct {
|
||||
Code *string `json:"code,omitempty"`
|
||||
ViewCount int `json:"viewCount"`
|
||||
LastViewedAt time.Time `json:"lastViewedAt"`
|
||||
Vouchers []*Voucher `json:"vouchers,omitempty"`
|
||||
Notifications []CartNotification `json:"cartNotification,omitempty"`
|
||||
SubscriptionDetails map[string]*SubscriptionDetails `json:"subscriptionDetails,omitempty"`
|
||||
|
||||
//CheckoutOrderId string `json:"checkoutOrderId,omitempty"`
|
||||
CheckoutStatus *CartPaymentStatus `json:"checkoutStatus,omitempty"`
|
||||
//CheckoutCountry string `json:"checkoutCountry,omitempty"`
|
||||
}
|
||||
|
||||
type Voucher struct {
|
||||
@@ -243,19 +176,14 @@ func (v *Voucher) AppliesTo(cart *CartGrain) ([]*CartItem, bool) {
|
||||
func NewCartGrain(id uint64, ts time.Time) *CartGrain {
|
||||
return &CartGrain{
|
||||
lastItemId: 0,
|
||||
lastDeliveryId: 0,
|
||||
lastVoucherId: 0,
|
||||
lastGiftcardId: 0,
|
||||
lastAccess: ts,
|
||||
lastChange: ts,
|
||||
TotalDiscount: NewPrice(),
|
||||
Vouchers: []*Voucher{},
|
||||
Deliveries: []*CartDelivery{},
|
||||
Giftcards: []*GiftcardItem{},
|
||||
Id: CartId(id),
|
||||
Items: []*CartItem{},
|
||||
TotalPrice: NewPrice(),
|
||||
Payments: []*CartPayment{},
|
||||
SubscriptionDetails: make(map[string]*SubscriptionDetails),
|
||||
}
|
||||
}
|
||||
@@ -294,33 +222,6 @@ func (c *CartGrain) GetState() ([]byte, error) {
|
||||
return json.Marshal(c)
|
||||
}
|
||||
|
||||
func (c *CartGrain) ItemsWithDelivery() []uint32 {
|
||||
ret := make([]uint32, 0, len(c.Items))
|
||||
for _, item := range c.Items {
|
||||
for _, delivery := range c.Deliveries {
|
||||
for _, id := range delivery.Items {
|
||||
if item.Id == id {
|
||||
ret = append(ret, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *CartGrain) ItemsWithoutDelivery() []uint32 {
|
||||
ret := make([]uint32, 0, len(c.Items))
|
||||
hasDelivery := c.ItemsWithDelivery()
|
||||
for _, item := range c.Items {
|
||||
found := slices.Contains(hasDelivery, item.Id)
|
||||
|
||||
if !found {
|
||||
ret = append(ret, item.Id)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *CartGrain) FindItemWithSku(sku string) (*CartItem, bool) {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
@@ -332,73 +233,6 @@ func (c *CartGrain) FindItemWithSku(sku string) (*CartItem, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (c *CartGrain) FindPayment(paymentId string) (*CartPayment, bool) {
|
||||
if paymentId == "" {
|
||||
return nil, false
|
||||
}
|
||||
for _, payment := range c.Payments {
|
||||
if payment != nil && payment.PaymentId == paymentId {
|
||||
return payment, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (c *CartGrain) SettledPayments() []*CartPayment {
|
||||
if len(c.Payments) == 0 {
|
||||
return nil
|
||||
}
|
||||
settled := make([]*CartPayment, 0, len(c.Payments))
|
||||
for _, payment := range c.Payments {
|
||||
if payment != nil && payment.IsSettled() {
|
||||
settled = append(settled, payment)
|
||||
}
|
||||
}
|
||||
if len(settled) == 0 {
|
||||
return nil
|
||||
}
|
||||
return settled
|
||||
}
|
||||
|
||||
func (c *CartGrain) OpenPayments() []*CartPayment {
|
||||
if len(c.Payments) == 0 {
|
||||
return nil
|
||||
}
|
||||
pending := make([]*CartPayment, 0, len(c.Payments))
|
||||
for _, payment := range c.Payments {
|
||||
if payment == nil {
|
||||
continue
|
||||
}
|
||||
if !payment.IsSettled() {
|
||||
pending = append(pending, payment)
|
||||
}
|
||||
}
|
||||
if len(pending) == 0 {
|
||||
return nil
|
||||
}
|
||||
return pending
|
||||
}
|
||||
|
||||
// func (c *CartGrain) Apply(content proto.Message, isReplay bool) (*CartGrain, error) {
|
||||
|
||||
// updated, err := ApplyRegistered(c, content)
|
||||
// if err != nil {
|
||||
// if err == ErrMutationNotRegistered {
|
||||
// return nil, fmt.Errorf("unsupported mutation type %T (not registered)", content)
|
||||
// }
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// // Sliding TTL: update lastChange only for non-replay successful mutations.
|
||||
// if updated != nil && !isReplay {
|
||||
// c.lastChange = time.Now()
|
||||
// c.lastAccess = time.Now()
|
||||
// go AppendCartEvent(c.Id, content)
|
||||
// }
|
||||
|
||||
// return updated, nil
|
||||
// }
|
||||
|
||||
func (c *CartGrain) UpdateTotals() {
|
||||
c.TotalPrice = NewPrice()
|
||||
c.TotalDiscount = NewPrice()
|
||||
@@ -423,12 +257,7 @@ func (c *CartGrain) UpdateTotals() {
|
||||
c.TotalPrice.Add(*rowTotal)
|
||||
|
||||
}
|
||||
for _, delivery := range c.Deliveries {
|
||||
c.TotalPrice.Add(delivery.Price)
|
||||
}
|
||||
for _, giftcard := range c.Giftcards {
|
||||
c.TotalPrice.Add(giftcard.Value)
|
||||
}
|
||||
|
||||
for _, voucher := range c.Vouchers {
|
||||
_, ok := voucher.AppliesTo(c)
|
||||
voucher.Applied = false
|
||||
|
||||
Reference in New Issue
Block a user