Files
go-cart-actor/CGM_LINE_ITEMS_SPEC.md
matst80 60cd6cfd51
All checks were successful
Build and Publish / BuildAndDeployAmd64 (push) Successful in 44s
Build and Publish / BuildAndDeployArm64 (push) Successful in 5m3s
update
2025-11-20 21:20:35 +01:00

5.0 KiB

go-cart-actor/CGM_LINE_ITEMS_SPEC.md

CGM (Customer Group Membership) Line Items Specification

This document specifies the implementation of Customer Group Membership (CGM) support in cart line items. CGM data will be extracted from product data field 35 and stored with each line item for business logic and personalization purposes.

Overview

CGM represents customer group membership information associated with products. This data needs to be:

  • Fetched from product data (stringfieldvalue 35)
  • Included in the AddItem proto message
  • Stored in cart line items (CartItem struct)
  • Accessible for business rules and personalization

Implementation Steps

1. Update Proto Messages

Add cgm field to the AddItem message in proto/messages.proto:

message AddItem {
  // ... existing fields ...
  string cgm = 25;  // Customer Group Membership from field 35
  // ... existing fields ...
}

Note: Use field number 25 (next available after existing fields).

2. Update Product Fetcher

Modify cmd/cart/product-fetcher.go to extract CGM from field 35:

func ToItemAddMessage(item *index.DataItem, storeId *string, qty int, country string) (*messages.AddItem, error) {
    // ... existing code ...
    
    cgm, _ := item.GetStringFieldValue(35)  // Extract CGM from field 35
    
    return &messages.AddItem{
        // ... existing fields ...
        Cgm: cgm,  // Add CGM field
        // ... existing fields ...
    }, nil
}

3. Update Cart Grain Structures

Add CGM field to ItemMeta struct in pkg/cart/cart-grain.go:

type ItemMeta struct {
    Name       string  `json:"name"`
    Brand      string  `json:"brand,omitempty"`
    Category   string  `json:"category,omitempty"`
    // ... existing fields ...
    Cgm        string  `json:"cgm,omitempty"`  // Customer Group Membership
    // ... existing fields ...
}

4. Update AddItem Mutation Handler

Modify the AddItem handler in pkg/cart/cart_mutations.go to populate the CGM field:

func AddItem(grain *CartGrain, req *messages.AddItem) error {
    // ... existing validation ...
    
    item := &CartItem{
        // ... existing fields ...
        Meta: &ItemMeta{
            Name:     req.Name,
            Brand:    req.Brand,
            // ... existing meta fields ...
            Cgm:      req.Cgm,  // Add CGM to item meta
            // ... existing meta fields ...
        },
        // ... existing fields ...
    }
    
    // ... rest of handler ...
}

5. Regenerate Proto Code

After updating proto/messages.proto, regenerate Go code:

cd proto
protoc --go_out=. --go_opt=paths=source_relative \
       --go-grpc_out=. --go-grpc_opt=paths=source_relative \
       messages.proto cart_actor.proto control_plane.proto

6. Update Tests

Add tests for CGM extraction and storage:

  • Unit test for ToItemAddMessage with CGM field
  • Integration test for AddItem mutation including CGM
  • Test that CGM is properly stored and retrieved in cart state

7. Update API Documentation

Update README.md and API examples to mention CGM field in line items.

Data Flow

  1. Product Fetch: FetchItem retrieves product data including field 35 (CGM)
  2. Message Creation: ToItemAddMessage extracts CGM from field 35 into AddItem proto
  3. Mutation Processing: AddItem handler stores CGM in CartItem.Meta.Cgm
  4. State Persistence: CGM is included in cart JSON serialization
  5. API Responses: CGM is returned in cart state responses

Business Logic Integration

CGM can be used for:

  • Personalized pricing rules
  • Group-specific discounts
  • Membership validation
  • Targeted promotions
  • Customer segmentation

Example usage in business logic:

func applyGroupDiscount(cart *CartGrain, userGroups []string) {
    for _, item := range cart.Items {
        if item.Meta != nil && slices.Contains(userGroups, item.Meta.Cgm) {
            // Apply group-specific discount
            item.Price = applyDiscount(item.Price, groupDiscountRate)
        }
    }
}

Backward Compatibility

  • CGM field is optional in proto (no required validation)
  • Existing carts without CGM will have empty string
  • Product fetcher gracefully handles missing field 35
  • API responses include CGM field (empty if not set)

Testing Checklist

  • Proto compilation succeeds
  • Product fetcher extracts CGM from field 35
  • AddItem mutation stores CGM in cart
  • Cart state includes CGM in JSON
  • API endpoints return CGM field
  • Existing functionality unaffected
  • Unit tests pass for CGM handling
  • Integration tests verify end-to-end flow

Configuration and Testability

Following project patterns:

  • CGM extraction is configurable via field index (currently 35)
  • Product fetcher interface allows mocking for tests
  • Mutation handlers are pure functions testable in isolation
  • Cart state serialization includes CGM for verification

This implementation maintains the project's standards for testability and configurability while adding CGM support to line items.