package profiles import ( "embed" "encoding/json" "fmt" "sort" "sync" "git.dumerain.org/alban/paycheck/internal/models" ) //go:embed profiles.json var embeddedFS embed.FS type profileJSON struct { Label string `json:"label"` Matricule string `json:"matricule,omitempty"` // ✅ pour auto-match avec l'agent importé Rates map[string]float64 `json:"rates"` ForfaitDimFerie float64 `json:"forfait_dim_ferie"` } type Repo struct { mu sync.RWMutex profiles map[string]models.Profile rules models.GlobalRules } // NewEmbeddedRepo charge les profils depuis profiles.json (embarqué). func NewEmbeddedRepo() (*Repo, *models.GlobalRules, error) { b, err := embeddedFS.ReadFile("profiles.json") if err != nil { return nil, nil, err } var raw map[string]profileJSON if err := json.Unmarshal(b, &raw); err != nil { return nil, nil, fmt.Errorf("profiles.json invalide: %w", err) } repo := &Repo{profiles: map[string]models.Profile{}} for id, p := range raw { repo.profiles[id] = models.Profile{ ID: id, Label: p.Label, Matricule: p.Matricule, T456: p.Rates["456"], T458: p.Rates["458"], T459: p.Rates["459"], T471: p.Rates["471"], } if repo.rules.ForfaitDimFerie == 0 { repo.rules.ForfaitDimFerie = p.ForfaitDimFerie } } // Valeur par défaut de sécurité si le JSON n'a aucun profil if repo.rules.ForfaitDimFerie == 0 { repo.rules.ForfaitDimFerie = 120 } return repo, &repo.rules, nil } // List renvoie les profils triés par label (dropdown stable). func (r *Repo) List() ([]models.ProfileListItem, error) { r.mu.RLock() defer r.mu.RUnlock() items := make([]models.ProfileListItem, 0, len(r.profiles)) for _, p := range r.profiles { items = append(items, models.ProfileListItem{ ID: p.ID, Label: p.Label, Matricule: p.Matricule, }) } sort.Slice(items, func(i, j int) bool { return items[i].Label < items[j].Label }) return items, nil } func (r *Repo) Get(id string) (models.Profile, error) { r.mu.RLock() defer r.mu.RUnlock() p, ok := r.profiles[id] if !ok { return models.Profile{}, fmt.Errorf("profil introuvable: %s", id) } return p, nil } func (r *Repo) Rules() models.GlobalRules { r.mu.RLock() defer r.mu.RUnlock() return r.rules }