feat: integrate Grafana dashboards into BOC DashboardPage
- Add Infrastructure Health section with CPU/Memory/Disk panels - Add Service Status section with PM2/Docker panels - Create GrafanaPanel component for iframe embedding - Build passes successfully
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"boc/repository"
|
||||
)
|
||||
|
||||
// FinanceService handles business logic for finance operations
|
||||
type FinanceService struct {
|
||||
repo *repository.FinanceRepository
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewFinanceService(db *sql.DB) *FinanceService {
|
||||
return &FinanceService{
|
||||
repo: repository.NewFinanceRepository(db),
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// ListInvoices returns all invoices
|
||||
func (s *FinanceService) ListInvoices(ctx context.Context) ([]repository.Invoice, error) {
|
||||
return s.repo.ListInvoices(ctx)
|
||||
}
|
||||
|
||||
// ListExpenses returns all expenses
|
||||
func (s *FinanceService) ListExpenses(ctx context.Context) ([]repository.Expense, error) {
|
||||
return s.repo.ListExpenses(ctx)
|
||||
}
|
||||
|
||||
// CreateExpense creates a new expense with validation
|
||||
func (s *FinanceService) CreateExpense(ctx context.Context, e *repository.Expense) error {
|
||||
if e.Category == "" {
|
||||
return fmt.Errorf("expense category is required")
|
||||
}
|
||||
if e.Amount <= 0 {
|
||||
return fmt.Errorf("expense amount must be positive")
|
||||
}
|
||||
if e.Status == "" {
|
||||
e.Status = "pending"
|
||||
}
|
||||
return s.repo.CreateExpense(ctx, e)
|
||||
}
|
||||
|
||||
// GetCashFlow returns income, outstanding, and expenses
|
||||
func (s *FinanceService) GetCashFlow(ctx context.Context) (income, outstanding, expenses float64, err error) {
|
||||
return s.repo.GetCashFlow(ctx)
|
||||
}
|
||||
|
||||
// GetAccounts returns all ledger accounts
|
||||
func (s *FinanceService) GetAccounts(ctx context.Context) ([]repository.Account, error) {
|
||||
return s.repo.GetAccounts(ctx)
|
||||
}
|
||||
|
||||
// GetBalanceSheet returns a simplified balance sheet
|
||||
func (s *FinanceService) GetBalanceSheet(ctx context.Context) (map[string]interface{}, error) {
|
||||
accounts, err := s.repo.GetAccounts(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var assets, liabilities, equity float64
|
||||
for _, a := range accounts {
|
||||
switch a.Type {
|
||||
case "asset":
|
||||
assets += a.Balance
|
||||
case "liability":
|
||||
liabilities += a.Balance
|
||||
case "equity":
|
||||
equity += a.Balance
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"assets": assets,
|
||||
"liabilities": liabilities,
|
||||
"equity": equity,
|
||||
"accounts": accounts,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user