apskel-pos-backend/internal/util/accounting_util.go
2025-09-12 15:37:19 +07:00

113 lines
3.6 KiB
Go

package util
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"path/filepath"
"apskel-pos-be/internal/entities"
"github.com/google/uuid"
)
type DefaultChartOfAccount struct {
ChartOfAccounts []ChartOfAccountTemplate `json:"chart_of_accounts"`
}
type ChartOfAccountTemplate struct {
Name string `json:"name"`
Code string `json:"code"`
ChartOfAccountType string `json:"chart_of_account_type"`
ParentCode *string `json:"parent_code"`
IsSystem bool `json:"is_system"`
Accounts []AccountTemplate `json:"accounts"`
}
type AccountTemplate struct {
Name string `json:"name"`
Number string `json:"number"`
AccountType string `json:"account_type"`
OpeningBalance float64 `json:"opening_balance"`
Description *string `json:"description"`
}
func CreateDefaultChartOfAccounts(ctx context.Context,
chartOfAccountProcessor interface{}, // Use interface{} to avoid import cycle
accountProcessor interface{}, // Use interface{} to avoid import cycle
organizationID uuid.UUID,
outletID *uuid.UUID) error {
// Load the default chart of accounts template
template, err := loadDefaultChartOfAccountsTemplate()
if err != nil {
return fmt.Errorf("failed to load default chart of accounts template: %w", err)
}
// Note: In a real implementation, you would get chart of account types
// and validate that all required types exist
// Create chart of accounts and accounts
chartOfAccountMap := make(map[string]uuid.UUID)
for _, coaTemplate := range template.ChartOfAccounts {
// Note: In a real implementation, you would call the processor to create the chart of account
// For now, we'll just store the mapping
chartOfAccountMap[coaTemplate.Code] = uuid.New() // This would be the actual ID from creation
// Create accounts for this chart of account
for _, accountTemplate := range coaTemplate.Accounts {
accountReq := &entities.Account{
OrganizationID: organizationID,
OutletID: outletID,
ChartOfAccountID: chartOfAccountMap[coaTemplate.Code],
Name: accountTemplate.Name,
Number: accountTemplate.Number,
AccountType: entities.AccountType(accountTemplate.AccountType),
OpeningBalance: accountTemplate.OpeningBalance,
CurrentBalance: accountTemplate.OpeningBalance,
Description: accountTemplate.Description,
IsActive: true,
IsSystem: coaTemplate.IsSystem,
}
// Note: In a real implementation, you would call the processor to create the account
_ = accountReq
}
}
return nil
}
func loadDefaultChartOfAccountsTemplate() (*DefaultChartOfAccount, error) {
// Get the path to the template file
templatePath := filepath.Join("internal", "constants", "default_chart_of_accounts.json")
// Read the template file
data, err := ioutil.ReadFile(templatePath)
if err != nil {
return nil, fmt.Errorf("failed to read template file: %w", err)
}
// Parse the JSON
var template DefaultChartOfAccount
if err := json.Unmarshal(data, &template); err != nil {
return nil, fmt.Errorf("failed to parse template JSON: %w", err)
}
return &template, nil
}
func getChartOfAccountTypeMap(ctx context.Context, chartOfAccountProcessor interface{}) (map[string]uuid.UUID, error) {
// This is a placeholder - in a real implementation, you would call the processor
// to get all chart of account types and create a map of code -> ID
return map[string]uuid.UUID{
"ASSET": uuid.New(),
"LIABILITY": uuid.New(),
"EQUITY": uuid.New(),
"REVENUE": uuid.New(),
"EXPENSE": uuid.New(),
}, nil
}