Produkty

OficjalnyDarmowy

Wspólny katalog produktów: SKU, EAN, ceny, wagi, zdjęcia, marki i miejsca magazynowe, uzupełniany automatycznie z zamówień i integracji.

@core·Wiktor KoźmińskiBrak recenzji7 firm z instalacjąAktualizacja 22 października 2026
Zainstaluj w Orbito Otwiera panel Orbito na karcie modułu
Licencja
Bezpłatny
Wersja
1.4.4
Kategoria
Magazyn

core/products

Import katalogu przez integracje

Kontrakt hooków products.catalog.ingest przyjmuje source, currency i products (maksymalnie jedną pozycję, pusta lista służy sprawdzeniu dostępności). Źródło musi odpowiadać uwierzytelnionemu modułowi i jego instancji. Dostawcy są odkrywani przez products.catalog.ingest.providers, a zapis wskazuje jedną instancję. Operacja jest idempotentna po źródle i SKU; zachowuje lokalne podmiany oraz BOM. Zwraca lekki wynik { ok, results: [{ _id, sku, sourceId }], bySku: {} }, bez zdjęć i rozbudowanych projekcji. Ponowienie po utracie odpowiedzi potwierdza ten sam rekord. Import masowy zapisuje adresy zdjęć i zachowuje istniejące obrazy użytkownika. Nie pobiera zdjęć do cache podczas zapisu metadanych; endpoint obrazu wczytuje je przy wyświetlaniu. Ogranicza to pamięć i rozmiary danych RPC przy dużych katalogach.

Produkty bez SKU zachowują zapisany syntetyczny klucz wraz z wielkością liter tożsamości źródła. Odczyt wyniku importu nie zamienia tego klucza na inną wartość. Diagnostyka transportu RPC jest wyłączona, by nie kopiować całych zdjęć do logów; logi biznesowe pozostają dostępne.

Widoki i nawigacja

Slot inventoryView przy SKU listy, na karcie produktu oraz w tabeli SKU wewnętrznych zbiera źródła przez views.productInventory. Stany pobiera przez inventory.stock.getBySkus, osobno dla każdego ID instancji dostawcy. Bez integracji slot jest pusty; błędy pozostają widoczne. Lista przekazuje wyłącznie SKU aktualnie wyrenderowanej strony, bez odpytywania całego katalogu. src/product-inventory-slots.js tworzy natywne widoki OVE z literalnych SKU wyrenderowanych wierszy. Przekazuje je kodowane URI, żeby silnik parametrów nie interpretował kodu jako szablonu. Nie wykonuje samodzielnego HTTP ani pollingu. Po zmianie kontrolera uruchom node scripts/sync-product-inventory.js.

Od wersji 1.1.6 moduł sam rejestruje strony OVE:

  • /products — lista z pages/list-v2.yaml i automatyczna zakładka Produkty

w górnej nawigacji;

  • /product/:productId — karta z layouts/product-detail-v2.yaml, otwierana

kliknięciem nazwy lub wiersza na liście. Kliknięcie SKU albo EAN kopiuje wartość do schowka. Przycisk Wróć do produktów prowadzi do listy modułu.

Karta produktu zawiera formularz danych podstawowych i cen, tabelę SKU wewnętrznych bezpośrednio pod formularzem oraz powiększony podgląd zdjęcia. Przyciski zapisu i przywracania znajdują się w nagłówku Dane produktu. Od wersji 1.1.13 przywracanie wykonuje update, a następnie image.clear, resetując dane i zdjęcie. Potwierdzenie pojawia się po obu operacjach; błąd resetu zdjęcia jest pokazany po odświeżeniu danych.

Pole Marka jest zwykłą lokalną podmianą danych katalogowych: można ją ustawić podczas tworzenia produktu albo na karcie, a wyczyszczenie pola wraca do wartości ze źródła. Na liście marka pojawia się dyskretnie pod nazwą; kliknięcie nazwy lub marki otwiera kartę produktu, natomiast tylko SKU i EAN kopiują się do schowka.

