Numer RMA jako identyfikator sprawy w systemie
Numer RMA wskazuje jedną sprawę reklamacyjną albo zwrotną i nic więcej. Nie opisuje klienta i nie zastępuje numeru zamówienia. Nie tworzy też roszczenia, bo podstawą żądania klienta jest rękojmia albo gwarancja. Mimo to ten sam numer pojawia się w wiadomości do klienta i na etykiecie paczki, a potem w bazie danych i na dokumentach rozliczeniowych. Z tego powodu jego format warto zaprojektować raz, zanim trafi do pierwszej sprawy.
Sprawa ma w systemie kilka numerów naraz, więc trzeba rozdzielić ich role. Tabela porządkuje je według tego, kto numer nadaje i do czego służy.
| Numer | Kto nadaje | Co identyfikuje | Gdzie się pojawia |
|---|---|---|---|
| Numer RMA | sprzedawca lub producent | sprawę reklamacyjną albo zwrotną | e-mail do klienta, etykieta paczki |
| Numer zamówienia | sklep lub ERP | transakcję sprzedaży | potwierdzenie zamówienia, faktura |
| Numer listu przewozowego | przewoźnik | przesyłkę w sieci kuriera | etykieta kuriera, śledzenie przesyłki |
| Numer seryjny | producent | egzemplarz urządzenia | tabliczka znamionowa, karta gwarancyjna |
| SSCC | nadawca jednostki logistycznej według standardu GS1 | jednostkę logistyczną, na przykład paletę | etykieta logistyczna GS1 |
Reguła: numer RMA identyfikuje sprawę, a pozostałe numery są jej atrybutami, więc system przechowuje je w osobnych polach i nie wyprowadza jednego z drugiego.
Zapisane zgłoszenie z internetowego formularza w Studio RMA.net ma przypisany automatycznie unikalny numer zgłoszenia, zwany też numerem referencyjnym albo numerem RMA. Opis aplikacji znajduje się na stronie Studio RMA.net, a moment nadania numeru i jego rolę w autoryzacji zwrotu wyjaśnia tekst o return merchandise authorization. Ogólną architekturę systemu opisuje artykuł RMA system - architektura i integracje.
Format numeru RMA i maska numeracji
Numer składa się z segmentów o stałej długości, które da się zweryfikować prostym wzorcem. Poniższa tabela pokazuje przykładową maskę RMA-RRRR-NNNNNN-C i rolę każdego segmentu. Format jest przykładem projektowym, a nie opisem numeracji konkretnego produktu.
| Segment | Przykład | Rola | Uwaga |
|---|---|---|---|
| Prefiks | RMA | odróżnia numer sprawy od innych numerów w korespondencji | stały, wielkie litery |
| Rok | 2026 | pozwala rozpocząć licznik od jedynki i skraca numer licznika | cztery cyfry |
| Licznik | 000123 | kolejność nadania w danym roku | sześć cyfr z zerami wiodącymi |
| Cyfra kontrolna | 3 | wykrywa pomyłkę przy ręcznym przepisaniu | liczona z roku i licznika |
Pełny numer z przykładu ma postać RMA-2026-000123-3. Separatorem jest myślnik, a nie ukośnik, ponieważ ukośnik wymaga kodowania, gdy numer trafia do adresu URL albo do nazwy pliku. Myślnik przechodzi bez zmian przez wiadomość e-mail i adres strony.
Reguła: numer RMA nie zawiera danych osobowych ani kwoty zamówienia, bo widzi go kurier i każdy, kto ma dostęp do wiadomości e-mail.
Długość i dozwolone znaki
Pole na numer w bazie i w interfejsach przewoźników ma ograniczoną długość, a klient przepisuje numer ręcznie z wiadomości do formularza. Krótki numer z cyframi i wielkimi literami ogranicza pomyłki. Litery O oraz I łatwo pomylić z cyframi 0 oraz 1, więc jeśli licznik zawiera litery, wyklucza się je z alfabetu. Numer z przykładu ma 17 znaków i mieści się w polu VARCHAR(20) z zapasem na ewentualny dodatek.
Cyfra kontrolna numeru
Cyfra kontrolna wykrywa pomyłkę przy przepisywaniu, zanim zapytanie trafi do bazy. Algorytm Luhna wyłapuje pojedynczą błędną cyfrę i większość zamian sąsiednich cyfr. Nie chroni natomiast przed celowym zgadywaniem numerów, więc nie zastępuje kontroli dostępu.
public static int CyfraKontrolna(string cyfry)
{
int suma = 0;
bool podwoj = true;
for (int i = cyfry.Length - 1; i >= 0; i--)
{
int d = cyfry[i] - '0';
if (podwoj)
{
d *= 2;
if (d > 9) d -= 9;
}
suma += d;
podwoj = !podwoj;
}
return (10 - suma % 10) % 10;
}
Metoda dostaje ciąg cyfr roku i licznika, czyli 2026000123, i zwraca cyfrę dopisywaną na końcu numeru. Przy odczycie formularza program liczy sumę ponownie i odrzuca numer z błędną cyfrą, zanim wykona zapytanie do bazy.
Nadawanie numeru RMA w transakcji bazy danych
Numer nadaje baza danych, ponieważ tylko ona widzi wszystkie równoległe zapisy. Dwie osoby rejestrujące zgłoszenia w tej samej sekundzie nie mogą dostać tej samej liczby. Aplikacja, która odczytuje ostatni numer i dodaje jedynkę, prędzej czy później wyda duplikat. Do wyboru są dwa mechanizmy, a różnią się zachowaniem przy wycofaniu transakcji.
| Mechanizm | Zachowanie przy ROLLBACK | Nowy rok | Obciążenie zapisu |
|---|---|---|---|
| SEQUENCE | numer przepada, w numeracji powstaje luka | ręczny restart sekwencji | brak blokady na tabeli spraw |
| Tabela liczników z UPDATE | numer wraca do puli razem z transakcją | osobny wiersz na każdy rok | zapisy kolejkują się na jednym wierszu |
Sekwencję opisuje dokumentacja CREATE SEQUENCE. Wariant z tabelą liczników nie tworzy luk, ponieważ zapis licznika i sprawy odbywa się w jednej transakcji, a blokada wiersza licznika trwa do jej zakończenia. Wiersz na nowy rok zakłada zadanie SQL Agent w grudniu, więc procedura nie wstawia go sama.
CREATE TABLE dbo.LicznikRma (
Rok SMALLINT NOT NULL PRIMARY KEY,
Ostatni INT NOT NULL
);
GO
CREATE PROCEDURE dbo.NadajNumerRma
@Rok SMALLINT OUTPUT,
@Nr INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
SET @Rok = YEAR(SYSUTCDATETIME());
UPDATE dbo.LicznikRma
SET @Nr = Ostatni = Ostatni + 1
WHERE Rok = @Rok;
IF @@ROWCOUNT = 0
THROW 50020, N'Brak licznika RMA na bieżący rok.', 1;
END;
Reguła: procedurę wywołuje się w tej samej transakcji, która wstawia sprawę, bo dopiero wtedy wycofanie zapisu zwalnia też numer.
Procedura zwraca rok i licznik, a aplikacja składa z nich numer razem z cyfrą kontrolną z poprzedniej sekcji.
string baza = rok.ToString() + nr.ToString("D6");
string numer = $"RMA-{rok}-{nr:D6}-{CyfraKontrolna(baza)}";
Unikalność wymuszona przez bazę
Poprawny algorytm nadawania nie wystarcza jako jedyne zabezpieczenie, bo numer można wstawić ręcznie albo zaimportować ze starego arkusza. Gwarancję daje indeks unikalny, który odrzuca duplikat na poziomie silnika, opisany w dokumentacji indeksów unikalnych. Ograniczenie CHECK pilnuje dodatkowo kształtu numeru.
CREATE TABLE dbo.SprawaRma (
SprawaId INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
NumerRma VARCHAR(20) NOT NULL,
DataWplywu DATETIME2(0) NOT NULL DEFAULT SYSUTCDATETIME(),
CONSTRAINT UQ_SprawaRma_Numer UNIQUE (NumerRma),
CONSTRAINT CK_SprawaRma_Numer CHECK (NumerRma LIKE
'RMA-[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]-[0-9]')
);
Klucz SprawaId jest liczbą wewnętrzną, a NumerRma służy światu zewnętrznemu. Relacje z innymi tabelami opierają się na kluczu wewnętrznym, więc zmiana formatu numeru nie wymaga przepisywania kluczy obcych. Nazwy tabel i kolumn są przykładowe.
Podwójne zgłoszenie z formularza
Klient klika przycisk dwa razy albo odświeża stronę po wysłaniu, a formularz wysyła ten sam ładunek ponownie. Bez zabezpieczenia powstają dwie sprawy z dwoma numerami. Formularz dołącza wtedy jednorazowy token, a tabela ma na nim indeks unikalny, więc drugi zapis zwraca numer pierwszej sprawy.
Powiązanie numeru RMA z dokumentami sprawy
Numer RMA łączy dokumenty, które powstają w różnych systemach i w różnych dniach. Potwierdzenie zgłoszenia wystawia system reklamacyjny, a korektę faktury księguje ERP. Przyjęcie zwrotu rejestruje magazyn. Bez wspólnego numeru ktoś musi te dokumenty łączyć ręcznie, po nazwisku klienta albo numerze zamówienia.
| Dokument | Wystawia | Gdzie stoi numer RMA | Uwaga |
|---|---|---|---|
| Potwierdzenie zgłoszenia | system RMA | temat i treść wiadomości | numer w temacie pozwala przypisać odpowiedź klienta do sprawy |
| Protokół przyjęcia towaru | magazyn lub serwis | pole sprawy w protokole | zapisuje stan towaru i datę odbioru |
| Decyzja o reklamacji | dział obsługi | treść pisma do klienta | rozstrzygnięcie i sposób załatwienia sprawy |
| Dokument magazynowy zwrotu | WMS | opis lub pole dodatkowe dokumentu | numer dokumentu nadaje WMS |
| Korekta faktury | ERP | uwagi lub pole dodatkowe | numer korekty nadaje ERP |
Reguła: numer RMA trafia do dokumentu jako odnośnik w polu opisu, a numer samego dokumentu nadaje system, w którym ten dokument powstaje.
Dokumenty zapisuje się w tabeli powiązanej ze sprawą kluczem wewnętrznym, a zapytanie po numerze RMA zwraca całą historię w jednym wyniku.
SELECT s.NumerRma, d.TypDokumentu, d.NumerDokumentu, d.DataWystawienia
FROM dbo.SprawaRma AS s
JOIN dbo.DokumentRma AS d ON d.SprawaId = s.SprawaId
WHERE s.NumerRma = @NumerRma
ORDER BY d.DataWystawienia;
Wynik pokazuje, na którym etapie jest sprawa i co jeszcze musi się wydarzyć. Statusy sprawy i dozwolone przejścia opisuje artykuł o programie do zarządzania reklamacjami, a terminy odpowiedzi - tekst o terminach i raportach reklamacji.

