Files
product_inventory/docs/ARCHITECTURE.md
Ben Miller 85cdfe1443 feat: implement status automation and router pattern
- Implemented modular status automation system (statusHandlers.ts).
- Added handlers for 'Published' (Active/Qty 1), 'Sold' (Active/Qty 0), and 'Drafted'.
- Refactored onEdit triggers into a central Router pattern in OnEditHandler.ts.
- Updated Product.ts to support explicit quantity setting (fixed 0 value bug).
- Updated shopifyApi.ts to implement SetInventoryItemQuantity (using ignoreCompareQuantity).
- Consolidated triggers into single onEditHandler.
- Updated project documentation.
2025-12-24 23:55:28 -07:00

3.9 KiB

Architecture Documentation

System Overview

This project serves as a bridge between Google Sheets and Shopify. It enables a two-way sync (primarily Sheets to Shopify for products) and allows managing inventory directly from a spreadsheet.

Core Flows

  1. Product Updates:

    • User edits a cell in the "product_inventory" sheet.
    • onEditQueue trigger fires, capturing the SKU and timestamp.
    • Edits are batched in PropertiesService (script properties).
    • A time-based trigger runs processBatchedEdits every minute.
    • The processing function locks the script, reads the queue, and pushes changes to Shopify via the Admin API.
  2. Order Sync:

    • Users can run menu commands to fetch orders from Shopify.
    • The Shop class fetches orders via the REST API, handling pagination.
    • Data is populated into specific sheets (_orders, _line_items, _customer, etc.).

Key Components

1. Queue System (src/onEditQueue.ts)

To avoid hitting Shopify API rate limits and Google Apps Script execution time limits, edits are not processed immediately.

  • onEditQueue(e):

    • Triggered on every cell edit.
    • Checks if the edit is valid (correct sheet, valid SKU).
    • Acquires a DocumentLock.
    • Updates a JSON list in ScriptProperties (pendingEdits).
    • Debounces edits (updates timestamp if SKU is already pending).
  • processBatchedEdits():

    • Run via time-based trigger (every 1 minute).
    • Acquires a ScriptLock.
    • Reads pendingEdits.
    • Filters for edits older than BATCH_INTERVAL_MS (30s) to allow for multiple quick edits to the same SKU.
    • Iterates through valid edits and calls Product.UpdateShopifyProduct.

2. Shopify Integration (src/shopifyApi.ts)

The project uses a hybrid approach for the Shopify Admin API:

  • REST API: Used primarily for fetching Orders (legacy support).
  • GraphQL API: Used for fetching and updating Products and Inventory.

The Shop class handles authentication using credentials stored in the "vars" sheet.

3. Configuration (src/config.ts)

Configuration, including API keys, is stored in a dedicated Google Sheet named "vars". The Config class reads these values at runtime using a vlookup style helper.

Required "vars" columns:

  • key: The name of the configuration variable.
  • value: The actual value.

4. Global Entry Points (src/global.ts)

Since Apps Script functions must be top-level to be triggered or attached to buttons, src/global.ts explicitly exposes necessary functions from the modules to the global scope.

5. Status Automation (src/statusHandlers.ts)

A modular system handles changes to the status column. It uses a registry of StatusHandler implementations:

  • Published: Sets Shopify Status ACTIVE, Quantity 1.
  • Sold/Artist Swap: Sets Shopify Status ACTIVE, Quantity 0.
  • Drafted: Sets Shopify Status DRAFT.

Triggers

Triggers are managed programmatically via src/triggers.ts. Running reinstallTriggers will wipe existing project triggers and set up the standard set:

  • onEdit -> onEditHandler (Main Router)
  • TimeBased (1 min) -> processBatchedEdits
  • TimeBased (10 min) -> checkRecentSales

5. Troubleshooting Panel (src/sidebar.ts, src/Sidebar.html)

A dedicated side panel provides visibility into the background queue system.

  • Backend (src/sidebar.ts):

    • getQueueStatus(): Returns the current state of the queue and global toggle.
    • setQueueEnabled(): Toggles the global queueEnabled script property.
    • deleteEdit() / pushEdit(): Manages specific items in the queue with safety checks.
  • Frontend (src/Sidebar.html):

    • Displays pending edits with timestamps.
    • Provides controls to globally enable/disable processing.
    • Allows manual intervention (delete/push) for individual items.