Initial commit: Complete Shopify Price Updater implementation

- Full Node.js application with Shopify GraphQL API integration
- Compare At price support for promotional pricing
- Comprehensive error handling and retry logic
- Progress tracking with markdown logging
- Complete test suite with unit and integration tests
- Production-ready with proper exit codes and signal handling
This commit is contained in:
2025-08-05 10:05:05 -05:00
commit 1e6881ba86
29 changed files with 10663 additions and 0 deletions

View File

@@ -0,0 +1,224 @@
# Design Document
## Overview
The Shopify Price Updater is a Node.js command-line script that uses Shopify's GraphQL Admin API to bulk update product prices based on tag filtering. The script will be built using the `@shopify/shopify-api` package and will implement proper error handling, rate limiting, and progress tracking.
## Architecture
The application follows a modular architecture with clear separation of concerns:
```
shopify-price-updater/
├── src/
│ ├── config/
│ │ └── environment.js # Environment variable loading and validation
│ ├── services/
│ │ ├── shopify.js # Shopify API client and authentication
│ │ ├── product.js # Product querying and updating logic
│ │ └── progress.js # Progress logging functionality
│ ├── utils/
│ │ ├── price.js # Price calculation utilities
│ │ └── logger.js # Console and file logging utilities
│ └── index.js # Main application entry point
├── .env.example # Environment variable template
├── package.json
└── Progress.md # Generated progress log file
```
## Compare At Price Workflow
The Compare At price functionality works as follows:
1. **Price Capture**: When a product variant is processed, the current price is captured as the "original price"
2. **Price Calculation**: The new price is calculated by applying the percentage adjustment to the original price
3. **Compare At Assignment**: The original price (before adjustment) is set as the Compare At price
4. **Simultaneous Update**: Both the new price and Compare At price are updated in a single GraphQL mutation
5. **Progress Tracking**: All three values (original, new, and Compare At) are logged for transparency
This creates a promotional pricing display where customers can see both the current discounted price and the original price for comparison.
## Components and Interfaces
### Environment Configuration (`config/environment.js`)
- Loads and validates environment variables from `.env` file
- Required variables: `SHOPIFY_SHOP_DOMAIN`, `SHOPIFY_ACCESS_TOKEN`, `TARGET_TAG`, `PRICE_ADJUSTMENT_PERCENTAGE`
- Validates that percentage is a valid number and tag is not empty
- Exports configuration object with validated values
### Shopify Service (`services/shopify.js`)
- Initializes Shopify GraphQL client using `@shopify/shopify-api`
- Handles authentication and session management
- Provides methods for executing GraphQL queries and mutations
- Implements retry logic for rate limiting (HTTP 429 responses)
### Product Service (`services/product.js`)
- Implements GraphQL queries to fetch products by tag
- Handles pagination for large product sets using cursor-based pagination
- Implements GraphQL mutations for price and Compare At price updates
- Manages product variant price updates (products can have multiple variants)
- Sets Compare At price to the original price before applying percentage adjustment
- Automatically formats tag queries with "tag:" prefix if not already present
### Progress Service (`services/progress.js`)
- Creates and manages Progress.md file
- Logs operation start, product updates, errors, and completion summary
- Appends to existing file with timestamps for multiple runs
- Formats progress entries in markdown for readability
### Price Utilities (`utils/price.js`)
- Calculates new prices based on percentage adjustment
- Handles rounding to appropriate decimal places for currency
- Validates price ranges and handles edge cases (negative prices, zero prices)
- Provides functions to prepare price update objects with both price and Compare At price values
### Logger Utilities (`utils/logger.js`)
- Provides consistent logging to console and progress file
- Implements different log levels (info, warning, error)
- Formats output for both human readability and progress tracking
## Data Models
### Product Query Response
```graphql
query getProductsByTag($query: String!, $first: Int!, $after: String) {
products(first: $first, after: $after, query: $query) {
edges {
node {
id
title
tags
variants(first: 100) {
edges {
node {
id
price
compareAtPrice
}
}
}
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}
```
### Product Update Mutation
```graphql
mutation productVariantUpdate($input: ProductVariantInput!) {
productVariantUpdate(input: $input) {
productVariant {
id
price
compareAtPrice
}
userErrors {
field
message
}
}
}
```
### Configuration Object
```javascript
{
shopDomain: string,
accessToken: string,
targetTag: string,
priceAdjustmentPercentage: number
}
```
### Progress Entry
```javascript
{
timestamp: Date,
productId: string,
productTitle: string,
variantId: string,
oldPrice: number,
newPrice: number,
compareAtPrice: number,
status: 'success' | 'error',
errorMessage?: string
}
```
## Error Handling
### Rate Limiting
- Implement exponential backoff for HTTP 429 responses
- Use Shopify's rate limit headers to determine retry timing
- Maximum retry attempts: 3 with increasing delays (1s, 2s, 4s)
### API Errors
- Parse GraphQL userErrors from mutation responses
- Log specific error messages for debugging
- Continue processing remaining products when individual updates fail
### Network Errors
- Catch and handle network connectivity issues
- Implement retry logic for transient network failures
- Graceful degradation when API is temporarily unavailable
### Data Validation
- Validate product data before attempting updates
- Skip products with invalid price data
- Handle edge cases like products without variants
### Progress Tracking Errors
- Continue script execution even if progress logging fails
- Fallback to console-only logging if file writing fails
- Ensure critical operations aren't blocked by logging issues
## Testing Strategy
### Unit Tests
- Test price calculation utilities with various percentage values
- Test environment configuration loading and validation
- Test GraphQL query and mutation builders
- Test error handling scenarios with mocked API responses
### Integration Tests
- Test Shopify API authentication with test credentials
- Test product querying with known test data
- Test price update operations in Shopify development store
- Test progress logging functionality
### End-to-End Tests
- Test complete workflow with development store
- Verify price updates are applied correctly
- Test error recovery and continuation scenarios
- Validate progress logging accuracy
### Manual Testing Checklist
- Test with various percentage values (positive, negative, decimal)
- Test with products having multiple variants
- Test with large product sets requiring pagination
- Test error scenarios (invalid credentials, network issues)
- Verify Progress.md file generation and formatting

