rpl-LIB

command module
v0.0.0-...-b59eb49 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 12, 2026 License: MIT Imports: 11 Imported by: 0

README

RPLibrary Backend API

RPLibrary Backend API untuk sistem manajemen perpustakaan Lab RPL yang mendukung autentikasi dan autorisasi, manajemen katalog buku, peminjaman, pengembalian, dan waitlist buku.

1. Skema Database

Skema Database

Entitas utama:

  • prodis
  • users
  • books
  • tags
  • book_tags
  • borrowed_books
  • waitlists

Relasi penting:

  • User -> Prodi (many-to-one)
  • Book <-> Tag (many-to-many via book_tags)
  • BorrowedBook -> User dan Book
  • Waitlist -> User dan Book

Enum penting:

  • Role user: Admin, User
  • Borrow status: pending, borrowed, returned, overdue
  • Waitlist status: waiting, notified, expired, completed, cancelled

2. Justifikasi Tech Stack

Komponen Pilihan Alasan
Bahasa Go Cepat, efisien, concurrency baik, cocok untuk API production
HTTP Framework Gin Ringan, performa tinggi, middleware ecosystem matang
ORM GORM Produktif untuk CRUD, relasi, migrasi, transaksi, dan easy to read
Database PostgreSQL Kuat untuk relasi data, konsisten, battle-tested
Auth JWT Stateless auth yang sederhana untuk API mobile/webdan banyak digunakan
Dependency Injection samber/do Wiring dependency rapi dan testability lebih baik
Validasi go-playground/validator Validasi request terstruktur dan konsisten
Mailer gomail (SMTP) Mendukung alur verifikasi email, reset password, dan notifikasi melalui email
Encryption AES + bcrypt Menyediakan enkripsi data sensitif dan hashing password
Logging logrus Menyediakan logging yang konsisten dan mudah diatur
Storage FileSystem (aktif), AWS S3 (opsi) Dev-friendly local storage dan karena bisa diakses publicaly (karena ini open proejct), siap cloud jika dibutuhkan
Deployment Docker + Docker Compose Setup environment cepat dan reproducible

3. Arsitektur Codebase

Menggunakan Layered Architecture karena gampang untuk dipahami, maintainable, dan juga gampang untuk di scale up jika nanti aplikasinya berkembang.

Layered Architecture

Sehingga alur request mengikuti pattern diagram berikut:

+--------------------------------------------------------------+
|                    Application Entry Point                   |
| main.go -> load .env -> init DB ->                           |
| cmd.Command (if args) OR config.NewRestConfig(db)            |
+-------------------------------+------------------------------+
                                |
+-------------------------------v------------------------------+
| Configuration Layer (internal/config/)                       |
| - NewRouter: NoRoute, CORS, /api/ping, static /assets        |
| - NewProvider: DI repositories/services/controllers (do)     |
| - NewRestConfig: register routes + start background workers  |
+-------------------------------+------------------------------+
                                |
+-------------------------------v------------------------------+
| HTTP Layer (internal/api/routes + internal/api/controller)   |
| - Routing per modul: Auth, Book, Tag, Borrow, Waitlist, File |
| - Bind and validate input via internal/pkg/validate          |
| - Response envelope via internal/pkg/response                |
+-------------------------------+------------------------------+
                                |
+-------------------------------v------------------------------+
| Business Layer (internal/api/service/)                       |
| - User, Book, Tag, Borrow, Waitlist, JWT service             |
| - Rule borrow/waitlist, status transition, token/email flow  |
| - Worker: waitlist queue (startup + tiap 15 menit)           |
| - Worker: overdue checker (startup + harian 00:00 WIB)       |
+-------------------------------+------------------------------+
                                |
+-------------------------------v------------------------------+
| Data Access Layer (internal/api/repository/)                 |
| - Abstraksi query GORM, preload relasi, pagination           |
| - Operasi CRUD + transaksi dari service layer                |
+-------------------------------+------------------------------+
                                |
+-------------------------------v------------------------------+
| Database Layer (PostgreSQL via GORM)                         |
| - Persistensi users, books, tags, borrows, waitlists         |
+--------------------------------------------------------------+

