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

11 KiB

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:

{
  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:

mutation productVariantsBulkUpdate(
	$productId: ID!
	$variants: [ProductVariantsBulkInput!]!
) {
	productVariantsBulkUpdate(productId: $productId, variants: $variants) {
		productVariants {
			id
			price
			compareAtPrice
		}
		userErrors {
			field
			message
		}
	}
}

Rollback Mutation Variables:

{
  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:

// 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

{
  isEligible: boolean,
  reason?: string, // Present if not eligible
  variant: {
    id: string,
    currentPrice: number,
    compareAtPrice: number | null
  }
}

Rollback Update Object

{
  newPrice: number, // Set to current compare-at price
  compareAtPrice: null // Always null to remove compare-at price
}

Rollback Results

{
  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

{
  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