Commit Graph
35 Commits
Author SHA1 Message Date
Malek TellissiandClaude Sonnet 4.6 dd710cb1c0 Fix 404 on recipe history page
Deploy / deploy (push) Successful in 14s
bootedInteractsWithTable() calls table() before mount() sets $this->record.
Accessing $this->record eagerly causes a TypeError on the uninitialized typed
property, which Filament/Livewire converts to a 404.

Deferred all $this->record accesses into closures so they only execute at
render time (after mount() has run).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 18:30:07 +02:00
Malek TellissiandClaude Sonnet 4.6 656b105cb9 Show Shopify product ID as read-only field next to product name
Deploy / deploy (push) Successful in 14s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 18:24:44 +02:00
Malek TellissiandClaude Sonnet 4.6 3301a1e9b2 Fix 500 on recipe save and surface errors as notifications
Deploy / deploy (push) Successful in 14s
- Fix root cause: recipes_spices.amount_in_percent was decimal(4,2) which
  overflows on 100% — widened to decimal(6,2) via migration
- Wrap afterSave() in try-catch so DB/logic errors show as a persistent
  danger notification instead of a blank 500 page
- Same for CreateProduct: errors show as notification; also reads
  recipe_spices from raw Livewire $this->data (not $data param which
  excludes dehydrated(false) fields) so recipes actually save on create

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 18:19:31 +02:00
Malek TellissiandClaude Sonnet 4.6 811f5a015e Add Shopify pull-from feature and fix product creation payload
Deploy / deploy (push) Successful in 14s
- Add "Aus Shopify laden" button on product edit page that pulls description
  and variant prices/SKUs/GTINs from Shopify back into SMS
- Add ShopifyService::getProduct() for fetching a single product
- Add 'options' to createProduct() payload so Shopify properly creates variants
  (without it Shopify ignores variant option values)
- Add request/response logging to createProduct() for diagnosing transfer issues
- Remove dead code from ProductResource (mutateFormData*, getRecord, getActions)
- Clean up imports in ProductResource

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 18:07:24 +02:00
Malek TellissiandClaude Sonnet 4.6 9ef24fc45f Fix 500 on product create: remove $arguments from render-time closures
Deploy / deploy (push) Successful in 15s
In Filament v3, $arguments is only injected when an action is executed
(clicked), not when it's rendered. Using $arguments in label(), icon(),
color() and visible() closures causes ErrorException: Undefined variable
$arguments on every Livewire update, including on the create page.

Simplified extraItemAction to static label/icon/color; all dynamic
logic (publish vs sync, guard for unsaved items) stays in action().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 17:39:58 +02:00
Malek TellissiandClaude Sonnet 4.6 74b47193d9 Hide 'publish to Shopify' button if any variant already has a shopify_variant_id
Deploy / deploy (push) Successful in 15s
Products imported before shopify_product_id column was added have null
there, but their variants already carry shopify_variant_id — that's
enough to know the product exists in Shopify. Running shopify:import
once will backfill shopify_product_id for all existing products.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 17:25:53 +02:00
Malek TellissiandClaude Sonnet 4.6 3450b06e32 Reload page after publishing variant to Shopify so badge updates
Deploy / deploy (push) Successful in 14s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 17:23:18 +02:00
Malek TellissiandClaude Sonnet 4.6 6fe34883c6 Add 'Publish to Shopify' for locally-created products
Deploy / deploy (push) Successful in 14s
New header action on the product edit page creates the entire product
(title, description, all variants) in Shopify via API. The returned
shopify_product_id and per-variant shopify_variant_ids are stored
locally. After success the page reloads so status badges update.
Button is hidden once the product is already linked to Shopify.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 17:22:37 +02:00
Malek TellissiandClaude Sonnet 4.6 3ebd9845b0 Add Shopify publish/sync per product variant
Deploy / deploy (push) Successful in 14s
Each size row in the product form now shows a Shopify status badge
(green ✓ Shopify / gray Lokal). For saved variants, an action button
appears: 'Zu Shopify' for local-only variants (creates via Shopify
API and stores the returned variant ID), 'Shopify sync' for linked
variants (pushes price/SKU/GTIN to Shopify).

Also fixes:
- gtin missing from ProductSize::$fillable (was silently not saved)
- shopify_product_id added to products table and stored on import
- sizes afterStateHydrated now loads ProductSize directly instead of
  via the belongsToMany pivot (gets product_size_id, shopify_variant_id)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 17:20:26 +02:00
