Lompat ke konten
dokumentasi.id
Commit 32b2830
v1
Star0

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

7

Endpoint API dan Skema OpenAPI

backend/config/urls.py menyatukan dua kelompok endpoint: rute yang dihasilkan SimpleRouter dan view khusus yang dipasang langsung di urlpatterns. Semua rute berada di bawah prefiks api/, karena router disertakan lewat path("api/", include(router.urls)) backend/config/urls.py:22-48.

Peta endpoint per modul

SimpleRouter didaftari satu per satu untuk 14 viewset, lalu hasilnya disertakan bersama rute khusus di dalam urlpatterns backend/config/urls.py:22-48. Pengelompokan berikut mengikuti modul pemilik viewset-nya.

graph TD
  URL["config/urls.py"] --> ROUTER["SimpleRouter: 14 register"]
  URL --> KHUSUS["urlpatterns khusus"]
  ROUTER --> MP["modul produk"]
  ROUTER --> MS["modul stok"]
  ROUTER --> MB["modul pembelian"]
  ROUTER --> MA["modul akun"]
  MP --> P1["kategori, produk, satuan, harga"]
  MS --> S1["batch, mutasi, barang-masuk, opname"]
  MB --> B1["pelanggan, transaksi, retur"]
  MA --> A1["pengguna, peran, log-aktivitas"]
  KHUSUS --> K1["api/kesehatan/"]
  KHUSUS --> K2["api/auth/sesi/"]
  KHUSUS --> K3["api/dasbor/"]
  KHUSUS --> K4["api/laporan/penjualan, stok, piutang, terlaris"]
  style URL fill:#f59e0b,color:#000
  style KHUSUS fill:#f59e0b,color:#000
  style ROUTER fill:#2d7d46,color:#fff
  style K1 fill:#2d7d46,color:#fff
  style K4 fill:#8b5cf6,color:#fff
%% fig: Peta endpoint dari SimpleRouter dan urlpatterns
%% desc: Router menghasilkan empat kelompok endpoint per modul, sementara kesehatan, sesi, dasbor, dan empat view laporan dipasang langsung di urlpatterns.
Fig. 1: Peta endpoint dari SimpleRouter dan urlpatternsRouter menghasilkan empat kelompok endpoint per modul, sementara kesehatan, sesi, dasbor, dan empat view laporan dipasang langsung di urlpatterns.
RuteviewsetModulRujukan
/api/kategori/KategoriViewSetprodukbackend/produk/views.py:33-43
/api/produk/ProdukViewSetprodukbackend/produk/views.py:46-65
/api/satuan/SatuanViewSetprodukbackend/produk/views.py:155-161
/api/harga/HargaViewSetprodukbackend/produk/views.py:164-173
/api/batch/BatchViewSetstokbackend/stok/views.py:24-26
/api/mutasi/MutasiViewSetstokbackend/stok/views.py:57-59
/api/barang-masuk/BarangMasukViewSetstokbackend/stok/views.py:73-75
/api/opname/OpnameViewSetstokbackend/stok/views.py:91-99
/api/pelanggan/PelangganViewSetpembelianbackend/pembelian/views.py:32-41
/api/transaksi/TransaksiViewSetpembelianbackend/pembelian/views.py:67-77
/api/retur/ReturViewSetpembelianbackend/pembelian/views.py:182-184
/api/pengguna/PenggunaViewSetakunbackend/akun/views.py:47-56
/api/peran/PeranViewSetakunbackend/akun/views.py:79-83
/api/log-aktivitas/LogAktivitasViewSetakunbackend/akun/views.py:86-88

Empat viewset hanya menyediakan sebagian aksi: KategoriViewSet membatasi http_method_names pada get, post, dan patch saja backend/produk/views.py:33-43. ProdukViewSet menambahkan komentar bahwa penghapusan tidak disediakan karena produk lama dinonaktifkan backend/produk/views.py:46-65. BatchViewSet dan MutasiViewSet hanya list dan retrieve backend/stok/views.py:24-26. TransaksiViewSet memilih TransaksiSerializer untuk list dan TransaksiDetailSerializer untuk aksi lain backend/pembelian/views.py:67-77.

view khusus di luar router

Rute khusus dideklarasikan sebagai daftar urlpatterns backend/config/urls.py:38-48.