Cross-cutting concerns yang aktif:

  • internal/middleware/: authentication, cors, only_allow, time.
  • internal/pkg/: logger, mailer, storage, validate, response, error, pagination, utils.
  • constants/: konstanta global (termasuk context keys untuk auth/role).
  • database/migrations dan database/seeders: manajemen skema dan data awal.
  • scripts/cron_functional: verifikasi flow cron waitlist dan overdue.

4. Project Structure

rpl-LIB/
├── cmd/                                      # CLI command untuk migration, seeding, help
│   └── command.go
├── constants/                                # Konstanta aplikasi yang dipakai lintas package
│   └── common.go
├── database/                                 # Setup koneksi DB, migration, seeders, dan seed JSON
│   ├── database.go
│   ├── json/
│   │   ├── books.json
│   │   ├── book_tags.json
│   │   ├── borrowed_books.json
│   │   ├── tags.json
│   │   ├── users.json
│   │   └── waitlists.json
│   ├── migrations/
│   │   └── migrate.go
│   └── seeders/
│       ├── seeder.go
│       └── seeds/
│           ├── book_seed.go
│           ├── book_tag_seed.go
│           ├── borrowed_book_seed.go
│           ├── prodi_seed.go
│           ├── tag_seed.go
│           ├── user_seed.go
│           └── waitlist_seed.go
├── docs/                                     # Bruno collection dan environment untuk dokumentasi API
│   ├── api/
│   │   ├── Auth/
│   │   ├── Book/
│   │   ├── Borrow/
│   │   ├── Tag/
│   │   └── Waitlist/
│   ├── environments/
│   │   └── local.bru
│   └── bruno.json
├── image/
│   ├── layered-architecture.jpg
│   └── skema-db.png
├── assets/                                   # File upload statis (covers, profiles)
│   ├── covers/
│   └── profiles/
├── internal/
│   ├── api/
│   │   ├── controller/                       # HTTP handler per modul (auth, book, borrow, tag, waitlist, file)
│   │   │   ├── book_controller.go
│   │   │   ├── borrow_controller.go
│   │   │   ├── file_controller.go
│   │   │   ├── tag_controller.go
│   │   │   ├── user_controller.go
│   │   │   └── waitlist_controller.go
│   │   ├── repository/                       # Abstraksi query/operasi data berbasis GORM
│   │   │   ├── book_repository.go
│   │   │   ├── borrow_repository.go
│   │   │   ├── common.go
│   │   │   ├── masterdata_repository.go
│   │   │   ├── tag_repository.go
│   │   │   ├── user_repository.go
│   │   │   └── waitlist_repository.go
│   │   ├── routes/                           # Definisi route + middleware per domain endpoint
│   │   │   ├── book_route.go
│   │   │   ├── borrow_route.go
│   │   │   ├── file_route.go
│   │   │   ├── tag_route.go
│   │   │   ├── user_route.go
│   │   │   └── waitlist_route.go
│   │   └── service/                          # Business rules, orchestration workflow, dan scheduler logic
│   │       ├── book_service.go
│   │       ├── borrow_service.go
│   │       ├── jwt_service.go
│   │       ├── tag_service.go
│   │       ├── user_service.go
│   │       └── waitlist_service.go
│   ├── config/                               # Router setup, DI provider, dan lifecycle HTTP server
│   │   ├── provide.go
│   │   ├── rest_config.go
│   │   └── rest_router_config.go
│   ├── dto/                                  # Kontrak request/response dan pesan domain
│   │   ├── book_dto.go
│   │   ├── borrow_dto.go
│   │   ├── common.go
│   │   ├── masterdata_dto.go
│   │   ├── tag_dto.go
│   │   ├── user_dto.go
│   │   └── waitlist_dto.go
│   ├── entity/                               # Model tabel dan relasi domain
│   │   ├── book_entity.go
│   │   ├── borrowed_book_entity.go
│   │   ├── common.go
│   │   ├── prodi_entity.go
│   │   ├── tag_entity.go
│   │   ├── user_entity.go
│   │   └── waitlist_entity.go
│   ├── middleware/                           # Middleware auth, CORS, role guard, dan pembatasan waktu
│   │   ├── authentication.go
│   │   ├── cors.go
│   │   ├── only_allow.go
│   │   └── time.go
│   └── pkg/
│       ├── error/                            # Error mapping dan formatting error aplikasi
│       │   └── errors.go
│       ├── form/                             # Parser helper untuk multipart/form
│       │   └── parser.go
│       ├── logger/                           # Wrapper logging
│       │   └── logger.go
│       ├── mailer/                           # Mail builder + template email
│       │   ├── mailer.go
│       │   ├── makeMail.go
│       │   └── template/
│       │       ├── borrow_overdue_email.html
│       │       ├── forgot_password_email.html
│       │       ├── verification_email.html
│       │       └── waitlist_notification_email.html
│       ├── pagination/                       # Utility pagination/filter metadata
│       │   ├── conv.go
│       │   └── meta.go
│       ├── response/                         # Standard response envelope API
│       │   └── response.go
│       ├── storage/                          # Adapter storage (filesystem, AWS S3)
│       │   ├── aws_s3.go
│       │   └── filesystem.go
│       ├── utils/                            # Utility AES, password hash, dan helper env
│       │   ├── aes.go
│       │   ├── is_prod.go
│       │   └── password.go
│       └── validate/                         # Request/body/file validation
│           ├── file_validate.go
│           └── validator.go
├── scripts/                                  # Script verifikasi fungsional cron waitlist/overdue
│   └── cron_functional/
│       └── main.go
├── .dockerignore
├── .env.example
├── .gitignore
├── docker-compose.yml
├── Dockerfile
├── go.mod
├── go.sum
├── LICENSE
├── main.go
└── README.md

