import { applyParams, save, ActionOptions } from "gadget-server"; import { preventCrossShopDataAccess } from "gadget-server/shopify"; export const run: ActionRun = async ({ params, record, logger, api, connections }) => { applyParams(params, record); await preventCrossShopDataAccess(params, record); // Check if any price-related fields or metafields are provided in params const priceFields = ['price', 'compareAtPrice']; const metafieldFields = ['hasMaliyet', 'webKar', 'dolarMaliyet']; const relevantFields = [...priceFields, ...metafieldFields]; // Debug: Log all params received with detailed logging logger.info("=== DETAILED PARAMS LOGGING ==="); // Try JSON.stringify with error handling try { logger.info("All params (JSON):", JSON.stringify(params, null, 2)); } catch (error) { logger.error("Error stringifying params:", error.message); logger.info("Params object keys:", Object.keys(params || {})); } // Log individual param values logger.info("Individual param values:"); if (params) { Object.entries(params).forEach(([key, value]) => { logger.info(` ${key}:`, value, `(type: ${typeof value})`); }); } else { logger.info(" params is null or undefined"); } // Log record information logger.info("=== RECORD INFORMATION ==="); logger.info("Record ID:", record.id); logger.info("Record shopId:", record.shopId); logger.info("Record productId:", record.productId); // Log current record values for price-related fields logger.info("Current record values:"); logger.info(" price:", record.price); logger.info(" compareAtPrice:", record.compareAtPrice); logger.info(" hasMaliyet:", record.hasMaliyet); logger.info(" webKar:", record.webKar); logger.info(" dolarMaliyet:", record.dolarMaliyet); const providedFields = relevantFields.filter(field => params[field] !== undefined); const forceSync = params.forceSync === true; logger.info("=== FIELD ANALYSIS ==="); logger.info(`Relevant fields checked: ${relevantFields.join(', ')}`); logger.info(`Provided fields from relevant fields: ${providedFields.join(', ')}`); logger.info(`Force sync requested: ${forceSync}`); // Log each relevant field individually relevantFields.forEach(field => { const value = params[field]; logger.info(` ${field}: ${value} (provided: ${value !== undefined})`); }); // Save the record locally await save(record); if (providedFields.length === 0 && !forceSync) { logger.info("No price or metafield parameters provided and no force sync, skipping Shopify sync"); return; } logger.info(`Syncing to Shopify due to provided fields: ${providedFields.join(', ')} or force sync: ${forceSync}`); // Add metafields if any are provided in params const metafieldsToUpdate = []; if (params.hasMaliyet !== undefined) { metafieldsToUpdate.push({ key: "has_maliyet", namespace: "custom", value: record.hasMaliyet?.toString() || "", type: "number_decimal" }); logger.info(`Has maliyet to sync: ${record.hasMaliyet}`); } if (params.webKar !== undefined) { metafieldsToUpdate.push({ key: "web_kar", namespace: "custom", value: record.webKar?.toString() || "", type: "number_decimal" }); logger.info(`Web kar to sync: ${record.webKar}`); } if (params.dolarMaliyet !== undefined) { metafieldsToUpdate.push({ key: "dolar_maliyet", namespace: "custom", value: record.dolarMaliyet?.toString() || "", type: "number_decimal" }); logger.info(`Dolar maliyet to sync: ${record.dolarMaliyet}`); } // Prepare variant update object const variantUpdate: any = { id: `gid://shopify/ProductVariant/${record.id}` }; // Add price fields if provided in params if (params.price !== undefined) { variantUpdate.price = record.price?.toString(); } if (params.compareAtPrice !== undefined) { variantUpdate.compareAtPrice = record.compareAtPrice?.toString(); } // Add metafields if any are provided if (metafieldsToUpdate.length > 0) { variantUpdate.metafields = metafieldsToUpdate; } // Prepare the correct GraphQL mutation for productUpdate const mutation = ` mutation productUpdate($input: ProductInput!) { productUpdate(input: $input) { product { id } userErrors { field message } } } `; // Structure variables for productUpdate mutation const variables = { input: { id: `gid://shopify/Product/${record.productId}`, variants: [variantUpdate] } }; // Log the mutation and variables for debugging logger.info("=== SHOPIFY SYNC DETAILS ==="); logger.info("Sending GraphQL mutation to Shopify"); logger.info("Mutation:", mutation.replace(/\s+/g, ' ').trim()); // Log variables with detailed breakdown try { logger.info("Variables (JSON):", JSON.stringify(variables, null, 2)); } catch (error) { logger.error("Error stringifying variables:", error.message); } // Log variables breakdown logger.info("Variables breakdown:"); logger.info(" Product ID:", variables.input.id); logger.info(" Variant update object:", JSON.stringify(variantUpdate, null, 2)); logger.info(" Metafields to update:", JSON.stringify(metafieldsToUpdate, null, 2)); // Enqueue the writeToShopify action try { await api.enqueue(api.writeToShopify, { shopId: record.shopId, mutation, variables }); logger.info("✅ Shopify sync enqueued successfully"); } catch (error) { logger.error("❌ Failed to enqueue Shopify sync:", error.message); // Don't throw error to avoid failing the local update } }; export const options: ActionOptions = { actionType: "update", triggers: { api: true }, };