RuteviewPerilakuRujukan
/api/kesehatan/kesehatanmengembalikan {"status": "ok"}backend/akun/views.py:29-30
/api/_allauth/include("allauth.headless.urls")rute headless allauthbackend/config/urls.py:38-48
/api/auth/sesi/SesiViewensure_csrf_cookie plus AllowAnybackend/akun/views.py:33-44
/api/dasbor/DasborViewisi mengikuti izin penggunabackend/laporan/views.py:166-172
/api/laporan/*LaporanPenjualanView, LaporanTerlarisView, LaporanStokView, LaporanPiutangViewdaftar baris laporanbackend/laporan/views.py:43-46

api/kesehatan/ dipanggil langsung oleh healthcheck container lewat HTTP, jadi rute ini dikecualikan dari pengalihan SSL lewat SECURE_REDIRECT_EXEMPT backend/config/settings.py:143-144.

Paginasi dan filter query string

Paginasi default memakai Paginasi dengan page_size = 25, parameter pengubah bernama ukuran, dan batas max_page_size = 200 backend/inti/paginasi.py:4-7. Kelas itu dipasang sebagai DEFAULT_PAGINATION_CLASS di REST_FRAMEWORK backend/config/settings.py:147-159. KategoriViewSet dan PeranViewSet mematikan paginasi dengan pagination_class = None backend/produk/views.py:33-43 dan backend/akun/views.py:79-83.

Filter dibaca langsung dari self.request.query_params di get_queryset:

RuteQuery stringRujukan
/api/produk/q, kategori, aktif=1, status=habis|menipis|amanbackend/produk/views.py:74-88
/api/harga/produkbackend/produk/views.py:164-173
/api/batch/produk, ada_sisa=1, q, status=kedaluwarsabackend/stok/views.py:32-45
/api/mutasi/produk, batch, jenisbackend/stok/views.py:63-70
/api/opname/statusbackend/stok/views.py:101-107
/api/pelanggan/q, aktif=1backend/pembelian/views.py:59-64
/api/transaksi/q, pelanggan, dari, sampai, status, status_bayar=lunas|belum_lunas|jatuh_tempobackend/pembelian/views.py:94-113
/api/retur/qbackend/pembelian/views.py:190-195

Parameter ekspor dan periode laporan

Parameter ekspor dideklarasikan sebagai OpenApiParameter("ekspor", str, enum=["xlsx", "pdf"]), bersama PARAM_PERIODE yang berisi dari dan sampai bertipe DATE backend/laporan/views.py:29-33. LaporanView.get memilih keluaran dari nilai parameter itu: ke_xlsx, ke_pdf, atau Response berisi data serializer backend/laporan/views.py:54-61.

sequenceDiagram
  participant K as Klien
  participant L as LaporanView.get
  participant P as ambil_periode
  participant E as laporan.ekspor
  K->>L: "GET /api/laporan/penjualan/?dari&sampai&ekspor"
  L->>P: "ambil_periode(request)"
  P-->>L: "(dari, sampai)"
  alt dari > sampai
    P-->>K: "ValidationError: Tanggal awal setelah tanggal akhir."
  else ekspor=xlsx
    L->>E: "ke_xlsx(judul, kolom, baris, nama_file)"
  else ekspor=pdf
    L->>E: "ke_pdf(judul, periode, kolom, baris, nama_file)"
  else tanpa ekspor
    L-->>K: "Response(serializer_class(baris, many=True).data)"
  end
%% fig: Siklus satu request laporan dengan parameter ekspor
%% desc: ambil_periode memvalidasi rentang tanggal, lalu get memilih berkas xlsx, berkas pdf, atau JSON sesuai nilai ekspor.
Fig. 2: Siklus satu request laporan dengan parameter eksporambil_periode memvalidasi rentang tanggal, lalu get memilih berkas xlsx, berkas pdf, atau JSON sesuai nilai ekspor.

ambil_periode memakai tanggal 1 bulan berjalan sebagai default dari dan hari ini sebagai default sampai; bila rentang terbalik, view melempar ValidationError({"dari": ["Tanggal awal setelah tanggal akhir."]}) backend/laporan/views.py:36-42.

RuteParameter yang dideklarasikanRujukan
/api/laporan/penjualan/dari, sampai, ekspor, per (hari/bulan)backend/laporan/views.py:85-92
/api/laporan/produk-terlaris/dari, sampai, eksporbackend/laporan/views.py:112-114
/api/laporan/stok/eksporbackend/laporan/views.py:137-139
/api/laporan/piutang/eksporbackend/laporan/views.py:161-163

per hanya dibaca pada laporan penjualan, dengan nilai selain bulan diperlakukan sebagai hari backend/laporan/views.py:82.

Custom action yang menambah endpoint

RuteMethodHandlerRujukan
/api/batch/{id}/kurangi/POSTBatchViewSet.kurangibackend/stok/views.py:47-54
/api/opname/{id}/setujui/POSTOpnameViewSet.setujuibackend/stok/views.py:119-127
/api/opname/{id}/tolak/POSTOpnameViewSet.tolakbackend/stok/views.py:119-127
/api/produk/{id}/foto/GETProdukViewSet.fotobackend/produk/views.py:97-103
/api/produk/{id}/foto/POSTProdukViewSet.unggah_fotobackend/produk/views.py:105-123
/api/produk/impor/POSTProdukViewSet.imporbackend/produk/views.py:125-142
/api/produk/template-impor/GETProdukViewSet.template_imporbackend/produk/views.py:144-152
/api/transaksi/{id}/bayar/POSTTransaksiViewSet.bayarbackend/pembelian/views.py:127-179
/api/transaksi/{id}/ajukan-batal/POSTTransaksiViewSet.ajukan_batalbackend/pembelian/views.py:127-179
/api/transaksi/{id}/setujui-batal/POSTTransaksiViewSet.setujui_batalbackend/pembelian/views.py:127-179
/api/transaksi/{id}/tolak-batal/POSTTransaksiViewSet.tolak_batalbackend/pembelian/views.py:127-179
/api/transaksi/{id}/nota/GETTransaksiViewSet.notabackend/pembelian/views.py:127-179
/api/pengguna/{id}/atur-password/POSTPenggunaViewSet.atur_passwordbackend/akun/views.py:61-76
/api/pengguna/{id}/reset-2fa/POSTPenggunaViewSet.reset_2fabackend/akun/views.py:61-76

Nama url_path dengan tanda hubung tetap ditulis di kode sebagai garis bawah: ajukan_batal dipetakan ke ajukan-batal backend/pembelian/views.py:127-179. TransaksiViewSet.create membalas 201 dengan TransaksiDetailSerializer backend/pembelian/views.py:120-125. unggah_foto membalas 204 setelah memeriksa settings.FOTO_MAKS_BYTE; impor memeriksa settings.IMPOR_MAKS_BYTE dan membalas HasilImporSerializer backend/produk/views.py:105-123 dan backend/produk/views.py:125-142. Kedua batas itu bernilai 2 MB dan 5 MB backend/config/settings.py:174-175.

⚠️ Satu @action bisa menjadi dua operasi OpenAPI. unggah_foto tidak memakai @action baru, melainkan @foto.mapping.post, sehingga GET dan POST berbagi path /api/produk/{id}/foto/ backend/produk/views.py:105-123. Di schema.yaml keduanya muncul sebagai produk_foto_retrieve dan produk_foto_create backend/schema.yaml:933-958.

Skema OpenAPI dan cara menjaganya selaras

schema.yaml adalah berkas openapi: 3.0.3 dengan title: Hydro API dan version: 1.0.0 backend/schema.yaml:1-4. Nilai itu berasal dari SPECTACULAR_SETTINGS, yang juga mengaktifkan COMPONENT_SPLIT_REQUEST dan memetakan enum ke MetodeBayarEnum, JenisMutasiEnum, StatusOpnameEnum, serta StatusTransaksiEnum backend/config/settings.py:161-172. Kelas skema default adalah drf_spectacular.openapi.AutoSchema backend/config/settings.py:147-159, dan rujukan enum hasil pemetaan itu terlihat pada MetodeBayarEnum di schema.yaml backend/schema.yaml:2974-2977.

Autentikasi tidak memakai Bearer: SkemaAutentikasiSesi mendaftarkan AutentikasiSesi sebagai skema cookieAuth bertipe apiKey pada cookie sessionid backend/inti/skema.py:4-9. Setiap operasi terproteksi mencantumkan security: - cookieAuth: [] backend/schema.yaml:312-313, sedangkan /api/auth/sesi/ menerima cookieAuth maupun {} sehingga tetap bisa dipanggil tanpa sesi backend/schema.yaml:13-15.

Blok paths membentang dari baris awal berkas sampai components.schemas backend/schema.yaml:1353-1354, dan blok itu dimulai dari /api/auth/sesi/ backend/schema.yaml:5-6.

Parameter laporan tergambar apa adanya di skema: /api/laporan/penjualan/ memuat dari, ekspor, per, dan sampai backend/schema.yaml:286-309, sementara /api/laporan/piutang/ hanya memuat ekspor backend/schema.yaml:324-333.

⚠️ schema.yaml adalah hasil generate, bukan berkas yang disunting tangan. Setelah endpoint berubah, jalankan manage.py spectacular --file schema.yaml --fail-on-warn dari backend/, lalu npm run tipe-api dari frontend/; opsi --fail-on-warn menggagalkan perintah bila ada bagian skema yang belum terdokumentasi README.md:62-67. Skrip tipe-api menjalankan openapi-typescript ../backend/schema.yaml -o src/lib/api-types.ts frontend/package.json:9.

⚠️ schema.yaml hanya memuat endpoint yang dihasilkan DRF. api/kesehatan/ dan api/_allauth/ tidak muncul di sana, karena blok paths langsung dimulai dari /api/auth/sesi/ backend/schema.yaml:5-6.