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>
This commit is contained in:
1 parent
3ebd9845b0
commit
6fe34883c6
2 files changed
+86
No files matched your search
@@ -17,6 +17,15 @@ class EditProduct extends EditRecord
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\Action::make('shopify-create-product')
|
||||
->label('In Shopify veröffentlichen')
|
||||
->icon('heroicon-o-arrow-up-tray')
|
||||
->color('warning')
|
||||
->requiresConfirmation()
|
||||
->modalHeading('Produkt in Shopify anlegen')
|
||||
->modalDescription('Erstellt das Produkt mit allen Varianten in Shopify und verknüpft die IDs.')
|
||||
->visible(fn () => ! $this->record->shopify_product_id)
|
||||
->action(fn () => $this->createProductInShopify()),
|
||||
Actions\Action::make('rezept-versionen')
|
||||
->label('Rezept-Versionen')
|
||||
->icon('heroicon-o-clock')
|
||||
@@ -112,6 +121,35 @@ class EditProduct extends EditRecord
|
||||
$product->update(['recipes_id' => $recipe->id]);
|
||||
}
|
||||
|
||||
public function createProductInShopify(): void
|
||||
{
|
||||
$product = $this->record;
|
||||
|
||||
if ($product->shopify_product_id) {
|
||||
Notification::make()->title('Bereits in Shopify verknüpft')->warning()->send();
|
||||
return;
|
||||
}
|
||||
|
||||
$sizes = ProductSize::with('packing')->where('product_id', $product->id)->get();
|
||||
|
||||
try {
|
||||
$result = app(ShopifyService::class)->createProduct($product, $sizes);
|
||||
|
||||
$product->update(['shopify_product_id' => $result['shopify_product_id']]);
|
||||
|
||||
foreach ($result['variants'] as $packingId => $variantId) {
|
||||
ProductSize::where('product_id', $product->id)
|
||||
->where('packing_id', $packingId)
|
||||
->update(['shopify_variant_id' => $variantId]);
|
||||
}
|
||||
|
||||
Notification::make()->title('Produkt in Shopify erstellt')->success()->send();
|
||||
$this->redirect(ProductResource::getUrl('edit', ['record' => $product]));
|
||||
} catch (\Throwable $e) {
|
||||
Notification::make()->title('Shopify-Fehler')->body($e->getMessage())->danger()->send();
|
||||
}
|
||||
}
|
||||
|
||||
public function publishVariantToShopify(int $sizeId): void
|
||||
{
|
||||
$size = ProductSize::with('packing')->find($sizeId);
|
||||
|
||||
@@ -76,6 +76,54 @@ class ShopifyService
|
||||
return $variants;
|
||||
}
|
||||
|
||||
public function createProduct(\App\Models\Product $product, \Illuminate\Support\Collection $sizes): array
|
||||
{
|
||||
$variants = $sizes->map(fn (ProductSize $s) => array_filter([
|
||||
'option1' => $s->packing->name . ' ' . $s->packing->size . 'g',
|
||||
'price' => number_format((float) $s->price, 2, '.', ''),
|
||||
'sku' => $s->sku ?: null,
|
||||
'barcode' => $s->gtin ?: null,
|
||||
]))->values()->toArray();
|
||||
|
||||
$body = [
|
||||
'product' => [
|
||||
'title' => $product->title,
|
||||
'body_html' => $product->description
|
||||
? '<p>' . nl2br(e($product->description)) . '</p>'
|
||||
: '',
|
||||
],
|
||||
];
|
||||
|
||||
if (! empty($variants)) {
|
||||
$body['product']['variants'] = $variants;
|
||||
}
|
||||
|
||||
$response = Http::withHeader('X-Shopify-Access-Token', $this->token)
|
||||
->post("{$this->baseUrl}/products.json", $body);
|
||||
|
||||
if ($response->failed()) {
|
||||
throw new \RuntimeException(
|
||||
'Shopify-Fehler ' . $response->status() . ': ' . $response->body()
|
||||
);
|
||||
}
|
||||
|
||||
$shopifyProduct = $response->json('product');
|
||||
$shopifyVariants = $shopifyProduct['variants'];
|
||||
|
||||
// Match returned variants back to local sizes by index (same order as sent)
|
||||
$variantMap = [];
|
||||
foreach ($sizes as $index => $size) {
|
||||
if (isset($shopifyVariants[$index])) {
|
||||
$variantMap[$size->packing_id] = (string) $shopifyVariants[$index]['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'shopify_product_id' => (string) $shopifyProduct['id'],
|
||||
'variants' => $variantMap,
|
||||
];
|
||||
}
|
||||
|
||||
public function createVariant(string $shopifyProductId, ProductSize $size): string
|
||||
{
|
||||
$packing = $size->packing;
|
||||
|
||||
Reference in new issue
Block a user