Przejdź do głównej zawartości

Generator numeru referencyjnego

Stworzysz Generator numeru referencyjnego - aplikację do tworzenia unikalnych identyfikatorów w określonym formacie (np. REF-2026-0001, INV-202602-0042). System zapewnia unikalność numerów, pozwala na wybór formatu i prowadzi historię wygenerowanych kodów.

Czego się nauczysz?

  • Generowania sekwencyjnych numerów
  • Formatowania stringów z paddingiem (str_pad)
  • Pracy z datami w numeracji
  • Walidacji unikalności
  • Tworzenia konfigurowalnych wzorców

W prawdziwej pracy...

Generowanie unikalnych identyfikatorów jest podstawą każdego systemu biznesowego - numery faktur, numerów zamówień, kodów produktów, identyfikatorów transakcji. Umiejętność projektowania systemów z sekwencyjną numeracją i gwarancją unikalności jest niezbędna dla każdego programisty aplikacji enterprise.

  1. Przycisk generowania Użytkownik klika przycisk “Generuj numer” i otrzymuje nowy, unikalny numer referencyjny.

  2. Format numeru Numer składa się z prefiksu, roku i numeru sekwencyjnego (np. REF-2026-0001).

  3. Zapis do historii Każdy wygenerowany numer jest zapisywany do pliku JSON z datą utworzenia.

  4. Lista numerów Użytkownik widzi historię wszystkich wygenerowanych numerów.

Przykładowa struktura pliku JSON:

{
"references": [
{
"id": 1,
"code": "REF-2026-0001",
"format": "prefix_year_seq",
"purpose": "Faktura",
"created_at": "2026-02-10 14:30:00"
},
{
"id": 2,
"code": "REF-2026-0002",
"format": "prefix_year_seq",
"purpose": "",
"created_at": "2026-02-10 15:45:00"
},
{
"id": 3,
"code": "INV-202602-0001",
"format": "prefix_yearmonth_seq",
"purpose": "Zamówienie",
"created_at": "2026-02-11 09:00:00"
}
]
}
FormatPrzykładOpis
PREFIX-YYYY-NNNNREF-2026-0001Prefiks, rok, numer sekwencyjny
PREFIX-YYYYMM-NNNNINV-202602-0042Prefiks, rok i miesiąc, numer
YYYY/NNNN2026/0001Rok/numer
PREFIX-NNNNDOC-0001Prefiks, numer (bez daty)

Wymagane funkcje:

  • Przycisk “Generuj numer”
  • Format: PREFIX-YYYY-NNNN (np. REF-2026-0001)
  • Automatyczna inkrementacja numeru
  • Wyświetlenie wygenerowanego numeru
  • Prosty interfejs CSS

Przykładowy scenariusz:

Użytkownik klika “Generuj”. System wyświetla: “Wygenerowano: REF-2026-0001”. Po kolejnym kliknięciu: “REF-2026-0002”. Numery są unikalne i sekwencyjne.

Ocena: 3.0

Podstawowy generator numeru:

function generateReferenceNumber(array $existingCodes, string $prefix = 'REF'): string {
$year = date('Y');
$pattern = $prefix . '-' . $year . '-';
// Znajdź najwyższy numer w tym roku
$maxSeq = 0;
foreach ($existingCodes as $ref) {
if (strpos($ref['code'], $pattern) === 0) {
$seq = (int) substr($ref['code'], strlen($pattern));
$maxSeq = max($maxSeq, $seq);
}
}
$nextSeq = $maxSeq + 1;
return $pattern . str_pad($nextSeq, 4, '0', STR_PAD_LEFT);
}
// Wynik: REF-2026-0001, REF-2026-0002, ...

Generator z różnymi formatami:

