adding revenue handlers and shell

This commit is contained in:
samantha42
2026-03-24 12:09:19 +01:00
parent 33b100f325
commit 1a9fe3adc7
13 changed files with 688 additions and 37 deletions

View File

@@ -0,0 +1,44 @@
package handlers
import (
"Portifolio/internal/model"
"Portifolio/internal/service"
"database/sql"
"encoding/json"
"net/http"
_ "github.com/mattn/go-sqlite3"
)
func AddCurrencyHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var input model.CurrencyInput
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
http.Error(w, "invalid json", http.StatusBadRequest)
return
}
id, err := service.InsertCurrency(db, input)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]any{"status": "created", "id": id})
}
}
func GetCurrenciesHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
currencies, err := service.GetAllCurrencies(db)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(currencies)
}
}

View File

@@ -6,47 +6,104 @@ import (
"database/sql"
"encoding/json"
"net/http"
"runtime"
"time"
_ "github.com/mattn/go-sqlite3"
)
var startTime = time.Now()
func HealthHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
dbStatus := "ok"
if err := db.Ping(); err != nil {
dbStatus = "error: " + err.Error()
health := checkHealth(db)
if health["status"] != "ok" {
w.WriteHeader(http.StatusServiceUnavailable)
}
json.NewEncoder(w).Encode(map[string]string{
"status": "ok",
"database": dbStatus,
})
json.NewEncoder(w).Encode(health)
}
}
func checkHealth(db *sql.DB) map[string]any {
// database
dbStatus := "ok"
dbLatency := ""
t := time.Now()
if err := db.Ping(); err != nil {
dbStatus = "error: " + err.Error()
} else {
dbLatency = time.Since(t).String()
}
// db pool stats
stats := db.Stats()
// overall status
status := "ok"
if dbStatus != "ok" {
status = "degraded"
}
var mem runtime.MemStats
runtime.ReadMemStats(&mem)
return map[string]any{
"status": status,
"uptime": time.Since(startTime).String(),
"database": map[string]any{
"status": dbStatus,
"latency": dbLatency,
"open_connections": stats.OpenConnections,
"in_use": stats.InUse,
"idle": stats.Idle,
},
"memory": map[string]any{
"alloc_mb": bToMb(mem.Alloc),
"sys_mb": bToMb(mem.Sys),
"num_gc": mem.NumGC,
},
"go_version": runtime.Version(),
"goroutines": runtime.NumGoroutine(),
}
}
func bToMb(b uint64) float64 {
return float64(b) / 1024 / 1024
}
func AddCompanyHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
var input model.CompanyInput
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
http.Error(w, "invalid json", http.StatusBadRequest)
return
}
if err := service.AddCompany(input, db); err != nil {
id, err := service.InsertCompany(db, input)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]string{"status": "created"})
json.NewEncoder(w).Encode(map[string]any{"status": "created", "id": id})
}
}
func GetCompaniesHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
companies, err := service.GetAllCompanies(db)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(companies)
}
}

View File

@@ -0,0 +1,130 @@
package handlers
import (
"Portifolio/internal/model"
"Portifolio/internal/service"
"database/sql"
"encoding/json"
"net/http"
"strconv"
_ "github.com/mattn/go-sqlite3"
)
func AddRevenueReportHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var input struct {
CompanyID int `json:"company_id"`
PeriodType string `json:"period_type"`
Year int `json:"year"`
Index int `json:"index"`
}
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
http.Error(w, "invalid json", http.StatusBadRequest)
return
}
var period model.Period
switch input.PeriodType {
case "Q":
period = model.QuarterPeriod(input.Year, input.Index)
case "H":
period = model.HalfYearPeriod(input.Year, input.Index)
case "Y":
period = model.FullYearPeriod(input.Year)
default:
http.Error(w, "invalid period_type (Q/H/Y)", http.StatusBadRequest)
return
}
id, err := service.InsertPeriod(db, period)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]any{
"status": "created",
"period_id": id,
"period": period.String(),
})
}
}
func AddRevenueEntryHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var input struct {
CompanyID int `json:"company_id"`
CurrencyID int `json:"currency_id"`
PeriodType string `json:"period_type"`
Year int `json:"year"`
Index int `json:"index"`
Category string `json:"category"`
Label string `json:"label"`
Value float64 `json:"value"`
}
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
http.Error(w, "invalid json", http.StatusBadRequest)
return
}
var period model.Period
switch input.PeriodType {
case "Q":
period = model.QuarterPeriod(input.Year, input.Index)
case "H":
period = model.HalfYearPeriod(input.Year, input.Index)
case "Y":
period = model.FullYearPeriod(input.Year)
default:
http.Error(w, "invalid period_type", http.StatusBadRequest)
return
}
if err := service.InsertRevenue(db, input.CompanyID, input.CurrencyID, input.Category, input.Label, input.Value, period); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]string{"status": "created"})
}
}
func GetRevenueReportHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
companyID, _ := strconv.Atoi(r.URL.Query().Get("company_id"))
periodType := r.URL.Query().Get("period_type")
year, _ := strconv.Atoi(r.URL.Query().Get("year"))
idx, _ := strconv.Atoi(r.URL.Query().Get("index"))
entries, err := service.GetRevenue(db, companyID, model.PeriodType(periodType), year, idx)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(entries)
}
}
func GetRevenueSumHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
companyID, _ := strconv.Atoi(r.URL.Query().Get("company_id"))
periodType := r.URL.Query().Get("period_type")
year, _ := strconv.Atoi(r.URL.Query().Get("year"))
rs, err := service.SumRevenue(db, companyID, model.PeriodType(periodType), year)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(rs)
}
}