Data4Autos-Shopify-Backend/fulfillmentService.js

99 lines
3.8 KiB
JavaScript
Executable File

const axios = require('axios');
const { log } = require('./logger');
/**
* Create (or retrieve existing) fulfillment service + location for a shop.
* Returns { fulfillmentService, locationId } — locationId is NEVER null if a
* fulfillment service exists, because we fall back to the service's own location.
*/
async function createFulfillmentService(shop, accessToken) {
const client = axios.create({
baseURL: `https://${shop}/admin/api/2025-10/graphql.json`,
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
});
try {
log(shop, `🚀 [FulfillmentService] Creating fulfillment service...`);
// ── Step 1: Create fulfillment service (or retrieve existing) ────────────
const createResp = await client.post('', {
query: `
mutation {
fulfillmentServiceCreate(
name: "Data4Autos Distribution",
callbackUrl: "https://backend.data4autos.com/fulfillment"
) {
fulfillmentService {
id serviceName callbackUrl handle
location { id name }
}
userErrors { field message }
}
}
`,
});
let fulfillmentService = createResp.data?.data?.fulfillmentServiceCreate?.fulfillmentService;
const createErrors = createResp.data?.data?.fulfillmentServiceCreate?.userErrors || [];
if (createErrors.length > 0) {
log(shop, `⚠️ [FulfillmentService] Create errors: ${JSON.stringify(createErrors)}`);
// Service likely already exists — query it instead
log(shop, `🔍 [FulfillmentService] Querying existing fulfillment service...`);
const existingResp = await client.post('', {
query: `
query {
fulfillmentServices(type: THIRD_PARTY) {
id serviceName callbackUrl handle
location { id name }
}
}
`,
});
const services = existingResp.data?.data?.fulfillmentServices || [];
fulfillmentService = services.find(s => s.handle === 'data4autos-distribution') || services[0] || null;
if (!fulfillmentService) {
log(shop, `❌ [FulfillmentService] Could not create or find existing service`);
return { fulfillmentService: null, locationId: null };
}
log(shop, `✅ [FulfillmentService] Found existing: ${fulfillmentService.id}`);
} else {
log(shop, `✅ [FulfillmentService] Created: ${fulfillmentService.id}`);
}
// ── Step 2: Get the shop's primary location ID ───────────────────────────
// Shopify never returns a location from fulfillmentServiceCreate — use the
// shop's first active location (the physical/online store location) instead.
let locationId = null;
try {
const locResp = await client.post('', {
query: `query { locations(first: 1, includeLegacy: true) { nodes { id name isActive } } }`,
});
const locNode = locResp.data?.data?.locations?.nodes?.[0];
if (locNode?.id) {
locationId = locNode.id;
log(shop, `📍 [FulfillmentService] Primary shop location: "${locNode.name}" → ${locationId}`);
} else {
log(shop, `⚠️ [FulfillmentService] No locations returned from Shopify`);
}
} catch (locErr) {
log(shop, `⚠️ [FulfillmentService] Could not fetch shop location: ${locErr.message}`);
}
log(shop, `📍 [FulfillmentService] Final locationId: ${locationId}`);
return { fulfillmentService, locationId };
} catch (error) {
const errDetail = error.response ? JSON.stringify(error.response.data) : error.message;
log(shop, `💥 [FulfillmentService] Request failed: ${errDetail}`);
return { fulfillmentService: null, locationId: null };
}
}
module.exports = { createFulfillmentService };