5. Alur Logika Bisnis Penting

5.1 System High-Level Flow

System High-Level Flow

5.2 Auth and Profile Flow

Auth Flow

Alur Auth & Profil

  1. Register user akan memvalidasi email unik dan prodi_id, lalu simpan user dengan role User dan is_verified=false.
  2. Setelah register, sistem mengirim email verifikasi dengan token AES (format email_expiredAt) dengan masa berlaku 2 menit.
  3. Login hanya berhasil jika email terdaftar, password valid, dan akun sudah terverifikasi.
  4. Verify email hanya menerima token valid dan belum expired, lalu mengubah is_verified=true.
  5. Forgot/reset password memakai token AES dengan TTL 2 menit; jika token invalid/expired maka reset ditolak.
5.3 Borrow Flow

Borrow Flow

Alur Ketersediaan Buku

  1. Slot tersedia dihitung dari: quantity - (active_borrows + active_notified_waitlist).
  2. can_borrow=true hanya jika slot masih ada dan tidak ada antrean waiting.
  3. Jika masih ada antrean waiting, user baru tidak bisa langsung borrow walaupun ada slot.

Alur Peminjaman

  1. User membuat request borrow, sistem cek book_id valid dan buku ada.
  2. Sistem menolak jika user sudah punya borrow aktif untuk buku yang sama.
  3. Sistem menolak jika masih ada waitlist waiting pada buku tersebut.
  4. Sistem menolak jika kuota tidak tersedia (berdasarkan perhitungan slot aktif).
  5. Jika lolos validasi, borrow dibuat dengan status awal pending.
  6. Admin hanya bisa ubah status pending -> borrowed (wajib isi due_date).
  7. Admin hanya bisa ubah status borrowed/overdue -> returned.
5.4 Waitlist Flow

Waitlist Flow

Alur Waitlist

  1. User join waitlist hanya jika belum punya waitlist aktif (waiting/notified) untuk buku yang sama.
  2. Jika antrean masih kosong tapi slot buku masih tersedia, join waitlist ditolak (user diminta borrow langsung).
  3. Waitlist baru disimpan dengan status waiting.
  4. Saat queue processor berjalan, entri notified yang melewati expired_at akan diubah jadi expired.
  5. Selama masih ada slot, antrean waiting terdepan dipromosikan ke notified dengan TTL claim 30 menit.
  6. Setiap promosi waiting -> notified akan memicu email notifikasi.
  7. Claim waitlist hanya bisa oleh pemilik entri dan hanya saat status notified serta belum expired.
  8. Saat claim valid, sistem membuat borrow pending lalu mengubah waitlist menjadi completed.
5.5 Background Scheduler Flow