Pole Miejsce magazynowe w sekcji Dane produktu zapisuje lokalną wartość warehouseLocation (do 200 znaków), która ma pierwszeństwo przed wartością ze źródła. Puste pole usuwa lokalne przypisanie i natychmiast wraca do lokalizacji ze źródła; dla starszych produktów bez danych źródłowych pozostaje puste. Przywracanie danych ze źródła zachowuje lokalne miejsce magazynowe.

Import i eksport CSV

Lista produktów udostępnia trzy akcje CSV:

  • pobranie przykładowego pliku z wymaganym nagłówkiem i jednym wierszem;
  • eksport całego bieżącego katalogu (wartości widoczne po uwzględnieniu lokalnych

podmian);

  • import pliku do 10 MB i 20 000 wierszy.

Kanoniczny nagłówek ma postać:

sku;nazwa;marka;ean;cena_netto;vat_procent;waga_kg;miejsce_magazynowe

Importer rozpoznaje również angielskie odpowiedniki nazw kolumn oraz separator przecinka lub tabulatora. Liczby mogą używać przecinka dziesiętnego. sku jest kluczem: istniejący produkt dostaje lokalne podmiany tylko dla wartości, które rzeczywiście się zmieniły, a brakujące SKU tworzy produkt ręczny (wtedy nazwa jest wymagana). Puste komórki nie zmieniają zapisanych danych. Brak wiersza w pliku nigdy nie usuwa produktu. Błędy pojedynczych wierszy są pomijane i ujęte w podsumowaniu importu; duplikat SKU w pliku nie jest wykonywany drugi raz.

Eksport i szablon są kodowane jako UTF-8 z BOM i używają średnika, dzięki czemu są czytelne w polskich ustawieniach arkuszy. Identyfikatory liczbowe zachowują zera wiodące, a pola tekstowe są zabezpieczane przed wykonaniem jako formuła.

Dodawanie produktu mapuje wartości kontrolek jawnie na sku, name, brand, ean i unitPrice. Błędy RPC mogą wrócić jako tablica w odpowiedzi HTTP 200, dlatego formularz zamyka się i pokazuje sukces dopiero po success: true. Przy błędzie zachowuje wpisane dane; po utworzeniu czyści pola. Pusta cena pozostaje nieustawiona.

Synchronizacja metadanych źródłowych

Przycisk z ikoną odświeżania na liście pobiera dane wyłącznie dla produktów widocznych na bieżącej stronie. Taka sama ikona na karcie odświeża tylko ten produkt. Przyciski mają opisy po najechaniu. Oba zwracają podsumowanie liczby zaktualizowanych, pominiętych i błędnych pozycji.

syncMetadata ignoruje SKU i źródło przekazane przez UI; po identyfikatorze produktu ponownie odczytuje zapisane original.sourceModule, sourceId i SKU. Produkty są grupowane według sourceModule, a adapter źródłowy musi udostępnić read-only metodę product.get_metadata({ products: [{ sourceId, sku }] }), zwracającą { results: [{ sourceId, sku, unitPrice?, brand?, warehouseLocation? }] }. Brak pola nie zmienia zapisanej wartości, a jawne '' oznacza potwierdzoną pustą wartość dla pól tekstowych. Błąd adaptera, brak sklepu albo niejednoznaczny wynik nie kasuje danych. Synchronizacja zapisuje cenę bazową netto w original.unitPrice oraz źródłową markę i lokalizację; nie nadpisuje lokalnych podmian. Wynik jest zapisywany przez pojedynczy CAS snapshotu sprzed odczytu adaptera, więc równoległy nowszy import wygrywa.

SKU wewnętrzne przechowują nazwę, ilość, opcjonalną cenę netto i własną stawkę VAT. Formularz na karcie produktu wyszukuje ten sam katalog core/products.search, który jest używany przy dodawaniu pozycji do zamówienia. Wybór podpowiedzi kopiuje aktualną cenę netto oraz VAT produktu do wpisu wewnętrznego. Pola netto i brutto przeliczają się dwukierunkowo według wpisanego VAT, a zmiana VAT aktualizuje cenę brutto bez nadpisywania stawki. Ceny i VAT można następnie zmienić lokalnie bez modyfikowania wybranego produktu katalogowego. Nadal można też wpisać własną nazwę, SKU, cenę i VAT bez wybierania podpowiedzi.

