@@ -88,6 +88,19 @@ func (c *CheckoutRepository) GetBySessionID(sessionID string) (*entity.Checkout,
8888 return & checkout , nil
8989}
9090
91+ // GetAbandonedBySessionID implements repository.CheckoutRepository.
92+ func (c * CheckoutRepository ) GetAbandonedBySessionID (sessionID string ) (* entity.Checkout , error ) {
93+ var checkout entity.Checkout
94+ err := c .db .Preload ("Items" ).Preload ("Items.Product" ).Preload ("Items.ProductVariant" ).
95+ Preload ("User" ).
96+ Where ("session_id = ? AND status = ?" , sessionID , entity .CheckoutStatusAbandoned ).
97+ First (& checkout ).Error
98+ if err != nil {
99+ return nil , err
100+ }
101+ return & checkout , nil
102+ }
103+
91104// GetByUserID implements repository.CheckoutRepository.
92105func (c * CheckoutRepository ) GetByUserID (userID uint ) (* entity.Checkout , error ) {
93106 var checkout entity.Checkout
@@ -207,7 +220,55 @@ func (c *CheckoutRepository) HasActiveCheckoutsWithProduct(productID uint) (bool
207220
208221// Update implements repository.CheckoutRepository.
209222func (c * CheckoutRepository ) Update (checkout * entity.Checkout ) error {
210- return c .db .Session (& gorm.Session {FullSaveAssociations : true }).Save (checkout ).Error
223+ return c .db .Transaction (func (tx * gorm.DB ) error {
224+ // First, get the current items in the database
225+ var currentItems []entity.CheckoutItem
226+ if err := tx .Where ("checkout_id = ?" , checkout .ID ).Find (& currentItems ).Error ; err != nil {
227+ return fmt .Errorf ("failed to fetch current checkout items: %w" , err )
228+ }
229+
230+ // Create a map of current item IDs in the checkout entity for efficient lookup
231+ currentItemIDs := make (map [uint ]bool )
232+ for _ , item := range checkout .Items {
233+ if item .ID != 0 {
234+ currentItemIDs [item .ID ] = true
235+ }
236+ }
237+
238+ // Delete items that are no longer in the checkout
239+ for _ , dbItem := range currentItems {
240+ if ! currentItemIDs [dbItem .ID ] {
241+ if err := tx .Unscoped ().Delete (& dbItem ).Error ; err != nil {
242+ return fmt .Errorf ("failed to delete checkout item %d: %w" , dbItem .ID , err )
243+ }
244+ }
245+ }
246+
247+ // Save the checkout with remaining items
248+ return tx .Session (& gorm.Session {FullSaveAssociations : true }).Save (checkout ).Error
249+ })
250+ }
251+
252+ // GetAllExpiredCheckoutsForDeletion implements repository.CheckoutRepository.
253+ func (c * CheckoutRepository ) GetAllExpiredCheckoutsForDeletion () ([]* entity.Checkout , error ) {
254+ var checkouts []* entity.Checkout
255+
256+ // Get all checkouts that are expired, abandoned, or completed (older than 30 days to be safe)
257+ thirtyDaysAgo := time .Now ().AddDate (0 , 0 , - 30 )
258+
259+ err := c .db .Preload ("Items" ).Preload ("Items.Product" ).Preload ("Items.ProductVariant" ).
260+ Where ("status IN (?, ?, ?) OR updated_at < ?" ,
261+ entity .CheckoutStatusExpired ,
262+ entity .CheckoutStatusAbandoned ,
263+ entity .CheckoutStatusCompleted ,
264+ thirtyDaysAgo ).
265+ Find (& checkouts ).Error
266+
267+ if err != nil {
268+ return nil , fmt .Errorf ("failed to get expired checkouts for deletion: %w" , err )
269+ }
270+
271+ return checkouts , nil
211272}
212273
213274// NewCheckoutRepository creates a new GORM-based CheckoutRepository
0 commit comments