Implemented Rollback Functionality

This commit is contained in:
2025-08-06 15:18:44 -05:00
parent d741dd5466
commit 78818793f2
20 changed files with 6365 additions and 74 deletions

View File

@@ -0,0 +1,390 @@
# 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

View File

@@ -0,0 +1,117 @@
# Requirements Document
## Introduction
This feature involves adding a rollback functionality to the existing Shopify price updater application that reverses pricing changes by setting the main product price to the current compare-at price and removing the compare-at price. This allows store administrators to easily revert promotional pricing back to original prices for products filtered by specific tags. The solution will extend the existing Shopify GraphQL API infrastructure and provide both price updating and rollback capabilities within the same application.
## Requirements
### Requirement 1
**User Story:** As a store administrator, I want to rollback product prices for products with specific tags, so that I can easily revert promotional pricing to original prices.
#### Acceptance Criteria
1. WHEN the rollback script is executed THEN the system SHALL connect to Shopify using GraphQL API
2. WHEN connecting to Shopify THEN the system SHALL authenticate using existing API credentials from environment variables
3. WHEN querying products THEN the system SHALL filter products by a configurable tag
4. WHEN a matching product is found THEN the system SHALL check if it has a compare-at price
5. WHEN a product has a compare-at price THEN the system SHALL set the main price to the compare-at price value
6. WHEN setting the new price THEN the system SHALL remove the compare-at price (set to null)
7. WHEN a product has no compare-at price THEN the system SHALL skip the product and log a warning
### Requirement 2
**User Story:** As a store administrator, I want to configure the rollback script through environment variables, so that I can easily specify which products to rollback without modifying code.
#### Acceptance Criteria
1. WHEN the rollback script starts THEN the system SHALL load Shopify API credentials from existing .env file
2. WHEN loading configuration THEN the system SHALL read the target product tag from environment variables
3. IF required environment variables are missing THEN the system SHALL display an error message and exit gracefully
4. WHEN the tag is specified THEN the system SHALL use it to filter products for rollback
5. WHEN no tag is specified THEN the system SHALL display an error and require tag specification
### Requirement 3
**User Story:** As a store administrator, I want to see detailed feedback about the rollback process, so that I can verify the changes were applied correctly.
#### Acceptance Criteria
1. WHEN the rollback script starts THEN the system SHALL display the configuration being used
2. WHEN products are found THEN the system SHALL display the count of matching products
3. WHEN rolling back each product THEN the system SHALL log the product name, current price, compare-at price, and new price
4. WHEN a product is skipped THEN the system SHALL log the reason (no compare-at price)
5. WHEN all rollbacks are complete THEN the system SHALL display a summary of total products updated and skipped
### Requirement 4
**User Story:** As a store administrator, I want the rollback script to handle errors gracefully, so that partial failures don't prevent other products from being rolled back.
#### Acceptance Criteria
1. WHEN API rate limits are encountered THEN the system SHALL implement appropriate retry logic
2. WHEN a product rollback fails THEN the system SHALL log the error and continue with remaining products
3. WHEN network errors occur THEN the system SHALL retry the operation with exponential backoff
4. WHEN invalid product data is encountered THEN the system SHALL skip the product and log a warning
5. WHEN the script completes THEN the system SHALL exit with appropriate status codes
### Requirement 5
**User Story:** As a developer, I want the rollback script to reuse existing Shopify API infrastructure, so that I can maintain consistency and reduce code duplication.
#### Acceptance Criteria
1. WHEN implementing the rollback solution THEN the system SHALL use existing Shopify service components
2. WHEN querying products THEN the system SHALL use existing GraphQL query patterns
3. WHEN updating products THEN the system SHALL use existing GraphQL mutation infrastructure
4. WHEN handling API responses THEN the system SHALL reuse existing error handling patterns
5. WHEN managing API connections THEN the system SHALL use existing authentication and session management
### Requirement 6
**User Story:** As a store administrator, I want the rollback script to validate data before making changes, so that I can avoid unintended price modifications.
#### Acceptance Criteria
1. WHEN processing a product THEN the system SHALL verify the product has variants with compare-at prices
2. WHEN a compare-at price exists THEN the system SHALL validate it is a positive number
3. WHEN rolling back prices THEN the system SHALL ensure the compare-at price is different from current price
4. WHEN a product variant has no compare-at price THEN the system SHALL skip that variant and log the reason
5. WHEN validation fails THEN the system SHALL skip the product and continue processing others
### Requirement 7
**User Story:** As a developer, I want the rollback script to maintain a progress log, so that I can track what rollback operations have been completed and reference them later.
#### Acceptance Criteria
1. WHEN the rollback script starts THEN the system SHALL create or append to a Progress.md file
2. WHEN each product is processed THEN the system SHALL log the rollback operation details to Progress.md
3. WHEN the script completes THEN the system SHALL write a summary to Progress.md with timestamp
4. WHEN errors occur THEN the system SHALL log error details to Progress.md for debugging
5. WHEN the script runs multiple times THEN the system SHALL append new progress entries without overwriting previous runs
### Requirement 8
**User Story:** As a store administrator, I want to run the rollback as an additional mode within the existing application, so that I can use both price updating and rollback functionality from the same tool.
#### Acceptance Criteria
1. WHEN running the application THEN the system SHALL support both price update and rollback modes
2. WHEN rollback mode is specified THEN the system SHALL perform rollback operations instead of price updates
3. WHEN logging progress THEN the system SHALL distinguish rollback entries from regular price update entries in the same Progress.md file
4. WHEN displaying console output THEN the system SHALL use clear messaging that indicates which operation mode is active
5. WHEN the rollback completes THEN the system SHALL provide a summary specific to rollback operations while maintaining compatibility with existing functionality
### Requirement 9
**User Story:** As a store administrator, I want to choose between price update and rollback modes when running the application, so that I can perform both operations using the same tool and configuration.
#### Acceptance Criteria
1. WHEN starting the application THEN the system SHALL determine the operation mode based on configuration or command line parameters
2. WHEN price update mode is selected THEN the system SHALL perform the existing price adjustment functionality
3. WHEN rollback mode is selected THEN the system SHALL perform the rollback functionality
4. WHEN no mode is specified THEN the system SHALL default to price update mode for backward compatibility
5. WHEN either mode is executed THEN the system SHALL use the same environment configuration and Shopify API infrastructure

View File

@@ -0,0 +1,86 @@
# Implementation Plan
- [x] 1. Extend environment configuration to support operation mode
- Add OPERATION_MODE environment variable loading and validation in config/environment.js
- Set default operation mode to "update" for backward compatibility
- Validate operation mode is either "update" or "rollback"
- Update .env.example file with new OPERATION_MODE variable
- _Requirements: 2.1, 2.2, 9.4, 9.5_
- [x] 2. Add rollback price calculation utilities
- Create validateRollbackEligibility function in utils/price.js to check if variant has valid compare-at price
- Create prepareRollbackUpdate function in utils/price.js to prepare rollback price update objects
- Add unit tests for rollback price utility functions
- _Requirements: 6.1, 6.2, 6.3, 6.4_
- [x] 3. Extend product service with rollback validation methods
- Add validateProductsForRollback method to services/product.js to filter products eligible for rollback
- Implement logic to skip products/variants without compare-at prices
- Add logging for validation warnings when products cannot be rolled back
- Write unit tests for rollback validation methods
- _Requirements: 1.7, 6.1, 6.4, 6.5_
- [x] 4. Implement core rollback functionality in product service
- Add rollbackVariantPrice method to services/product.js to update individual variant prices
- Implement rollbackProductPrices method to orchestrate batch rollback operations
- Add processProductForRollback method to handle individual product rollback processing
- Use existing GraphQL mutation infrastructure for price updates
- _Requirements: 1.4, 1.5, 1.6, 5.1, 5.2, 5.3_
- [x] 5. Extend logging utilities for rollback operations
- Add logRollbackStart method to utils/logger.js to log rollback operation initialization
- Add logRollbackUpdate method to utils/logger.js to log successful rollback operations
- Add logRollbackSummary method to utils/logger.js for rollback completion summaries
- Ensure rollback logs are distinguished from price update logs in Progress.md
- _Requirements: 3.1, 3.3, 3.5, 7.1, 7.2, 7.3, 8.3_
- [x] 6. Implement rollback workflow in main application
- Add operation mode detection logic to src/index.js based on configuration
- Create fetchAndValidateProductsForRollback method in main application class
- Create rollbackPrices method to execute rollback operations
- Create displayRollbackSummary method for rollback-specific result display
- _Requirements: 8.1, 8.2, 8.4, 8.5, 9.1, 9.2, 9.3_
- [x] 7. Integrate dual operation mode routing
- Modify main application run method to route between update and rollback workflows
- Ensure both operation modes use the same error handling and infrastructure
- Maintain backward compatibility when operation mode is not specified
- Add operation mode indication in console output and logging
- _Requirements: 9.1, 9.2, 9.3, 9.4, 9.5_
- [x] 8. Add comprehensive error handling for rollback operations
- Implement graceful handling of products without compare-at prices
- Add retry logic for rollback API operations using existing patterns
- Ensure rollback errors are properly logged and don't stop processing of other products
- Add rollback-specific error analysis in completion summaries
- _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5_
- [x] 9. Update package.json scripts for rollback mode
- Add npm script for running rollback operations
- Update existing scripts to maintain backward compatibility
- Add script documentation for both operation modes
- _Requirements: 8.1, 8.2_
- [x] 10. Create comprehensive tests for rollback functionality
- Write unit tests for all new rollback utility functions
- Write integration tests for rollback product service methods
- Write end-to-end tests for complete rollback workflow
- Test dual operation mode functionality and backward compatibility
- _Requirements: All requirements - comprehensive testing coverage_
- [x] 11. Update documentation and examples
- Update .env.example with OPERATION_MODE variable and usage examples
- Add rollback operation examples and usage instructions
- Update any existing documentation to reflect dual operation mode capability
- _Requirements: 2.1, 8.4, 9.4_