View File

@@ -0,0 +1,94 @@
# Requirements Document
## Introduction
This feature involves creating a Node.js script that connects to Shopify's GraphQL API to update product prices based on specific criteria. The script will filter products by a preset tag and adjust their prices by a configurable percentage (either increase or decrease). The solution will use Shopify's official Node.js API package and store configuration in environment variables for security and flexibility.
## Requirements
### Requirement 1
**User Story:** As a store administrator, I want to bulk update product prices for products with specific tags, so that I can efficiently manage pricing across my inventory.
#### Acceptance Criteria
1. WHEN the script is executed THEN the system SHALL connect to Shopify using GraphQL API
2. WHEN connecting to Shopify THEN the system SHALL authenticate using 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 update its price by the specified percentage
5. WHEN updating prices THEN the system SHALL support both price increases and decreases based on percentage value
6. WHEN updating a product price THEN the system SHALL set the original price as the "Compare At" price
7. WHEN the original price exists THEN the system SHALL preserve it as the Compare At price before applying the adjustment
### Requirement 2
**User Story:** As a store administrator, I want to configure the script through environment variables, so that I can easily change settings without modifying code.
#### Acceptance Criteria
1. WHEN the script starts THEN the system SHALL load Shopify API credentials from .env file
2. WHEN loading configuration THEN the system SHALL read the target product tag from environment variables
3. WHEN loading configuration THEN the system SHALL read the price adjustment percentage from environment variables
4. IF required environment variables are missing THEN the system SHALL display an error message and exit gracefully
5. WHEN percentage is positive THEN the system SHALL increase prices
6. WHEN percentage is negative THEN the system SHALL decrease prices
### Requirement 3
**User Story:** As a store administrator, I want to see detailed feedback about the price update process, so that I can verify the changes were applied correctly.
#### Acceptance Criteria
1. WHEN the 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 updating each product THEN the system SHALL log the product name, old price, new price, and Compare At price
4. WHEN all updates are complete THEN the system SHALL display a summary of total products updated
5. IF errors occur during updates THEN the system SHALL log error details and continue processing other products
### Requirement 4
**User Story:** As a store administrator, I want the script to handle errors gracefully, so that partial failures don't prevent other products from being updated.
#### Acceptance Criteria
1. WHEN API rate limits are encountered THEN the system SHALL implement appropriate retry logic
2. WHEN a product update 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 script to use Shopify's official Node.js package and GraphQL API, so that I can leverage well-maintained and efficient tools.
#### Acceptance Criteria
1. WHEN implementing the solution THEN the system SHALL use Shopify's official Node.js API package
2. WHEN querying products THEN the system SHALL use GraphQL queries for efficient data retrieval
3. WHEN updating products THEN the system SHALL use GraphQL mutations for price updates
4. WHEN handling API responses THEN the system SHALL properly parse GraphQL response structures
5. WHEN managing API connections THEN the system SHALL follow Shopify's best practices for authentication and session management
### Requirement 6
**User Story:** As a store administrator, I want the script to set Compare At prices to show customers the original price before adjustment, so that I can create effective promotional pricing displays.
#### Acceptance Criteria
1. WHEN a product price is being updated THEN the system SHALL capture the current price as the Compare At price
2. WHEN the Compare At price is set THEN the system SHALL use the original price value before any percentage adjustment
3. WHEN updating product variants THEN the system SHALL set both the new price and Compare At price in the same operation
4. WHEN a product already has a Compare At price THEN the system SHALL replace it with the current price before adjustment
5. WHEN logging price updates THEN the system SHALL include the Compare At price in the progress tracking
### Requirement 7
**User Story:** As a developer, I want the script to maintain a progress log, so that I can track what operations have been completed and reference them later.
#### Acceptance Criteria
1. WHEN the 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 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

