diff --git a/public/docs/openapi.json b/public/docs/openapi.json index 9775579..180f80b 100644 --- a/public/docs/openapi.json +++ b/public/docs/openapi.json @@ -490,6 +490,56 @@ } } }, + "/retribusi/v1/summary/hourly": { + "get": { + "tags": ["Summary"], + "summary": "Get hourly summary", + "description": "Mendapatkan rekap per jam untuk chart (24 jam)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date", + "example": "2025-01-01" + } + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, "/retribusi/v1/dashboard/daily": { "get": { "tags": ["Dashboard"], @@ -548,6 +598,97 @@ } } }, + "/retribusi/v1/dashboard/by-category": { + "get": { + "tags": ["Dashboard"], + "summary": "Get by category chart data", + "description": "Data chart grouped by category (bar/donut chart)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, + "/retribusi/v1/dashboard/summary": { + "get": { + "tags": ["Dashboard"], + "summary": "Get summary statistics", + "description": "Mendapatkan summary statistics (stat cards)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "date", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, "/retribusi/v1/realtime/stream": { "get": { "tags": ["Realtime"], @@ -598,6 +739,1075 @@ } } } + }, + "/retribusi/v1/frontend/locations/{code}": { + "get": { + "tags": ["Frontend"], + "summary": "Get location detail", + "description": "Mendapatkan detail location berdasarkan code", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Location code" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "404": { + "description": "Location not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "put": { + "tags": ["Frontend"], + "summary": "Update location", + "description": "Update location (code tidak bisa diubah)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "is_active": { + "type": "integer", + "enum": [0, 1] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Location updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "404": { + "description": "Location not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "tags": ["Frontend"], + "summary": "Delete location", + "description": "Soft delete location (admin only)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Location deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "403": { + "description": "Forbidden (admin only)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/retribusi/v1/frontend/gates": { + "get": { + "tags": ["Frontend"], + "summary": "Get gates list", + "description": "Mendapatkan daftar gates dengan pagination", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + }, + "post": { + "tags": ["Frontend"], + "summary": "Create gate", + "description": "Membuat gate baru (operator/admin only)", + "security": [ + { + "BearerAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["location_code", "gate_code", "name", "direction", "is_active"], + "properties": { + "location_code": { + "type": "string", + "example": "kerkof_01" + }, + "gate_code": { + "type": "string", + "example": "gate01" + }, + "name": { + "type": "string", + "example": "Gate 01" + }, + "direction": { + "type": "string", + "enum": ["in", "out"], + "example": "in" + }, + "camera": { + "type": "string", + "description": "Camera URL (HLS, RTSP, HTTP) atau camera ID", + "example": "https://example.com/stream.m3u8", + "maxLength": 500 + }, + "is_active": { + "type": "integer", + "enum": [0, 1], + "example": 1 + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Gate created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "409": { + "description": "Conflict (gate already exists)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/retribusi/v1/frontend/gates/{location_code}/{gate_code}": { + "get": { + "tags": ["Frontend"], + "summary": "Get gate detail", + "description": "Mendapatkan detail gate berdasarkan location_code dan gate_code", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "location_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "404": { + "description": "Gate not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "put": { + "tags": ["Frontend"], + "summary": "Update gate", + "description": "Update gate (location_code dan gate_code tidak bisa diubah)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "location_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "direction": { + "type": "string", + "enum": ["in", "out"] + }, + "camera": { + "type": "string", + "description": "Camera URL (HLS, RTSP, HTTP) atau camera ID", + "maxLength": 500 + }, + "is_active": { + "type": "integer", + "enum": [0, 1] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Gate updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "404": { + "description": "Gate not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "tags": ["Frontend"], + "summary": "Delete gate", + "description": "Soft delete gate (admin only)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "location_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Gate deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, + "/retribusi/v1/frontend/tariffs": { + "get": { + "tags": ["Frontend"], + "summary": "Get tariffs list", + "description": "Mendapatkan daftar tariffs dengan pagination", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + }, + "post": { + "tags": ["Frontend"], + "summary": "Create tariff", + "description": "Membuat tariff baru (operator/admin only)", + "security": [ + { + "BearerAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["location_code", "gate_code", "category", "price"], + "properties": { + "location_code": { + "type": "string" + }, + "gate_code": { + "type": "string" + }, + "category": { + "type": "string", + "enum": ["person_walk", "motor", "car"] + }, + "price": { + "type": "integer", + "minimum": 0 + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Tariff created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, + "/retribusi/v1/frontend/tariffs/{location_code}/{gate_code}/{category}": { + "get": { + "tags": ["Frontend"], + "summary": "Get tariff detail", + "description": "Mendapatkan detail tariff berdasarkan location_code, gate_code, dan category", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "location_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "category", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "404": { + "description": "Tariff not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "put": { + "tags": ["Frontend"], + "summary": "Update tariff", + "description": "Update tariff price (operator/admin only)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "location_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "category", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["price"], + "properties": { + "price": { + "type": "integer", + "minimum": 0 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Tariff updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + }, + "delete": { + "tags": ["Frontend"], + "summary": "Delete tariff", + "description": "Hard delete tariff (admin only)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "location_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "category", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Tariff deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, + "/retribusi/v1/frontend/audit-logs": { + "get": { + "tags": ["Frontend"], + "summary": "Get audit logs", + "description": "Mendapatkan audit trail history dengan pagination dan filter", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "entity", + "in": "query", + "schema": { + "type": "string", + "enum": ["locations", "gates", "tariffs"] + } + }, + { + "name": "action", + "in": "query", + "schema": { + "type": "string", + "enum": ["create", "update", "delete"] + } + }, + { + "name": "entity_key", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "start_date", + "in": "query", + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "end_date", + "in": "query", + "schema": { + "type": "string", + "format": "date" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, + "/retribusi/v1/frontend/entry-events": { + "get": { + "tags": ["Frontend"], + "summary": "Get entry events", + "description": "Mendapatkan daftar raw entry events (data mentah dari mesin)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "category", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "start_date", + "in": "query", + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "end_date", + "in": "query", + "schema": { + "type": "string", + "format": "date" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, + "/retribusi/v1/frontend/streams": { + "get": { + "tags": ["Frontend"], + "summary": "Get streams list", + "description": "Get list of streams (alias untuk gates)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, + "/retribusi/v1/realtime/snapshot": { + "get": { + "tags": ["Realtime"], + "summary": "Get snapshot", + "description": "Mendapatkan snapshot data untuk dashboard cards", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "date", + "in": "query", + "schema": { + "type": "string", + "format": "date" + }, + "description": "Date (default: today)" + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } + }, + "/retribusi/v1/realtime/events": { + "get": { + "tags": ["Realtime"], + "summary": "Get realtime events list", + "description": "Mendapatkan daftar realtime events (history untuk SSE)", + "security": [ + { + "BearerAuth": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "location_code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "gate_code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "category", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "start_date", + "in": "query", + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "end_date", + "in": "query", + "schema": { + "type": "string", + "format": "date" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + } + } + } } } }