package service import ( "context" "fmt" "time" "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/repository" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "gorm.io/gorm" ) type SequenceService interface { GenerateNumber(ctx context.Context, clientId string, config pkgdto.SequenceConfig) (string, error) GenerateNumberWithPeriod(ctx context.Context, clientId string, config pkgdto.SequenceConfig, suffix string) (string, error) GenerateNumberWithSuffix(ctx context.Context, clientId string, config pkgdto.SequenceConfig, suffix string) (string, error) GetNextSequence(ctx context.Context, clientId string, config pkgdto.SequenceConfig) (int, error) GenerateDocumentNumber(ctx context.Context, clientId string, docType string, config pkgdto.SequenceConfig) (string, error) } type sequenceService struct { db *gorm.DB sequenceRepo repository.SequenceRepository } func NewSequenceService(sequenceRepo repository.SequenceRepository, db *gorm.DB) SequenceService { return &sequenceService{ sequenceRepo: sequenceRepo, db: db, } } // GenerateNumberWithSuffix implements SequenceService. func (s *sequenceService) GenerateNumberWithSuffix(ctx context.Context, clientId string, config pkgdto.SequenceConfig, suffix string) (string, error) { period := config.Period seq, err := s.sequenceRepo.GetOrCreateSequence(ctx, s.db, clientId, config.EntityType, period) if err != nil { return "", err } seq.CurrentSeq++ if err := s.sequenceRepo.UpdateSequence(ctx, s.db, seq); err != nil { return "", err } refNum := fmt.Sprintf("%s-%s-%04d", config.Prefix, suffix, seq.CurrentSeq) return refNum, nil } func (s *sequenceService) GenerateNumber(ctx context.Context, clientId string, config pkgdto.SequenceConfig) (string, error) { period := config.Period if period == "" { period = "-" } seq, err := s.sequenceRepo.GetOrCreateSequence(ctx, s.db, clientId, config.EntityType, period) if err != nil { return "", err } seq.CurrentSeq++ if err := s.sequenceRepo.UpdateSequence(ctx, s.db, seq); err != nil { return "", err } refNum := fmt.Sprintf("%s-%04d", config.Prefix, seq.CurrentSeq) return refNum, nil } func (s *sequenceService) GenerateNumberWithPeriod(ctx context.Context, clientId string, config pkgdto.SequenceConfig, suffix string) (string, error) { if config.Period == "" { config.Period = time.Now().Format("0601") } period := config.Period seq, err := s.sequenceRepo.GetOrCreateSequence(ctx, s.db, clientId, config.EntityType, period) if err != nil { return "", err } seq.CurrentSeq++ if err := s.sequenceRepo.UpdateSequence(ctx, s.db, seq); err != nil { return "", err } refNum := fmt.Sprintf("%s-%s-%s-%04d", config.Prefix, suffix, period, seq.CurrentSeq) return refNum, nil } func (s *sequenceService) GetNextSequence(ctx context.Context, clientId string, config pkgdto.SequenceConfig) (int, error) { period := config.Period if period == "" { period = "-" } seq, err := s.sequenceRepo.GetOrCreateSequence(ctx, s.db, clientId, config.EntityType, period) if err != nil { return 0, err } seq.CurrentSeq++ if err := s.sequenceRepo.UpdateSequence(ctx, s.db, seq); err != nil { return 0, err } return seq.CurrentSeq, nil } func (s *sequenceService) GenerateDocumentNumber(ctx context.Context, clientId string, docType string, config pkgdto.SequenceConfig) (string, error) { // Ambil nama client berdasarkan clientId var client struct { Name string } if err := s.db.Table("m_clients").Select("name").Where("id = ?", clientId).First(&client).Error; err != nil { return "", fmt.Errorf("client not found") } if client.Name == "" { return "", fmt.Errorf("client name is empty") } initials := utils.GetInitials(client.Name) // Ambil sequence dari sequence service seqNum, err := s.GetNextSequence(ctx, clientId, config) if err != nil { return "", err } docNum := fmt.Sprintf("%s-%s-%04d", docType, initials, seqNum) return docNum, nil }