View File

@@ -0,0 +1,112 @@
# Implementation Plan
- [x] 1. Set up project structure and dependencies
- Create package.json with required dependencies (@shopify/shopify-api, dotenv)
- Create directory structure (src/, config/, services/, utils/)
- Create .env.example file with required environment variables
- _Requirements: 2.1, 2.2, 2.3, 5.1_
- [x] 2. Implement environment configuration module
- Create config/environment.js to load and validate .env variables
- Implement validation for required Shopify credentials and configuration
- Add error handling for missing or invalid environment variables
- _Requirements: 2.1, 2.2, 2.3, 2.4_
- [x] 3. Create Shopify API service
- Implement services/shopify.js with GraphQL client initialization
- Add authentication using Shopify access token
- Implement retry logic for rate limiting and network errors
- _Requirements: 1.1, 1.2, 4.1, 4.3, 5.1, 5.5_
- [x] 4. Implement price calculation utilities
- Create utils/price.js with percentage-based price calculation functions
- Add validation for price ranges and edge cases
- Implement proper rounding for currency values
- Add function to prepare price update objects with Compare At price values
- _Requirements: 1.5, 2.5, 2.6, 6.1, 6.2_
- [x] 5. Create progress logging service
- Implement services/progress.js for Progress.md file management
- Add functions to log operation start, product updates, and completion summary
- Implement timestamp formatting and markdown structure
- _Requirements: 6.1, 6.2, 6.3, 6.4, 6.5_
- [x] 6. Implement console logging utilities
- Create utils/logger.js for consistent console and progress file logging
- Add different log levels (info, warning, error) with appropriate formatting
- Integrate with progress service for dual logging
- _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5_
- [x] 7. Create product querying functionality
- Implement GraphQL query in services/product.js to fetch products by tag
- Add cursor-based pagination handling for large product sets
- Include product variants in query response
- _Requirements: 1.3, 5.2, 5.4_
- [x] 8. Implement product price update functionality
- Add GraphQL mutation for updating product variant prices and Compare At prices
- Implement batch processing of product variants with Compare At price setting
- Add logic to capture original price before adjustment and set as Compare At price
- Add error handling for individual product update failures
- _Requirements: 1.4, 1.5, 1.6, 1.7, 4.2, 4.4, 5.3, 5.4, 6.1, 6.2, 6.3_
- [x] 9. Create main application entry point
- Implement src/index.js with complete workflow orchestration
- Add configuration loading, product fetching, and price updating sequence
- Implement error handling and graceful exit with appropriate status codes
- _Requirements: 3.1, 3.4, 4.5_
- [x] 10. Add comprehensive error handling and logging
- Integrate all error handling scenarios across modules
- Ensure progress logging continues even when individual operations fail
- Add final summary reporting with success/failure counts
- Update logging to include Compare At price information in progress tracking
- _Requirements: 3.3, 3.4, 3.5, 4.1, 4.2, 4.3, 4.4, 6.5, 7.4_
- [x] 11. Create unit tests for core utilities
- Write tests for price calculation functions with various scenarios
- Test environment configuration loading and validation
- Test progress logging functionality
- _Requirements: 1.5, 2.4, 2.5, 2.6, 6.1, 6.2, 6.3_
- [x] 12. Update existing implementation to support Compare At price functionality
- Modify price calculation utilities to handle Compare At price preparation
- Update GraphQL mutation to include compareAtPrice field in product variant updates
- Modify product update logic to capture original price and set as Compare At price
- Update progress logging to include Compare At price information
- _Requirements: 1.6, 1.7, 6.1, 6.2, 6.3, 6.4, 6.5_
- [x] 13. Write integration tests for Shopify API interactions
- Test GraphQL query execution with mock responses
- Test product update mutations with error scenarios
- Test rate limiting and retry logic
- Add tests for Compare At price functionality
- _Requirements: 1.1, 1.2, 1.3, 1.4, 4.1, 4.3, 5.2, 5.3, 6.3_
## Implementation Status
**All tasks completed successfully!**
The Shopify Price Updater implementation is fully complete with:
- **Core Functionality**: Complete price update workflow with Compare At price support
- **Error Handling**: Comprehensive retry logic, rate limiting, and graceful error recovery
- **Progress Tracking**: Detailed logging to Progress.md with timestamps and summaries
- **Testing**: Full test coverage including unit tests, integration tests, and edge cases
- **Configuration**: Robust environment variable validation and configuration management
- **Production Ready**: Proper exit codes, signal handling, and production-grade error handling
The application is ready for production use and meets all requirements specified in the design document.