Att hålla lagret korrekt och uppdaterat är av yttersta vikt för alla återförsäljare med hög volym. För Wellcare och Raf Pharmacy – två ledande apotekskedjor i Qatar med över 10 000 SKU:er , 100+ fysiska butiker och aktiv försäljning i Shopifys webbutiker , mobilappar och kassasystem – byggde vi en robust ERP-till-Shopify-lösning för lageruppdatering i realtid. Nedan delar vi vår heltäckande arkitektur, kodavsnitt och prestandaresultat.

Projektets omfattning och utmaningar

  • kunder: Wellcare Apotek och Raf Apotek, Qatar
  • Katalogstorlek: 10,000+ SKU:er
  • Försäljningskanaler: Shopify-butik, headless mobilappar, 100+ fysiska platser
  • ERP: INNSOF ERP skickar aktieuppdateringar
  • Krav:
    • Realtidssynkronisering för att förhindra överförsäljning
    • Skalbar för hög uppdateringsvolym
    • Minimal API-latens och fel
    • Noggrann lagerhantering på flera platser

1. Inledande tillvägagångssätt: Shopify REST API

Vi använde först Shopifys REST Admin API-slutpunkt /admin/api/2024‑01/inventory_levels/set.json för att publicera aktieuppdateringar.

// Sample REST payload
$payload = [
  'location_id'      => $locationId,
  'inventory_item_id'=> $inventoryItemId,
  'available'        => $newStock
];
$response = $this->shopifyService->restRequest('POST', "/inventory_levels/set.json", $payload);

REST API-begränsningar

  • Inga batchuppdateringar: En SKU per begäran
  • Strikta gränser för avgift: ~2 samtal/sek per butik → flaskhals för tusentals SKU:er
  • Hög latens: 50–100 ms per begäran, ackumulerade fördröjningar
  • Felbenägen: Ofta förekommande hastighetsgränsfel under belastning

2. Migrera till Shopify GraphQL API

För att övervinna REST-begränsningarna bytte vi till Shopifys GraphQL Admin API , vilket låste upp:

  • Batchuppdateringar med inventoryAdjustQuantities mutation
  • Kostnadsbaserad strypning (mer flexibel än REST)
  • Lägre nätverkskostnader genom att endast begära nödvändiga fält
  • Deltabaserade justeringar (uppdateras endast när lagret faktiskt ändras)

3. Arkitekturöversikt

  1. ERP → Mellanprogramvara
    • INNSOF ERP skickar en JSON-nyttolast via HTTP POST till vår StockController.
  2. Anrikning och avverkning
    • Vi analyserar, validerar och loggar begäran i en lokal databas (api_request_log).
    • Vi berikar varje SKU med location_id och inventory_item_id (från cachade tabeller).
  3. Få aktuellt lager
    • Hämta befintliga lagernivåer via GraphQL (per plats och SKU).
  4. Beräkningsdelta
    • Jämför ERP-lager med Shopify-lager för att avgöra delta.
  5. Justera lagret
    • Skicka en enda GraphQL-mutation per batch (upp till 100 SKU:er).
  6. Svarshantering
    • Logga framgångar/misslyckanden och skicka uppdateringsstatus tillbaka till ERP.
  7. Återförsök och reserv
    • Automatiserade cron-jobb försöker om misslyckade batchar; återgå till REST om det behövs.

4. Hämta aktuellt lager via GraphQL

Noggrann deltaberäkning börjar med att hämta befintliga kvantiteter. Vi batchar upp till 60 artiklar per fråga:

query inventoryItems {
  item1: inventoryItem(id: "gid://shopify/InventoryItem/123456789") {
    id
    tracked
    sku
    inventoryLevels(first: 10) {
      edges {
        node {
          location { id name }
          quantities(names: "available") {
            quantity
          }
        }
      }
    }
  }
  # item2, item3… up to 60
}

Vår PHP-metod samlar dessa i en array:

private function getCurrentStock(array $products): array {
    $batches = array_chunk($products, 60);
    $results = [];
    foreach ($batches as $batch) {
        // Build GraphQL query dynamically…
        $response = $this->shopifyService->executeGraphQl($query, []);
        // Parse `$response['data']` into $results[]
    }
    return $results;  // [ ['inventory_item_id'=>…, 'location_id'=>…, 'quantity'=>…], … ]
}

5. Justera lager via GraphQL

När vi vet det aktuella lagret förbereder vi deltauppdateringens nyttolast:

Mutationsmall

