littleshop/VARIANT_CSV_FORMAT.md
SysAdmin 062916d5ce Fix: CSV import now creates ProductVariants instead of ProductMultiBuys
CRITICAL BUG FIX: Orders were totaling £0 because imported products had:
- Base price set to £0
- Variants stored as ProductMultiBuys (not ProductVariants)
- Order creation couldn't find variant prices → used base price of £0

Changes:
- CSV import now detects format: semicolons (;) = variants, colons (:) = multi-buys
- Added ImportProductVariantsAsync() to handle pipe-delimited variant format
- Format: "value; price; stock|value; price; stock" (e.g., "10; 30.00; 100|25; 70.00; 50")
- Updated CSV export to prioritize ProductVariants over MultiBuys
- Updated CSV template with correct variant format examples
- Added comprehensive documentation in VARIANT_CSV_FORMAT.md

Migration Required:
- Existing products with incorrect MultiBuy data need re-import
- Convert format from "name:qty:price;name:qty:price" to "value; price; stock|value; price; stock"
- Ensure base price is 0 for variant-based products

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-08 18:31:46 +01:00

3.6 KiB

Product Variant CSV Import Format

Overview

As of the latest update, the CSV import system now correctly creates ProductVariant records instead of ProductMultiBuy records when using semicolon-delimited variations.

CSV Column Format

Name,Description,Price,Weight,WeightUnit,StockQuantity,CategoryName,IsActive,Variations,PhotoUrls

Product Base Price and Stock

  • Set Price to 0 if using variants (variant prices override base price)
  • Set StockQuantity to 0 if using variants (variant stock is tracked separately)

Variations Column Format

Use pipe | to separate multiple variants, semicolons ; to separate the three required parts:

"value; price; stock|value; price; stock|value; price; stock"

Format Components:

  • value: Variant name/value (e.g., "10", "25", "3.5g", "7g")
  • price: Price for this variant as decimal (e.g., 30.00)
  • stock: Stock level for this variant as integer (e.g., 100)

Example - Quantity-based variants:

"Buprenorphine 2mg",0,150,Grams,0,Pharmaceuticals,true,"10; 30.00; 100|25; 70.00; 50|50; 130.00; 25",""

This creates:

  • Variant "10" at £30.00 with 100 in stock
  • Variant "25" at £70.00 with 50 in stock
  • Variant "50" at £130.00 with 25 in stock

Example - Weight-based variants:

"Cannabis Flower",0,200,Grams,0,Botanicals,true,"3.5g; 35.00; 10|7g; 65.00; 8|14g; 120.00; 5",""

This creates:

  • Variant "3.5g" at £35.00 with 10 in stock
  • Variant "7g" at £65.00 with 8 in stock
  • Variant "14g" at £120.00 with 5 in stock

Legacy ProductMultiBuy Format (Still Supported)

Old multi-buy format using colons : (no semicolons):

"Name:Quantity:Price;Name:Quantity:Price"

Example:

"Example Product",29.99,150,Grams,50,Electronics,true,"Single:1:29.99;Twin Pack:2:55.00",""

Variant Type Detection

The system automatically determines variant type based on the value:

  • Contains "g" (grams): Weight variant type
  • Otherwise: Quantity variant type

CSV Import Behavior

  1. Semicolon Detection: If the Variations column contains semicolons (;), it's treated as ProductVariant format
  2. Colon-Only Format: If only colons (:) are present, it's treated as legacy ProductMultiBuy format
  3. Empty Variations: Product uses base Price and StockQuantity

Exporting Products

When exporting products to CSV:

  • Products with ProductVariants export in the pipe-delimited format: "value; price; stock|value; price; stock"
  • Products with ProductMultiBuys export in the legacy colon format: "name:qty:price;name:qty:price"

Template Download

Download the CSV template from Admin Panel → Products → Import CSV → Download Template to see the correct format with examples.

Migration from Old Format

If you previously imported products using the old format (semicolons but creating MultiBuys), you'll need to:

  1. Delete existing products with incorrect MultiBuy data
  2. Re-import using the corrected pipe-delimited format shown above
  3. Ensure product base Price is set to 0 when using variants

Order Creation

When customers order products with variants:

  • TeleBot automatically passes the ProductVariantId to the order API
  • OrderService uses the variant's Price property to calculate the order total
  • If variant Price is null, it falls back to product base price (which should be 0 for variant-based products)

Technical Implementation

See ProductImportService.cs:

  • ImportProductVariantsAsync(): Handles pipe-delimited variant format
  • ImportProductMultiBuysAsync(): Handles legacy colon-delimited multi-buy format
  • Detection logic at line ~239