Skip to main content

Universal auto-number generator by Risna Berti (Nanumber)

Project description

📦 Risnaberti Nanumber

PyPI version Python version License Status

Universal auto-number generator library by Risna Berti (Nana)
Aman, fleksibel, dan mudah diintegrasikan ke FastAPI, Django, Flask, atau framework lainnya.


✨ Fitur Utama

✅ Format fleksibel: #SUP-{y}{number}#SUP-250001
✅ Reset otomatis per tahun / bulan
✅ Thread-safe (aman dari race condition)
✅ Multi-storage (Memory, SQLite, PostgreSQL, MySQL)
✅ Siap integrasi ke FastAPI / Django
✅ Terinspirasi dari Laravel Nanamber


🧱 Instalasi

pip install risnaberti-nanumber

⚙️ Quick Start (Demo Mode)

🧩 Gunakan MemoryStorage untuk testing atau eksplorasi awal.
Data hanya disimpan sementara di RAM — akan hilang setelah program dihentikan.

from risnaberti.nanumber import NumberGenerator, MemoryStorage

# Gunakan penyimpanan in-memory (sementara)
storage = MemoryStorage()
gen = NumberGenerator(storage)

print(gen.generate("supplier", "#SUP-{y}{number}"))
# 👉 #SUP-250001

Cocok untuk demo atau unit test, bukan untuk produksi.


💾 Production Mode (Persistent Storage)

💾 Gunakan SQLAlchemyStorage untuk penyimpanan permanen di database.
Nanumber akan otomatis membuat tabel auto_numbers untuk menyimpan last_value.

from risnaberti.nanumber import NumberGenerator, SQLAlchemyStorage

# Gunakan SQLite (atau PostgreSQL/MySQL)
storage = SQLAlchemyStorage("sqlite:///nanumber.db")

gen = NumberGenerator(storage)
print(gen.generate("invoice", "INV-{Y}-{number:04d}"))
# 👉 INV-2025-0001

Setelah restart aplikasi, nomor akan berlanjut dari nilai terakhir di tabel database.


⚙️ Integrasi dengan FastAPI

1️⃣ Instal dependency

pip install fastapi[all] risnaberti-nanumber

2️⃣ Tambahkan endpoint

# app/main.py
from fastapi import FastAPI
from risnaberti.nanumber import NumberGenerator, SQLAlchemyStorage

app = FastAPI()

storage = SQLAlchemyStorage("sqlite:///nanumber.db")
gen = NumberGenerator(storage)

@app.get("/generate/{entity}")
def generate_number(entity: str):
    format_map = {
        "supplier": "#SUP-{y}{number:04d}",
        "invoice": "INV-{Y}-{number:05d}",
    }
    fmt = format_map.get(entity, "{Y}{number:04d}")
    return {"entity": entity, "number": gen.generate(entity, fmt)}

3️⃣ Jalankan server

uvicorn app.main:app --reload

Buka:


🧩 Integrasi dengan Django

# apps/supplier/signals.py
from django.db.models.signals import pre_save
from django.dispatch import receiver
from .models import Supplier
from risnaberti.nanumber import NumberGenerator, SQLAlchemyStorage

storage = SQLAlchemyStorage("sqlite:///db.sqlite3")
gen = NumberGenerator(storage)

@receiver(pre_save, sender=Supplier)
def generate_supplier_code(sender, instance, **kwargs):
    if not instance.code:
        instance.code = gen.generate("supplier", "#SUP-{y}{number}")

🔢 Contoh Format Nomor

Template Hasil Keterangan
#SUP-{y}{number} #SUP-250001 Tahun 2 digit
INV-{Y}-{number:05d} INV-2025-00001 Tahun penuh + padding
{m}{number:03d} 11001 Reset otomatis tiap tahun

🧠 Uji Multi-thread (Concurrency Test)

import threading
from risnaberti.nanumber import NumberGenerator, SQLAlchemyStorage

storage = SQLAlchemyStorage("sqlite:///test.db")
gen = NumberGenerator(storage)

def worker():
    print(gen.generate("supplier", "#SUP-{y}{number:04d}"))

threads = [threading.Thread(target=worker) for _ in range(10)]
for t in threads: t.start()
for t in threads: t.join()

Output:

#SUP-250001
#SUP-250002
#SUP-250003
...

Semua hasil unik — tidak ada duplikasi walaupun 10 thread berjalan bersamaan 🚀


📁 Struktur Package

risnaberti/
  nanumber/
    ├── core.py
    ├── exceptions.py
    ├── config.py
    └── storage/
        ├── base.py
        ├── memory.py
        ├── sqlite.py
        └── sqlalchemy_storage.py

📄 Lisensi

MIT © 2025 Risna Berti


💬 Kontribusi

Pull request selalu terbuka 🎉
Jika kamu menemukan bug atau ide fitur baru, silakan buat issue di GitHub:

👉 https://github.com/risnaberti/nanumber


🌟 Dukungan & Kontak

Jika kamu menggunakan library ini di project kamu, kasih bintang di GitHub ⭐

📧 Email: risnaberti07@gmail.com 🐙 GitHub: @risnaberti


Made with ❤️ by Risna Berti

"Because numbering should be smart, safe, and beautiful."

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

risnaberti_nanumber-0.1.1.tar.gz (10.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

risnaberti_nanumber-0.1.1-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file risnaberti_nanumber-0.1.1.tar.gz.

File metadata

  • Download URL: risnaberti_nanumber-0.1.1.tar.gz
  • Upload date:
  • Size: 10.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for risnaberti_nanumber-0.1.1.tar.gz
Algorithm Hash digest
SHA256 85ac1f8cc689e240294b8789ff09072bae8c54107c9e40ef05274a5e339f1b3a
MD5 03d36a8f4ca924202ab8348346f94c17
BLAKE2b-256 df5b8a790370ddef7066c3ce25f1b64011d6cbb1125fd52bf598f7a9d6d2fcb1

See more details on using hashes here.

File details

Details for the file risnaberti_nanumber-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for risnaberti_nanumber-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 949042de02f7546ab748c1cd401a7168b2b95a6f75359eee0a35283ae0fb8103
MD5 a380a9a39ee565a57839f80fb29d99bb
BLAKE2b-256 5062fd6d0fd99387173734b1c6719a0c4edd10dc0d1eee6e54368bf7073f11ef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page