add app setting letter out

This commit is contained in:
Aditya Siregar
2025-08-28 19:23:41 +07:00
parent 6da48504fa
commit 592fa97be7
18 changed files with 1077 additions and 538 deletions
@@ -0,0 +1,71 @@
package processor
import (
"context"
"fmt"
"eslogad-be/internal/entities"
"eslogad-be/internal/repository"
)
// LetterNumberGenerator handles generation of letter numbers with configurable prefix and sequence
type LetterNumberGenerator interface {
GenerateNumber(ctx context.Context, prefixKey, sequenceKey string, defaultPrefix string) (string, error)
}
type LetterNumberGeneratorImpl struct {
settingRepo *repository.AppSettingRepository
}
func NewLetterNumberGenerator(settingRepo *repository.AppSettingRepository) *LetterNumberGeneratorImpl {
return &LetterNumberGeneratorImpl{
settingRepo: settingRepo,
}
}
func (g *LetterNumberGeneratorImpl) GenerateNumber(ctx context.Context, prefixKey, sequenceKey string, defaultPrefix string) (string, error) {
prefix := defaultPrefix
if s, err := g.settingRepo.Get(ctx, prefixKey); err == nil {
if v, ok := s.Value["value"].(string); ok && v != "" {
prefix = v
}
}
seq := 0
if s, err := g.settingRepo.Get(ctx, sequenceKey); err == nil {
if v, ok := s.Value["value"].(float64); ok {
seq = int(v)
}
}
seq = seq + 1
letterNumber := fmt.Sprintf("%s%04d", prefix, seq)
if err := g.settingRepo.Upsert(ctx, sequenceKey, entities.JSONB{"value": seq}); err != nil {
}
return letterNumber, nil
}
// GetCurrentSequence returns the current sequence number for a given key
func (g *LetterNumberGeneratorImpl) GetCurrentSequence(ctx context.Context, sequenceKey string) (int, error) {
seq := 0
if s, err := g.settingRepo.Get(ctx, sequenceKey); err == nil {
if v, ok := s.Value["value"].(float64); ok {
seq = int(v)
}
}
return seq, nil
}
// GetPrefix returns the configured prefix for a given key
func (g *LetterNumberGeneratorImpl) GetPrefix(ctx context.Context, prefixKey string, defaultPrefix string) string {
prefix := defaultPrefix
if s, err := g.settingRepo.Get(ctx, prefixKey); err == nil {
if v, ok := s.Value["value"].(string); ok && v != "" {
prefix = v
}
}
return prefix
}
@@ -0,0 +1,539 @@
package processor
import (
"context"
"time"
"eslogad-be/internal/contract"
"eslogad-be/internal/entities"
"eslogad-be/internal/repository"
"github.com/google/uuid"
"gorm.io/gorm"
)
type LetterOutgoingProcessor interface {
CreateOutgoingLetter(ctx context.Context, letter *entities.LetterOutgoing, attachments []entities.LetterOutgoingAttachment, userID, departmentID uuid.UUID) error
GetOutgoingLetterByID(ctx context.Context, id uuid.UUID) (*entities.LetterOutgoing, error)
ListOutgoingLetters(ctx context.Context, filter repository.ListOutgoingLettersFilter, limit, offset int) ([]entities.LetterOutgoing, int64, error)
UpdateOutgoingLetter(ctx context.Context, letter *entities.LetterOutgoing, userID uuid.UUID) error
DeleteOutgoingLetter(ctx context.Context, id uuid.UUID, userID uuid.UUID) error
UpdateLetterStatus(ctx context.Context, letterID uuid.UUID, status entities.LetterOutgoingStatus, userID uuid.UUID, fromStatus, toStatus *string) error
ProcessApprovalSubmission(ctx context.Context, letterID uuid.UUID, approvalFlowID uuid.UUID, userID uuid.UUID) error
ProcessApproval(ctx context.Context, letterID uuid.UUID, approval *entities.LetterOutgoingApproval, userID uuid.UUID, allApproved bool) error
ProcessRejection(ctx context.Context, letterID uuid.UUID, approval *entities.LetterOutgoingApproval, userID uuid.UUID) error
AddRecipients(ctx context.Context, letterID uuid.UUID, recipients []entities.LetterOutgoingRecipient, userID uuid.UUID) error
UpdateRecipient(ctx context.Context, recipient *entities.LetterOutgoingRecipient) error
RemoveRecipient(ctx context.Context, letterID uuid.UUID, recipientID uuid.UUID, userID uuid.UUID) error
AddAttachments(ctx context.Context, letterID uuid.UUID, attachments []entities.LetterOutgoingAttachment, userID uuid.UUID) error
RemoveAttachment(ctx context.Context, letterID uuid.UUID, attachmentID uuid.UUID, userID uuid.UUID) error
CreateDiscussion(ctx context.Context, discussion *entities.LetterOutgoingDiscussion, attachments []entities.LetterOutgoingDiscussionAttachment, userID uuid.UUID) error
GetDiscussionByID(ctx context.Context, id uuid.UUID) (*entities.LetterOutgoingDiscussion, error)
UpdateDiscussion(ctx context.Context, discussion *entities.LetterOutgoingDiscussion) error
DeleteDiscussion(ctx context.Context, id uuid.UUID) error
GetApprovalsByLetter(ctx context.Context, letterID uuid.UUID) ([]entities.LetterOutgoingApproval, error)
GetApprovalFlow(ctx context.Context, flowID uuid.UUID) (*entities.ApprovalFlow, error)
}
type LetterOutgoingProcessorImpl struct {
db *gorm.DB
letterRepo *repository.LetterOutgoingRepository
attachmentRepo *repository.LetterOutgoingAttachmentRepository
recipientRepo *repository.LetterOutgoingRecipientRepository
discussionRepo *repository.LetterOutgoingDiscussionRepository
discussionAttachmentRepo *repository.LetterOutgoingDiscussionAttachmentRepository
activityLogRepo *repository.LetterOutgoingActivityLogRepository
approvalFlowRepo *repository.ApprovalFlowRepository
approvalRepo *repository.LetterOutgoingApprovalRepository
numberGenerator *LetterNumberGeneratorImpl
txManager *repository.TxManager
}
func NewLetterOutgoingProcessor(
db *gorm.DB,
letterRepo *repository.LetterOutgoingRepository,
attachmentRepo *repository.LetterOutgoingAttachmentRepository,
recipientRepo *repository.LetterOutgoingRecipientRepository,
discussionRepo *repository.LetterOutgoingDiscussionRepository,
discussionAttachmentRepo *repository.LetterOutgoingDiscussionAttachmentRepository,
activityLogRepo *repository.LetterOutgoingActivityLogRepository,
approvalFlowRepo *repository.ApprovalFlowRepository,
approvalRepo *repository.LetterOutgoingApprovalRepository,
numberGenerator *LetterNumberGeneratorImpl,
txManager *repository.TxManager,
) *LetterOutgoingProcessorImpl {
return &LetterOutgoingProcessorImpl{
db: db,
letterRepo: letterRepo,
attachmentRepo: attachmentRepo,
recipientRepo: recipientRepo,
discussionRepo: discussionRepo,
discussionAttachmentRepo: discussionAttachmentRepo,
activityLogRepo: activityLogRepo,
approvalFlowRepo: approvalFlowRepo,
approvalRepo: approvalRepo,
numberGenerator: numberGenerator,
txManager: txManager,
}
}
func (p *LetterOutgoingProcessorImpl) CreateOutgoingLetter(ctx context.Context, letter *entities.LetterOutgoing, attachments []entities.LetterOutgoingAttachment, userID, departmentID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
// Step 1: Assign approval flow from department if not provided
if err := p.assignApprovalFlowFromDepartment(txCtx, letter, departmentID); err != nil {
// Log error but continue - approval flow is optional
}
// Step 2: Set status based on approval flow
if letter.ApprovalFlowID != nil {
letter.Status = entities.LetterOutgoingStatusPendingApproval
} else {
letter.Status = entities.LetterOutgoingStatusApproved
}
// Step 3: Generate and assign letter number
if err := p.assignLetterNumber(txCtx, letter); err != nil {
return err
}
// Step 4: Create the letter
if err := p.letterRepo.Create(txCtx, letter); err != nil {
return err
}
// Step 5: Create recipients from approval flow
if err := p.createRecipientsFromApprovalFlow(txCtx, letter); err != nil {
return err
}
// Step 6: Create attachments
if err := p.createAttachments(txCtx, letter.ID, attachments); err != nil {
return err
}
// Step 7: Log the activity
return p.logActivity(txCtx, letter.ID, entities.LetterOutgoingActionCreated, userID)
})
}
func (p *LetterOutgoingProcessorImpl) assignApprovalFlowFromDepartment(ctx context.Context, letter *entities.LetterOutgoing, departmentID uuid.UUID) error {
if letter.ApprovalFlowID != nil || departmentID == uuid.Nil {
return nil
}
flow, err := p.approvalFlowRepo.GetByDepartment(ctx, departmentID)
if err != nil {
return err
}
if flow != nil {
letter.ApprovalFlowID = &flow.ID
}
return nil
}
func (p *LetterOutgoingProcessorImpl) assignLetterNumber(ctx context.Context, letter *entities.LetterOutgoing) error {
letterNumber, err := p.numberGenerator.GenerateNumber(
ctx,
contract.SettingOutgoingLetterPrefix,
contract.SettingOutgoingLetterSequence,
"ESLO",
)
if err != nil {
return err
}
letter.LetterNumber = letterNumber
return nil
}
func (p *LetterOutgoingProcessorImpl) createRecipientsFromApprovalFlow(ctx context.Context, letter *entities.LetterOutgoing) error {
if letter.ApprovalFlowID == nil {
return nil
}
flow, err := p.approvalFlowRepo.Get(ctx, *letter.ApprovalFlowID)
if err != nil || flow == nil || len(flow.Steps) == 0 {
return err
}
recipient := p.createRecipientFromApprovalStep(flow.Steps[0], letter.ID)
if recipient == nil {
return nil // No valid recipient could be created
}
return p.recipientRepo.CreateBulk(ctx, []entities.LetterOutgoingRecipient{*recipient})
}
// createRecipientFromApprovalStep creates a recipient from an approval flow step
func (p *LetterOutgoingProcessorImpl) createRecipientFromApprovalStep(step entities.ApprovalFlowStep, letterID uuid.UUID) *entities.LetterOutgoingRecipient {
recipient := &entities.LetterOutgoingRecipient{
LetterID: letterID,
IsPrimary: true,
}
if step.ApproverUser != nil {
recipient.RecipientName = step.ApproverUser.Name
recipient.RecipientEmail = &step.ApproverUser.Email
// Extract position from user profile if available
if step.ApproverUser.Profile != nil && step.ApproverUser.Profile.JobTitle != nil {
recipient.RecipientPosition = step.ApproverUser.Profile.JobTitle
}
} else if step.ApproverRole != nil {
recipient.RecipientName = step.ApproverRole.Name
position := "Role: " + step.ApproverRole.Name
recipient.RecipientPosition = &position
} else {
return nil // No valid approver found
}
return recipient
}
// createAttachments creates letter attachments
func (p *LetterOutgoingProcessorImpl) createAttachments(ctx context.Context, letterID uuid.UUID, attachments []entities.LetterOutgoingAttachment) error {
if len(attachments) == 0 {
return nil
}
// Update letter IDs for all attachments
for i := range attachments {
attachments[i].LetterID = letterID
}
return p.attachmentRepo.CreateBulk(ctx, attachments)
}
// logActivity logs an activity for the letter
func (p *LetterOutgoingProcessorImpl) logActivity(ctx context.Context, letterID uuid.UUID, actionType string, userID uuid.UUID) error {
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActionType: actionType,
ActorUserID: &userID,
}
return p.activityLogRepo.Create(ctx, activityLog)
}
func (p *LetterOutgoingProcessorImpl) GetOutgoingLetterByID(ctx context.Context, id uuid.UUID) (*entities.LetterOutgoing, error) {
return p.letterRepo.Get(ctx, id)
}
func (p *LetterOutgoingProcessorImpl) ListOutgoingLetters(ctx context.Context, filter repository.ListOutgoingLettersFilter, limit, offset int) ([]entities.LetterOutgoing, int64, error) {
return p.letterRepo.List(ctx, filter, limit, offset)
}
func (p *LetterOutgoingProcessorImpl) UpdateOutgoingLetter(ctx context.Context, letter *entities.LetterOutgoing, userID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
if err := p.letterRepo.Update(txCtx, letter); err != nil {
return err
}
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letter.ID,
ActionType: entities.LetterOutgoingActionUpdated,
ActorUserID: &userID,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) DeleteOutgoingLetter(ctx context.Context, id uuid.UUID, userID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
if err := p.letterRepo.SoftDelete(txCtx, id); err != nil {
return err
}
letter, _ := p.letterRepo.Get(txCtx, id)
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letter.ID,
ActionType: entities.LetterOutgoingActionDeleted,
ActorUserID: &userID,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) UpdateLetterStatus(ctx context.Context, letterID uuid.UUID, status entities.LetterOutgoingStatus, userID uuid.UUID, fromStatus, toStatus *string) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
if err := p.letterRepo.UpdateStatus(txCtx, letterID, status); err != nil {
return err
}
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActorUserID: &userID,
FromStatus: fromStatus,
ToStatus: toStatus,
}
switch status {
case entities.LetterOutgoingStatusPendingApproval:
activityLog.ActionType = entities.LetterOutgoingActionSubmittedApproval
case entities.LetterOutgoingStatusApproved:
activityLog.ActionType = entities.LetterOutgoingActionApproved
case entities.LetterOutgoingStatusSent:
activityLog.ActionType = entities.LetterOutgoingActionSent
case entities.LetterOutgoingStatusArchived:
activityLog.ActionType = entities.LetterOutgoingActionArchived
default:
activityLog.ActionType = entities.LetterOutgoingActionUpdated
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) ProcessApprovalSubmission(ctx context.Context, letterID uuid.UUID, approvalFlowID uuid.UUID, userID uuid.UUID) error {
flow, err := p.approvalFlowRepo.Get(ctx, approvalFlowID)
if err != nil {
return err
}
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
approvals := make([]entities.LetterOutgoingApproval, len(flow.Steps))
for i, step := range flow.Steps {
approvals[i] = entities.LetterOutgoingApproval{
LetterID: letterID,
StepID: step.ID,
Status: entities.ApprovalStatusPending,
}
}
if err := p.approvalRepo.CreateBulk(txCtx, approvals); err != nil {
return err
}
if err := p.letterRepo.UpdateStatus(txCtx, letterID, entities.LetterOutgoingStatusPendingApproval); err != nil {
return err
}
fromStatus := string(entities.LetterOutgoingStatusDraft)
toStatus := string(entities.LetterOutgoingStatusPendingApproval)
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActionType: entities.LetterOutgoingActionSubmittedApproval,
ActorUserID: &userID,
FromStatus: &fromStatus,
ToStatus: &toStatus,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) ProcessApproval(ctx context.Context, letterID uuid.UUID, approval *entities.LetterOutgoingApproval, userID uuid.UUID, allApproved bool) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
now := time.Now()
approval.Status = entities.ApprovalStatusApproved
approval.ApproverID = &userID
approval.ActedAt = &now
if err := p.approvalRepo.Update(txCtx, approval); err != nil {
return err
}
if allApproved {
if err := p.letterRepo.UpdateStatus(txCtx, letterID, entities.LetterOutgoingStatusApproved); err != nil {
return err
}
}
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActionType: entities.LetterOutgoingActionApproved,
ActorUserID: &userID,
TargetID: &approval.ID,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) ProcessRejection(ctx context.Context, letterID uuid.UUID, approval *entities.LetterOutgoingApproval, userID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
now := time.Now()
approval.Status = entities.ApprovalStatusRejected
approval.ApproverID = &userID
approval.ActedAt = &now
if err := p.approvalRepo.Update(txCtx, approval); err != nil {
return err
}
if err := p.letterRepo.UpdateStatus(txCtx, letterID, entities.LetterOutgoingStatusDraft); err != nil {
return err
}
fromStatus := string(entities.LetterOutgoingStatusPendingApproval)
toStatus := string(entities.LetterOutgoingStatusDraft)
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActionType: entities.LetterOutgoingActionRejected,
ActorUserID: &userID,
TargetID: &approval.ID,
FromStatus: &fromStatus,
ToStatus: &toStatus,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) AddRecipients(ctx context.Context, letterID uuid.UUID, recipients []entities.LetterOutgoingRecipient, userID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
if err := p.recipientRepo.CreateBulk(txCtx, recipients); err != nil {
return err
}
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActionType: entities.LetterOutgoingActionRecipientAdded,
ActorUserID: &userID,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) UpdateRecipient(ctx context.Context, recipient *entities.LetterOutgoingRecipient) error {
return p.recipientRepo.Update(ctx, recipient)
}
func (p *LetterOutgoingProcessorImpl) RemoveRecipient(ctx context.Context, letterID uuid.UUID, recipientID uuid.UUID, userID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
if err := p.recipientRepo.Delete(txCtx, recipientID); err != nil {
return err
}
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActionType: entities.LetterOutgoingActionRecipientRemoved,
ActorUserID: &userID,
TargetID: &recipientID,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) AddAttachments(ctx context.Context, letterID uuid.UUID, attachments []entities.LetterOutgoingAttachment, userID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
if err := p.attachmentRepo.CreateBulk(txCtx, attachments); err != nil {
return err
}
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActionType: entities.LetterOutgoingActionAttachmentAdded,
ActorUserID: &userID,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) RemoveAttachment(ctx context.Context, letterID uuid.UUID, attachmentID uuid.UUID, userID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
if err := p.attachmentRepo.Delete(txCtx, attachmentID); err != nil {
return err
}
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: letterID,
ActionType: entities.LetterOutgoingActionAttachmentRemoved,
ActorUserID: &userID,
TargetID: &attachmentID,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) CreateDiscussion(ctx context.Context, discussion *entities.LetterOutgoingDiscussion, attachments []entities.LetterOutgoingDiscussionAttachment, userID uuid.UUID) error {
return p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
if err := p.discussionRepo.Create(txCtx, discussion); err != nil {
return err
}
if len(attachments) > 0 {
if err := p.discussionAttachmentRepo.CreateBulk(txCtx, attachments); err != nil {
return err
}
}
activityLog := &entities.LetterOutgoingActivityLog{
LetterID: discussion.LetterID,
ActionType: entities.LetterOutgoingActionDiscussionAdded,
ActorUserID: &userID,
TargetID: &discussion.ID,
}
if err := p.activityLogRepo.Create(txCtx, activityLog); err != nil {
return err
}
return nil
})
}
func (p *LetterOutgoingProcessorImpl) GetDiscussionByID(ctx context.Context, id uuid.UUID) (*entities.LetterOutgoingDiscussion, error) {
return p.discussionRepo.Get(ctx, id)
}
func (p *LetterOutgoingProcessorImpl) UpdateDiscussion(ctx context.Context, discussion *entities.LetterOutgoingDiscussion) error {
return p.discussionRepo.Update(ctx, discussion)
}
func (p *LetterOutgoingProcessorImpl) DeleteDiscussion(ctx context.Context, id uuid.UUID) error {
return p.discussionRepo.Delete(ctx, id)
}
func (p *LetterOutgoingProcessorImpl) GetApprovalsByLetter(ctx context.Context, letterID uuid.UUID) ([]entities.LetterOutgoingApproval, error) {
return p.approvalRepo.ListByLetter(ctx, letterID)
}
func (p *LetterOutgoingProcessorImpl) GetApprovalFlow(ctx context.Context, flowID uuid.UUID) (*entities.ApprovalFlow, error) {
return p.approvalFlowRepo.Get(ctx, flowID)
}
+11 -18
View File
@@ -2,7 +2,6 @@ package processor
import (
"context"
"fmt"
"time"
"eslogad-be/internal/appcontext"
@@ -31,10 +30,11 @@ type LetterProcessorImpl struct {
priorityRepo *repository.PriorityRepository
institutionRepo *repository.InstitutionRepository
dispActionRepo *repository.DispositionActionRepository
numberGenerator *LetterNumberGeneratorImpl
}
func NewLetterProcessor(letterRepo *repository.LetterIncomingRepository, attachRepo *repository.LetterIncomingAttachmentRepository, txManager *repository.TxManager, activity *ActivityLogProcessorImpl, dispRepo *repository.LetterIncomingDispositionRepository, dispDeptRepo *repository.LetterIncomingDispositionDepartmentRepository, dispSelRepo *repository.LetterDispositionActionSelectionRepository, noteRepo *repository.DispositionNoteRepository, discussionRepo *repository.LetterDiscussionRepository, settingRepo *repository.AppSettingRepository, recipientRepo *repository.LetterIncomingRecipientRepository, departmentRepo *repository.DepartmentRepository, userDeptRepo *repository.UserDepartmentRepository, priorityRepo *repository.PriorityRepository, institutionRepo *repository.InstitutionRepository, dispActionRepo *repository.DispositionActionRepository) *LetterProcessorImpl {
return &LetterProcessorImpl{letterRepo: letterRepo, attachRepo: attachRepo, txManager: txManager, activity: activity, dispositionRepo: dispRepo, dispositionDeptRepo: dispDeptRepo, dispositionActionSelRepo: dispSelRepo, dispositionNoteRepo: noteRepo, discussionRepo: discussionRepo, settingRepo: settingRepo, recipientRepo: recipientRepo, departmentRepo: departmentRepo, userDeptRepo: userDeptRepo, priorityRepo: priorityRepo, institutionRepo: institutionRepo, dispActionRepo: dispActionRepo}
func NewLetterProcessor(letterRepo *repository.LetterIncomingRepository, attachRepo *repository.LetterIncomingAttachmentRepository, txManager *repository.TxManager, activity *ActivityLogProcessorImpl, dispRepo *repository.LetterIncomingDispositionRepository, dispDeptRepo *repository.LetterIncomingDispositionDepartmentRepository, dispSelRepo *repository.LetterDispositionActionSelectionRepository, noteRepo *repository.DispositionNoteRepository, discussionRepo *repository.LetterDiscussionRepository, settingRepo *repository.AppSettingRepository, recipientRepo *repository.LetterIncomingRecipientRepository, departmentRepo *repository.DepartmentRepository, userDeptRepo *repository.UserDepartmentRepository, priorityRepo *repository.PriorityRepository, institutionRepo *repository.InstitutionRepository, dispActionRepo *repository.DispositionActionRepository, numberGenerator *LetterNumberGeneratorImpl) *LetterProcessorImpl {
return &LetterProcessorImpl{letterRepo: letterRepo, attachRepo: attachRepo, txManager: txManager, activity: activity, dispositionRepo: dispRepo, dispositionDeptRepo: dispDeptRepo, dispositionActionSelRepo: dispSelRepo, dispositionNoteRepo: noteRepo, discussionRepo: discussionRepo, settingRepo: settingRepo, recipientRepo: recipientRepo, departmentRepo: departmentRepo, userDeptRepo: userDeptRepo, priorityRepo: priorityRepo, institutionRepo: institutionRepo, dispActionRepo: dispActionRepo, numberGenerator: numberGenerator}
}
func (p *LetterProcessorImpl) CreateIncomingLetter(ctx context.Context, req *contract.CreateIncomingLetterRequest) (*contract.IncomingLetterResponse, error) {
@@ -42,20 +42,15 @@ func (p *LetterProcessorImpl) CreateIncomingLetter(ctx context.Context, req *con
err := p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
userID := appcontext.FromGinContext(txCtx).UserID
prefix := "ESLI"
seq := 0
if s, err := p.settingRepo.Get(txCtx, contract.SettingIncomingLetterPrefix); err == nil {
if v, ok := s.Value["value"].(string); ok && v != "" {
prefix = v
}
letterNumber, err := p.numberGenerator.GenerateNumber(
txCtx,
contract.SettingIncomingLetterPrefix,
contract.SettingIncomingLetterSequence,
"ESLI",
)
if err != nil {
return err
}
if s, err := p.settingRepo.Get(txCtx, contract.SettingIncomingLetterSequence); err == nil {
if v, ok := s.Value["value"].(float64); ok {
seq = int(v)
}
}
seq = seq + 1
letterNumber := fmt.Sprintf("%s%04d", prefix, seq)
entity := &entities.LetterIncoming{
ReferenceNumber: req.ReferenceNumber,
@@ -73,8 +68,6 @@ func (p *LetterProcessorImpl) CreateIncomingLetter(ctx context.Context, req *con
return err
}
_ = p.settingRepo.Upsert(txCtx, contract.SettingIncomingLetterSequence, entities.JSONB{"value": seq})
defaultDeptCodes := []string{}
if s, err := p.settingRepo.Get(txCtx, contract.SettingIncomingLetterRecipients); err == nil {
if arr, ok := s.Value["department_codes"].([]interface{}); ok {
@@ -4,7 +4,6 @@ import (
"context"
"testing"
"eslogad-be/internal/contract"
"eslogad-be/internal/entities"
"github.com/google/uuid"