Numer jako odnośnik w ERP i WMS
Przy integracji system RMA przekazuje numer razem z poleceniem, na przykład zlecenia przyjęcia zwrotu do WMS albo korekty do ERP. System docelowy zapisuje go w polu referencyjnym i zwraca własny numer dokumentu, który system RMA dopisuje do sprawy. Oba numery wskazują wtedy na siebie nawzajem. Zasady wymiany danych z magazynem opisuje tekst o integracji systemów magazynowych.
Numer RMA na przesyłce i etykiecie zwrotnej
Magazyn rozpoznaje paczkę zwrotną po etykiecie, a nie po nazwisku nadawcy, więc numer musi być na niej czytelny dla skanera. W praktyce paczka niesie dwa numery: list przewozowy nadany przez kuriera i numer RMA nadany przez sprzedawcę. Skaner odczytuje oba, a system łączy je w jednej sprawie.
| Element etykiety | Nadaje | Zawartość | Rola przy odbiorze |
|---|---|---|---|
| Numer listu przewozowego | przewoźnik | numer śledzenia przesyłki | potwierdza, że paczka dotarła do magazynu |
| Numer RMA | sprzedawca | RMA-2026-000123-3 | wskazuje sprawę w systemie |
| Adres zwrotny | sprzedawca | tekst adresu | kieruje paczkę do właściwego magazynu |
Reguła: kod kreskowy zawiera wyłącznie numer RMA, a dane sprawy system pobiera z bazy, bo etykieta nie może się zdezaktualizować po zmianie danych w sprawie.

