Files
PriceUpdaterAppv2/.kiro/specs/price-rollback/design.md

391 lines
11 KiB
Markdown

# Design Document
## Overview
The Price Rollback feature extends the existing Shopify Price Updater application to support reversing pricing changes by setting the main product price to the current compare-at price and removing the compare-at price. This functionality will be integrated into the existing application architecture, providing dual operation modes (price update and rollback) within the same codebase and infrastructure.
## Architecture
The rollback functionality will be integrated into the existing modular architecture with minimal changes:
```
shopify-price-updater/
├── src/
│ ├── config/
│ │ └── environment.js # Extended to support operation mode configuration
│ ├── services/
│ │ ├── shopify.js # Existing Shopify API client (no changes)
│ │ ├── product.js # Extended with rollback methods
│ │ └── progress.js # Extended to log rollback operations
│ ├── utils/
│ │ ├── price.js # Extended with rollback price utilities
│ │ └── logger.js # Extended to distinguish operation types
│ └── index.js # Extended to support dual operation modes
├── .env.example # Updated with operation mode variable
├── package.json # Updated scripts for rollback mode
└── Progress.md # Contains both update and rollback logs
```
## Operation Mode Selection
The application will determine its operation mode through environment configuration:
### Environment Variable
- `OPERATION_MODE`: Controls which operation to perform
- `"update"` (default): Performs price updates with percentage adjustments
- `"rollback"`: Performs price rollbacks using compare-at prices
### Backward Compatibility
- If `OPERATION_MODE` is not specified, defaults to `"update"` mode
- All existing environment variables remain unchanged
- Existing scripts and workflows continue to work without modification
## Components and Interfaces
### Environment Configuration (`config/environment.js`)
**Extensions:**
- Add `OPERATION_MODE` environment variable loading and validation
- Validate operation mode is either "update" or "rollback"
- Export operation mode in configuration object
- Maintain backward compatibility when operation mode is not specified
**New Configuration Object:**
```javascript
{
shopDomain: string,
accessToken: string,
targetTag: string,
priceAdjustmentPercentage: number, // Only used in update mode
operationMode: 'update' | 'rollback' // New field
}
```
### Product Service (`services/product.js`)
**New Methods:**
1. **`validateProductsForRollback(products)`**
- Validates products have variants with compare-at prices
- Skips products/variants without compare-at prices
- Logs validation warnings for products that cannot be rolled back
- Returns array of products with rollback-eligible variants
2. **`rollbackProductPrices(products)`**
- Main rollback orchestration method
- Processes products in batches to manage rate limits
- Returns results object with rollback statistics
- Logs progress and errors during rollback operations
3. **`processProductForRollback(product, results)`**
- Processes individual product for rollback
- Iterates through variants and performs rollback operations
- Updates results object with success/failure counts
- Handles variant-level error logging
4. **`rollbackVariantPrice(variant, productId)`**
- Updates individual variant price to compare-at price value
- Sets compare-at price to null (removes it)
- Uses existing GraphQL mutation infrastructure
- Returns success/failure result with error details
**GraphQL Mutation for Rollback:**
```graphql
mutation productVariantsBulkUpdate(
$productId: ID!
$variants: [ProductVariantsBulkInput!]!
) {
productVariantsBulkUpdate(productId: $productId, variants: $variants) {
productVariants {
id
price
compareAtPrice
}
userErrors {
field
message
}
}
}
```
**Rollback Mutation Variables:**
```javascript
{
productId: "gid://shopify/Product/123",
variants: [{
id: "gid://shopify/ProductVariant/456",
price: "750.00", // Set to current compare-at price
compareAtPrice: null // Remove compare-at price
}]
}
```
### Price Utilities (`utils/price.js`)
**New Functions:**
1. **`validateRollbackEligibility(variant)`**
- Checks if variant has a valid compare-at price
- Validates compare-at price is different from current price
- Returns boolean indicating rollback eligibility
- Provides reason for ineligibility if applicable
2. **`prepareRollbackUpdate(variant)`**
- Prepares price update object for rollback operation
- Sets new price to current compare-at price value
- Sets compare-at price to null
- Validates the rollback operation is safe to perform
**Example Usage:**
```javascript
// Check if variant can be rolled back
const isEligible = validateRollbackEligibility(variant);
// Prepare rollback update
const rollbackUpdate = prepareRollbackUpdate(variant);
// Returns: { newPrice: 750.00, compareAtPrice: null }
```
### Logger Utilities (`utils/logger.js`)
**Extensions:**
1. **`logRollbackStart(config)`**
- Logs rollback operation start with configuration
- Distinguishes from price update operations in logs
- Includes operation mode in log entries
2. **`logRollbackUpdate(updateDetails)`**
- Logs successful rollback operations
- Includes original price, compare-at price, and new price
- Formats specifically for rollback operations
3. **`logRollbackSummary(results)`**
- Logs rollback completion summary
- Includes rollback-specific statistics
- Distinguishes from price update summaries
### Main Application (`index.js`)
**Extensions:**
1. **Operation Mode Detection:**
- Read operation mode from configuration
- Route to appropriate workflow based on mode
- Maintain single entry point for both operations
2. **Rollback Workflow Methods:**
- `fetchAndValidateProductsForRollback()`: Fetch and validate products for rollback
- `rollbackPrices(products)`: Execute rollback operations
- `displayRollbackSummary(results)`: Display rollback-specific summary
3. **Unified Error Handling:**
- Extend existing error handling to support rollback operations
- Maintain consistent error reporting across both modes
- Preserve existing signal handling and graceful shutdown
## Data Models
### Rollback Validation Result
```javascript
{
isEligible: boolean,
reason?: string, // Present if not eligible
variant: {
id: string,
currentPrice: number,
compareAtPrice: number | null
}
}
```
### Rollback Update Object
```javascript
{
newPrice: number, // Set to current compare-at price
compareAtPrice: null // Always null to remove compare-at price
}
```
### Rollback Results
```javascript
{
totalProducts: number,
totalVariants: number,
eligibleVariants: number, // New field for rollback
successfulRollbacks: number,
failedRollbacks: number,
skippedVariants: number, // Variants without compare-at prices
errors: Array<{
productId: string,
productTitle: string,
variantId: string,
errorMessage: string
}>
}
```
### Progress Entry for Rollback
```javascript
{
timestamp: Date,
operationType: 'rollback', // Distinguishes from 'update'
productId: string,
productTitle: string,
variantId: string,
oldPrice: number, // Original price before rollback
compareAtPrice: number, // Compare-at price being used as new price
newPrice: number, // New price (same as compare-at price)
status: 'success' | 'error' | 'skipped',
errorMessage?: string,
skipReason?: string // For variants without compare-at prices
}
```
## Error Handling
### Rollback-Specific Error Scenarios
1. **No Compare-At Price:**
- Skip variant and log warning
- Continue processing other variants
- Include in skipped count for summary
2. **Invalid Compare-At Price:**
- Skip variant if compare-at price is null, zero, or negative
- Log validation warning with specific reason
- Continue processing other variants
3. **Same Price Values:**
- Skip variant if current price equals compare-at price
- Log informational message (no rollback needed)
- Continue processing other variants
4. **API Update Failures:**
- Use existing retry logic for rate limiting
- Log specific error messages from Shopify API
- Continue processing remaining variants
### Enhanced Error Reporting
- Distinguish rollback errors from update errors in logs
- Provide rollback-specific error analysis in completion summary
- Include skipped variant statistics in error reporting
- Maintain existing error handling patterns for consistency
## Testing Strategy
### Unit Tests
**New Test Cases:**
- Test rollback price calculation utilities
- Test rollback eligibility validation
- Test rollback update object preparation
- Test operation mode configuration loading
**Extended Test Cases:**
- Test product service rollback methods
- Test logger rollback-specific methods
- Test main application rollback workflow
### Integration Tests
**New Test Scenarios:**
- Test rollback operations with development store
- Test rollback with products having various compare-at price scenarios
- Test rollback mode selection and configuration
- Test mixed scenarios (some variants eligible, some not)
**Extended Test Scenarios:**
- Test dual operation mode functionality
- Test backward compatibility with existing configurations
- Test progress logging for rollback operations
### End-to-End Tests
**Rollback Workflow Tests:**
- Test complete rollback workflow with test products
- Verify prices are correctly set to compare-at values
- Verify compare-at prices are removed after rollback
- Test error recovery and continuation scenarios
**Dual Mode Tests:**
- Test switching between update and rollback modes
- Test that both modes use same infrastructure correctly
- Verify progress logging distinguishes between operations
### Manual Testing Checklist
**Rollback Functionality:**
- Test rollback with products having compare-at prices
- Test rollback with products missing compare-at prices
- Test rollback with mixed variant scenarios
- Verify Progress.md logging for rollback operations
**Integration Testing:**
- Test backward compatibility with existing configurations
- Test operation mode switching
- Test that existing update functionality remains unchanged
- Verify error handling consistency across both modes
## Implementation Considerations
### Code Reuse Strategy
- Maximize reuse of existing Shopify API infrastructure
- Extend existing classes rather than creating new ones
- Maintain consistent error handling patterns
- Preserve existing logging and progress tracking mechanisms
### Performance Considerations
- Use same batching strategy as existing price updates
- Apply same rate limiting and retry logic
- Maintain existing pagination patterns for product fetching
- Preserve existing delay mechanisms between operations
### Backward Compatibility
- Default to existing behavior when operation mode not specified
- Maintain all existing environment variables and their behavior
- Preserve existing script entry points and command line usage
- Ensure existing Progress.md format remains compatible
### Configuration Management
- Add new environment variable with sensible default
- Validate operation mode values during configuration loading
- Provide clear error messages for invalid operation modes
- Update .env.example with new configuration option