mutation AdjustMultipleInventoryQuantities($input: InventoryAdjustQuantitiesInput!) {
  inventoryAdjustQuantities(input: $input) {
    inventoryAdjustmentGroup {
      createdAt
      changes { name delta }
    }
    userErrors { field message }
  }
}

PHP-variablerformat

$changes = [];
foreach ($updatedProducts as $p) {
    $changes[] = [
      'inventoryItemId'=> "gid://shopify/InventoryItem/{$p['inventory_item_id']}",
      'locationId'     => "gid://shopify/Location/{$p['location_id']}",
      'delta'          => $p['erp_stock'] - $p['current_stock']
    ];
}

$variables = [
  'input' => [
    'reason'               => 'correction',
    'name'                 => 'available',
    'referenceDocumentUri' => 'logistics://erp/batch-2025-07-29',
    'changes'              => $changes
  ]
];

$response = $this->shopifyService->executeGraphQl($mutation, $variables);

Det här enda anropet uppdaterar upp till 100 SKU: er samtidigt, vilket minskar nätverksstörningar avsevärt.

6. Optimeringshöjdpunkter

  • Batching och Chunking: 60 objekt/fråga för läsningar; 100 objekt/mutation för skrivningar.
  • Lokal cachelagring: HITTA BUTIK inventory_item_id & location_id i MySQL för att undvika upprepade sökningar.
  • Deltalogik: Uppdatera endast SKU:er vars nuvarande lager skiljer sig från ERP-lagret.
  • Medvetenhet om hastighetsgränser: Insert sleep()/usleep() strategiskt och reserv till REST för brådskande återförsök.
  • Robust loggning: Varje förfrågan och svar loggas api_request_log och stock_update_log tabeller.

7. Prestandajämförelse

metriskREST APIGraphQL API
Stöd för batchuppdateringar
Genomsnittlig tid per 100 SKU:er~60 sekunder~5 sekunder
Hastighetsgränsfel (under belastning)FrekventSällsynta
Noggrannhet i realtidModerateHög
ERP-feedbackintegrationPartiellFullständig, inloggad

8. Tekniker och verktyg

  • Shopify GraphQL Admin API
  • PHP (Aktiekontroller) med ShopifyServiceLogManagerDBOpsApiService
  • MySQL för lokal cachning och loggar
  • INNSOF ERP webhooks
  • cron jobb för återförsök och ERP-återanrop

9. Fördelar för Wellcare & Raf Pharmacy

  • 🔄 Lagernoggrannhet i realtid i över 100 butiker och kanaler
  • ???? Noll överförsäljning och sömlös kundupplevelse
  • ⚡ hög genomströmningtusentals SKU-uppdateringar per timme
  • 🔍 Detaljerad revisionslogg för efterlevnad och felsökning
  • 📈 Förbättrad SEO och UX på webb- och mobila butiker

10. Vanliga frågor

  1. Varför hämta aktuellt lager innan man uppdaterar?
    Säkerställer att vi beräknar korrekt delta, vilket förhindrar oavsiktliga överskrivningar eller dubbla justeringar.
  2. Hur många SKU:er kan GraphQL hantera i en batch?
    Upp till 100 SKU:er per mutation och 60 per fråga, konfigurerbart baserat på butiksplan.
  3. Kan jag blanda REST och GraphQL?
    Ja. Vi behåller REST som reserv för kritiska uppdateringar när GraphQL begränsas.
  4. Fungerar lagerhantering på flera platser?
    Absolut. Vi frågar efter och uppdaterar nivåer per plats med hjälp av locationId.
  5. Är den här metoden anpassningsbar till andra ERP-system?
    Ja. Vår modulära design kan integreras med Odoo, SAP, Oracle 6i och fler.

Varför välja Seamedias e-handelslösningar?
På Seamedia kombinerar vi djupgående Shopify-expertis med robust kunskap om ERP-integration för att leverera skräddarsydda, högpresterande lösningar som driver verkliga affärsresultat. Vårt team – lett av erfarna konsulter som Prajosh VM—förstår komplexiteten i lagerhantering på flera platser, höga SKU-volymer och omnikanalig detaljhandel. Vi utformar skalbara, API-drivna arbetsflöden som håller ditt lager korrekt, dina kunder nöjda och din verksamhet igång. Oavsett om du är en snabbväxande apotekskedja, en nationell återförsäljare eller en storföretagstillverkare, erbjuder Seamedia heltäckande utveckling, sömlös ERP-anslutning och support dygnet runt.

Redo att effektivisera ditt lager och öka din försäljning?
Kontakta oss idag på hello@seamedia.in eller besök www.seamedia.in för att diskutera hur vi kan bygga en anpassad lösning för realtidssynkronisering av aktier för ditt företag.