Symbolika kodu i szablon etykiety
Code 128 koduje pełny zestaw znaków ASCII, w tym myślnik, więc numer z przykładu mieści się w jednym kodzie bez konwersji. Kod QR wymaga skanera obrazowego, natomiast Code 128 odczyta także prosty skaner laserowy. Dobór symboliki dla magazynu opisuje artykuł o kodach EAN i GS1-128. Etykieta na drukarce Zebra powstaje z szablonu ZPL.
^XA
^PW812
^FO40,40^A0N,40,40^FDZWROT - RMA^FS
^FO40,100^BY3^BCN,120,Y,N,N^FDRMA-2026-000123-3^FS
^XZ
Szablon wstawia numer jako kod kreskowy z linią czytelną dla człowieka. Odczyt wydruku skanerem jest częścią testu wdrożeniowego etykiety, bo zbyt mały moduł kodu albo słaby kontrast obniżają skuteczność skanowania.
Numer RMA a numer SSCC
Numer RMA nie należy do systemu identyfikatorów GS1, więc nie zastępuje SSCC, czyli numeru jednostki logistycznej, na przykład palety zwrotnej. Zwrot całej palety może nosić obie etykiety: SSCC identyfikuje jednostkę w łańcuchu dostaw, a numer RMA wskazuje sprawę u sprzedawcy. Budowę SSCC omawia strona etykieta logistyczna GS1, a wysyłkę z magazynu do kurierów - artykuł firmy kurierskie i wysyłka z magazynu.
Dostęp klienta do statusu po numerze RMA
Numery nadawane kolejno da się zgadywać: klient, który ma RMA-2026-000123-3, może wpisać sąsiedni numer i zobaczyć cudzą sprawę. Cyfra kontrolna tego nie zatrzyma, bo atakujący też ją policzy. Portal statusu wymaga więc drugiego elementu znanego tylko właścicielowi sprawy, na przykład adresu e-mail podanego w zgłoszeniu.
async function sprawdzStatus(numerRma, email) {
const odpowiedz = await fetch('/api/rma/status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ numerRma, email })
});
if (!odpowiedz.ok) {
return null;
}
return odpowiedz.json();
}
Serwer zwraca ten sam kod błędu i ten sam komunikat dla nieistniejącego numeru oraz dla numeru z niepasującym adresem, więc odpowiedź nie zdradza, które numery istnieją. Liczbę prób z jednego adresu IP ogranicza się dodatkowo. Dane osobowe przesyła się w treści żądania POST, a nie w adresie URL, bo adresy trafiają do logów serwera i historii przeglądarki.
Zakres portalu dla odbiorców firmowych i indywidualnych opisuje artykuł o dostępie klientów B2B i B2C do systemu RMA, a kanały zgłoszeń - tekst o reklamacjach online.
Przypadki brzegowe numeracji RMA
Numeracja działa bez zarzutu, dopóki sprawa ma jeden numer i jedną przesyłkę. Kłopoty zaczynają się przy wyjątkach, które trzeba zapisać w regułach, zanim się zdarzą.
- Anulowanie sprawy - numer nie wraca do puli, a sprawa dostaje status anulowanej, żeby wcześniejsza korespondencja nadal wskazywała właściwy rekord.
- Kilka przesyłek w jednej sprawie - sprawa ma jeden numer RMA i wiele numerów listów przewozowych zapisanych w osobnej tabeli.
- Kilka spraw w jednej paczce - klient odsyła razem towary z dwóch zamówień, a magazyn skanuje dwie etykiety RMA i przypisuje je do jednego przyjęcia.
- Zmiana formatu - stare numery zostają w bazie bez zmian, a nowy format rozpoznaje się po wersji maski zapisanej w osobnej kolumnie.
Migracja numeracji z arkusza kalkulacyjnego
Firmy zaczynające od arkusza mają już numery nadane ręcznie, często w kilku formatach. Przy migracji importuje się je bez zmian jako numery historyczne, a licznik nowej numeracji ustawia się powyżej największej dotychczasowej liczby z danego roku. Indeks unikalny wychwyci duplikaty w danych źródłowych podczas importu, więc można je wyjaśnić przed uruchomieniem produkcyjnym.

W sklepie internetowym numer łączy się dodatkowo z zamówieniem i korespondencją, co omawia tekst o reklamacjach w sklepie internetowym.