Malek TellissiandClaude Sonnet 4.6 e187465553 Fix syncSizes: replace belongsToMany sync with ProductSize updateOrCreate
Deploy / deploy (push) Successful in 14s
belongsToMany sync() is wrong for products_sizes which is a full model
with its own id and a unique shopify_variant_id. The new approach:
- updateOrCreate per row (safe for repeated saves)
- strips non-digits from gtin, stores null when empty (fixes 500 on
  unsignedBigInteger column with empty string in strict SQL mode)
- only deletes local-only sizes (whereNull shopify_variant_id) that
  were removed — Shopify-imported sizes are never deleted here

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 17:00:58 +02:00
Malek TellissiandClaude Sonnet 4.6 e14baca7e0 Add LOT API v1 endpoint with full batch details
Deploy / deploy (push) Successful in 15s
Route changed to /api/v1/{lot_number}. LotResource now includes
packing details, units_produced, quantity_g and recipe version.
CORS config added for public API access. README documents the
endpoint, example response and subdomain setup instructions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 16:43:48 +02:00
Malek TellissiandClaude Sonnet 4.6 269570c7d6 Remove recipe name field; use product title internally
Deploy / deploy (push) Successful in 15s
The recipe name input is dropped from the product form — the version
number alone identifies a recipe. The product title is stored as the
internal name to satisfy the NOT NULL constraint. The history table
no longer shows the name column.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 06:00:18 +02:00
Malek TellissiandClaude Sonnet 4.6 a7e7375edd Add recipe versioning: auto-bump on change, history sub-page
Deploy / deploy (push) Successful in 16s
Each time the recipe name or spices are changed on the product edit
page, a new version is created instead of overwriting the current one.
Unchanged saves are skipped. A 'Rezept-Versionen' button opens a
sub-page (/produkt/{id}/rezept-versionen) listing all versions with
their spices and timestamps; the active version is highlighted in green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 05:52:59 +02:00
Malek TellissiandClaude Sonnet 4.6 4775cffaae Embed recipe editing directly on product page
Deploy / deploy (push) Successful in 14s
Replaces the recipe dropdown with an inline Section containing a name
field and a spice-repeater with percentage inputs. On save, the recipe
is created (version 1) or updated in place; spice pivot rows are synced
via sync(). SumEquals100 rule enforces that percentages add up to 100.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 05:43:37 +02:00
Malek TellissiandClaude Sonnet 4.6 a34bb29620 Auto-deduct spice inventory when batch is created/updated/deleted
Deploy / deploy (push) Successful in 14s
- Add size_id, units_produced, quantity_g to batches table
- quantity_g auto-calculated from units × packing size on save
- Batch model deducts spice quantities on create, reverses on delete,
  recalculates on update when relevant fields change
- Batch form shows live total weight preview
- Chargen table shows units + grams produced

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 05:34:09 +02:00
Malek TellissiandClaude Sonnet 4.6 1e93aaa7d8 Make description read-only and auto-sized using Placeholder
Deploy / deploy (push) Successful in 14s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 05:22:32 +02:00
Malek TellissiandClaude Sonnet 4.6 a12502418b Display product images in grid layout with 200px preview height
Deploy / deploy (push) Successful in 14s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 05:20:40 +02:00
Malek TellissiandClaude Sonnet 4.6 a7f5c4a83e Recipe versioning, inline recipe create, recipe summary, Shopify description
Deploy / deploy (push) Successful in 15s
- Add version + product_id to recipes table (migration)
- Recipe select shows version label (e.g. "Kurkuma v2")
- Creating recipe from product page pre-fills product name, auto-increments version
- Recipe ingredient summary shown read-only below the select
- Remove package_content field (redundant with recipe ingredients)
- Pull product description from Shopify body_html on import
- Update existing products with empty description on re-import

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 05:18:11 +02:00
Malek TellissiandClaude Sonnet 4.6 6e28984278 Add recipe inline create/edit and batches relation on product page
Deploy / deploy (push) Successful in 14s
- Recipe select now has a create/edit modal (name + description)
- Batches RelationManager shows all LOT charges for the product below
  the form, sorted newest first, with create/edit/delete actions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 05:10:04 +02:00