function generateByFormat(array $existingCodes, string $format, string $prefix = 'REF'): string {
switch ($format) {
case 'prefix_year_seq':
// REF-2026-0001
$pattern = $prefix . '-' . date('Y') . '-';
break;
case 'prefix_yearmonth_seq':
// REF-202602-0001
$pattern = $prefix . '-' . date('Ym') . '-';
break;
case 'year_seq':
// 2026/0001
$pattern = date('Y') . '/';
break;
case 'prefix_seq':
// REF-0001
$pattern = $prefix . '-';
break;
default:
$pattern = $prefix . '-' . date('Y') . '-';
}
$maxSeq = findMaxSequence($existingCodes, $pattern);
$nextSeq = $maxSeq + 1;
return $pattern . str_pad($nextSeq, 4, '0', STR_PAD_LEFT);
}
function findMaxSequence(array $codes, string $pattern): int {
$maxSeq = 0;
foreach ($codes as $ref) {
$code = $ref['code'];
if (strpos($code, $pattern) === 0) {
$seqPart = substr($code, strlen($pattern));
$seq = (int) preg_replace('/[^0-9]/', '', $seqPart);
$maxSeq = max($maxSeq, $seq);
}
}
return $maxSeq;
}

Walidacja unikalności:

function isUnique(array $existingCodes, string $newCode): bool {
foreach ($existingCodes as $ref) {
if ($ref['code'] === $newCode) {
return false;
}
}
return true;
}
function generateUniqueCode(array $existingCodes, string $format, string $prefix): string {
$attempts = 0;
$maxAttempts = 100;
do {
$code = generateByFormat($existingCodes, $format, $prefix);
$attempts++;
if ($attempts >= $maxAttempts) {
throw new Exception("Nie można wygenerować unikalnego kodu");
}
} while (!isUnique($existingCodes, $code));
return $code;
}

Resetowanie numeracji (wariant C):

function shouldResetSequence(string $format, array $existingCodes): bool {
if (empty($existingCodes)) {
return false;
}
$lastRef = end($existingCodes);
$lastDate = date('Y-m', strtotime($lastRef['created_at']));
$currentDate = date('Y-m');
// Resetuj przy zmianie miesiąca dla formatów z miesiącem
if ($format === 'prefix_yearmonth_seq' && $lastDate !== $currentDate) {
return true;
}
// Resetuj przy zmianie roku dla formatów z rokiem
$lastYear = date('Y', strtotime($lastRef['created_at']));
$currentYear = date('Y');
if (in_array($format, ['prefix_year_seq', 'year_seq']) && $lastYear !== $currentYear) {
return true;
}
return false;
}

Zapis do historii:

function saveReference(array &$references, string $code, string $format, string $purpose = ''): int {
$newId = empty($references) ? 1 : max(array_column($references, 'id')) + 1;
$newRef = [
'id' => $newId,
'code' => $code,
'format' => $format,
'purpose' => trim($purpose),
'created_at' => date('Y-m-d H:i:s'),
];
$references[] = $newRef;
return $newId;
}

JavaScript - kopiowanie do schowka:

function copyCode(code) {
navigator.clipboard.writeText(code).then(() => {
showNotification('Skopiowano: ' + code);
}).catch(err => {
console.error('Błąd kopiowania:', err);
// Fallback dla starszych przeglądarek
fallbackCopy(code);
});
}
function fallbackCopy(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
showNotification('Skopiowano: ' + text);
}

Dostępne formaty:

function getAvailableFormats(): array {
return [
'prefix_year_seq' => [
'name' => 'PREFIX-RRRR-NNNN',
'example' => 'REF-2026-0001',
'description' => 'Prefiks, rok, numer sekwencyjny',
],
'prefix_yearmonth_seq' => [
'name' => 'PREFIX-RRRRMM-NNNN',
'example' => 'INV-202602-0001',
'description' => 'Prefiks, rok i miesiąc, numer (resetuje się co miesiąc)',
],
'year_seq' => [
'name' => 'RRRR/NNNN',
'example' => '2026/0001',
'description' => 'Rok/numer',
],
'prefix_seq' => [
'name' => 'PREFIX-NNNN',
'example' => 'DOC-0001',
'description' => 'Prefiks i numer (bez daty)',
],
];
}

Wykorzystaj lekcje!

Cotygodniowe spotkania podczas lekcji to idealny moment, by:

  • Pokazać postępy - nawet małe kroki się liczą
  • Wyjaśnić wątpliwości - pytaj, nie zgaduj
  • Skonsultować rozwiązania - feedback pomoże Ci się rozwijać

Pracuj iteracyjnie - lepiej mieć działający wariant A niż niedokończony C!