Wewnętrzny upsert przyjmuje opcjonalne previousSourceId. Służy ono wyłącznie do migracji tożsamości źródła: stary identyfikator zostaje zastąpiony tylko wtedy, gdy wskazuje ten sam dokument co aktualnie importowane SKU. Zapobiega to przejęciu danych jednego wariantu przez inny wariant tego samego produktu.

Rejestracja następuje przy starcie, ponownie po włączeniu nowej wersji oraz po ponownym połączeniu SDK z rdzeniem. Kolejne aktualizacje modułu aktualizują treść obu stron. Automatyczna zakładka wymaga SDK @orbito/api-lib 3.2.0.

Po aktualizacji modułu zakładka pojawi się w Ustawienia → Nawigacja → Automatyczne zakładki z modułów. Wcześniejszy ręczny link do user/products można usunąć z nawigacji, żeby uniknąć dwóch pozycji Produkty. Moduł nie usuwa stron ani ustawień nawigacji utworzonych przez użytkownika.

Pliki w katalogu głównym workspace (products*.yaml, product-details*.yaml) oraz pozostałe layouty zachowują wcześniejsze szablony. Zmiany widoków modułu należy wprowadzać w dwóch plikach wskazanych powyżej.

Przenoszenie produktów między firmami

Na liście Produkty kliknij Eksport CSV w firmie źródłowej. Przełącz firmę, kliknij Import CSV, wybierz pobrany plik i kliknij Importuj produkty. Możesz też pobrać Szablon CSV z paska nad listą produktów i uzupełnić go w arkuszu. Nowy produkt wymaga SKU i nazwy.

Plik jest zwykłą tabelą z ośmioma kolumnami:

sku;nazwa;marka;ean;cena_netto;vat_procent;waga_kg;miejsce_magazynowe
PROD-001;Przykładowy produkt;Marka;;49,99;23;0,5;A-01

Każdy produkt zajmuje jeden wiersz. Eksport zawiera aktualnie widoczne wartości, bez JSON, zdjęć w base64 i wewnętrznych danych systemowych. Nie jest kopią zapasową zdjęć, rozbić na SKU wewnętrzne ani historii integracji.

Przy istniejącym SKU wybierz Pomiń produkt (domyślnie) lub Aktualizuj produkt. Brakujące produkty zostaną dodane. Puste komórki pozostawiają dotychczasową wartość. Powtórny import nie tworzy duplikatów, a wynik pokazuje liczbę dodanych, zaktualizowanych i pominiętych wierszy.

Limit pliku to 10 MB i 20 000 produktów. Większy katalog można pobrać przyciskiem Pobierz kolejną część CSV. Import nadal przyjmuje starsze eksporty z wersji 1.2.7, ale nowe pliki i szablon mają wyłącznie powyższe kolumny.

Weryfikacja

npm test
omm pack -C . --dry-run

Test rejestracji sprawdza start i aktywację modułu. Test integracyjny z zainstalowanym SDK sprawdza treść wysyłanych widoków, automatyczną zakładkę, powrót z karty produktu, ponowne połączenie i ponowienie po błędzie.

syncOrderSourcePrices (wewnętrzne API) dopisuje konto źródła i cenę kanałową do istniejącego SKU. Parametry: source, products z sku, sourceId, baseUnitPrice i tax, currency, orderAt. Operacja jest idempotentna, sprawdza kolizje tożsamości i używa blokad oraz CAS. Zachowuje kartotekę, ręczne pola i BOM. Obserwacja ze starszego zamówienia nie zastępuje nowszej ceny kanału.

products.resolveBySkus zwraca effectiveName — główną nazwę katalogową z pierwszeństwem ręcznej nazwy, niezależną od trybu prezentacji displayMode. Pole name zachowuje dotychczasową semantykę. Szczegóły kontraktu dla dokumentów: docs/product-names-contract.md.