Malek TellissiandClaude Sonnet 4.6 e959faff8d Fix barcode 500 error, GTIN mask formatting, and add price sync
Deploy / deploy (push) Successful in 15s
- Wrap barcode generation in try-catch to prevent 500 on invalid GTIN
- Move barcode preview above GTIN input field
- Add input mask (X XXXXXX XXXXXX) and strip non-digits before save/render
- Only render barcode when >= 8 digits present
- shopify:sync now updates price alongside inventory

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 04:59:46 +02:00
Malek TellissiandClaude Sonnet 4.6 25b32c717b Add SKU/GTIN fields, live barcode preview, and Shopify price import
Deploy / deploy (push) Successful in 26s
- Add SKU and GTIN fields to product variant repeater
- Render EAN/UPC barcode live from GTIN input (picqer/php-barcode-generator)
- Pull variant price from Shopify API instead of defaulting to 0
- Sync sku/gtin through EditProduct and CreateProduct save logic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 04:46:00 +02:00
Malek TellissiandClaude Sonnet 4.6 822790bfc0 Improve image import logging and move HTTP downloads out of DB transaction
Deploy / deploy (push) Successful in 16s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-12 04:16:12 +02:00
Malek TellissiandClaude Sonnet 4.6 02c17d6984 Add shopify:images command to download product images for existing products
Deploy / deploy (push) Successful in 14s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 15:09:47 +02:00
Malek TellissiandClaude Sonnet 4.6 9ee67dfb69 Download and store Shopify product images locally on import
Deploy / deploy (push) Successful in 13s
Images are fetched from Shopify CDN, stored in storage/app/public/product-images/
as UUIDs, and saved in the Product.images array — matching Filament's FileUpload format.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 15:08:01 +02:00
Malek TellissiandClaude Sonnet 4.6 edc4c5a28c Set explicit navigation group order in panel provider
Deploy / deploy (push) Successful in 13s
Produkte group appears first, followed by Lager, Waren Ein/Ausgang,
Ressourcen, CRM.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 15:06:21 +02:00
Malek TellissiandClaude Sonnet 4.6 53955b0163 Group Produkte, Rezepte and Chargen under 'Produkte' nav group
Deploy / deploy (push) Successful in 13s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 15:04:19 +02:00
Malek TellissiandClaude Sonnet 4.6 32e196719a Extend shopify:import to handle Stück, Stangen and Default Title variants
Deploy / deploy (push) Successful in 13s
Parses additional packaging formats from option1 and falls back to SKU
parsing for single-variant products with 'Default Title'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 15:02:12 +02:00
Malek TellissiandClaude Sonnet 4.6 94d94effa9 Add shopify:import command for initial product/inventory import
Deploy / deploy (push) Successful in 14s
Fetches all products and variants from Shopify API, creates local
Products, Packings and ProductSizes with shopify_variant_id, and
fills ProductInventory rows to match Shopify's inventory_quantity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 14:58:40 +02:00
Malek TellissiandClaude Sonnet 4.6 80b7831a1e Remove temporary Shopify OAuth install routes
Deploy / deploy (push) Successful in 14s
Token captured, routes no longer needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 03:21:48 +02:00
Malek TellissiandClaude Sonnet 4.6 527f99bb6e Set explicit redirect_uri in Shopify OAuth install URL
Deploy / deploy (push) Successful in 14s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 03:15:02 +02:00
Malek TellissiandClaude Sonnet 4.6 99d3ea748c Fix nullable clientSecret in ShopifyInstallController
Deploy / deploy (push) Successful in 13s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 03:13:40 +02:00
Malek TellissiandClaude Sonnet 4.6 2b7913311a Add temporary Shopify OAuth install routes
Deploy / deploy (push) Successful in 14s
/shopify/install  → redirects to Shopify OAuth
/shopify/callback → exchanges code for access token and displays it

To be removed after token is captured.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 03:12:20 +02:00
Malek TellissiandClaude Sonnet 4.6 7e9c43f2bf Improve Shopify sync error logging
Deploy / deploy (push) Successful in 14s
Log clear hint for 403 (IP whitelist), 401, 429, 5xx.
Commands exit with failure and print error when API returns no data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 02:54:44 +02:00
Malek TellissiandClaude Sonnet 4.6 467d85dfec Add Shopify inventory sync and order webhook
Deploy / deploy (push) Successful in 14s
- Migration: shopify_variant_id on products_sizes, shopify_order_id on products_sales
- ShopifyService: paginated REST client (2024-10 API)
- shopify:map — one-time command to link variants by SKU
- shopify:sync — reconciliation command (Shopify is master)
- VerifyShopifyWebhook middleware: HMAC-SHA256 verification
- ShopifyWebhookController: idempotent orders/paid handler, FIFO inventory deduction
- Webhook route: POST /api/webhooks/shopify/orders-paid

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-11 02:53:49 +02:00
Malek Tellissi 400172cdde Erster Upload 2026-09-11 01:17:47 +02:00