Background Scheduler Flow

Alur Otomasi Cron di Runtime

  1. Processor waitlist berjalan sekali saat startup, lalu periodik setiap 15 menit.
  2. Processor overdue berjalan sekali saat startup, lalu harian pada pukul 00:00 zona waktu Asia/Jakarta.
  3. Borrow dengan status aktif yang melewati due date akan diubah ke overdue dan mengirim email notifikasi keterlambatan.

6. Dokumentasi API

Dokumentasi request API disediakan dalam format Bruno Collection.

Note: Semua endpoint di dalam folder User bisa diakses oleh role Admin dan User, sedangkan endpoint di dalam folder Admin hanya bisa diakses oleh role Admin. Untuk endpoint yang memiliki akses role Admin dan User, maka pada bagian request header harus menyertakan token JWT yang didapatkan dari proses login.

Collection & Environment
Daftar Dokumen Endpoint (Bruno)
Auth
Book
Tag
Borrow
Waitlist
Cara Menggunakan Dokumentasi Bruno
  1. Install Bruno: https://www.usebruno.com/
  2. Pastikan repo sudah di clone ke lokal
  3. Buka Bruno, lalu pilih Open Collection dan arahkan ke folder docs sebagai collection.

Bruno

  1. Pilih environment docs/environments/local.bru.
  2. Pastikan server API berjalan di host/port yang sama.
  3. Jalankan request per modul.

7. Query Params: Pagination, Sorting, Filtering

Endpoint list mendukung parameter berikut:

  • page (default 1)
  • take (default 10)
  • sort (asc atau desc)
  • sort_by (contoh: id, title, author, published_year, created_at, updated_at)
  • filter
  • filter_by

Contoh filter buku:

  • filter_by=title&filter=clean architecture
  • filter_by=author&filter=martin
  • filter_by=published_year&filter=2023
  • filter_by=tag_name&filter=backend,go

8. Setup Project

8.1 Prasyarat
8.2 Konfigurasi Environment
  1. Clone Repository
git clone https://github.com/Shabrinashsf/go-gin-gorm-boilerplate.git
cd go-gin-gorm-boilerplate
  1. Salin .env.example ke .env
cp .env.example .env
  1. Isi variabel sesuai environment lokal.

Daftar variabel utama:

  • Database: DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT
  • SMTP: SMTP_HOST, SMTP_PORT, SMTP_SENDER_NAME, SMTP_SENDER_EMAIL, SMTP_AUTH_EMAIL, SMTP_AUTH_PASSWORD
  • Security: JWT_SECRET, AES_KEY
  • App: APP_PORT, APP_ENV, BE_URL, APP_URL
  • Storage cloud (opsional): AWS_ACCESS_KEY, AWS_SECRET_KEY, AWS_REGION, S3_BUCKET

Referensi lengkap: .env.example

Cara mendapatkan akun SMTP gratis menggunakan akun google:
  1. Buka Google Account
  2. Pilih menu Security dan aktifkan 2-Step Verification.
  3. Setelah itu, pilih menu App Passwords
  4. Buat nama aplikasi (ex: RPLibrary)
  5. Salin password yang diberikan, lalu masukkan ke variabel SMTP_AUTH_PASSWORD di file .env
8.3 Menjalankan Dengan Docker
docker-compose up --build -d
docker-compose exec app go run main.go --migrate
docker-compose exec app go run main.go --seed
docker-compose logs -f app
8.4 Menjalankan Lokal (Tanpa Docker App)
go mod download
go run main.go --migrate
go run main.go --seed
go run main.go

Server default berjalan di: http://localhost:8888

Jika ingin testing mengenai cron service untuk scheduler waitlist dan overdue, bisa dilihat di folder scripts/cron_functional untuk menjalankan skrip verifikasi fungsionalnya. Sebagai tambahan aplikasi mendukung graceful shutdown ketika menerima interrupt signal.

Data seeding untuk tabel borrowed_books dan waitlists bisa jadi tidak sinkron dengan response yang sudah ada (karena data testing api belum dipindah ke seeding, karena terlanjur drop db dan ternyata lupa data testing api belum dipindah ke seeding, maafkan :D).

Made with ❤️ by Shabrinashsf

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL