add dukcapil

This commit is contained in:
Aditya Siregar
2026-05-07 04:01:32 +07:00
parent 9a975d146e
commit bc64eb20ea
235 changed files with 1197 additions and 28187 deletions
-186
View File
@@ -1,186 +0,0 @@
package contract
import (
"time"
"github.com/google/uuid"
)
// AnalyticsDashboardRequest represents the request for analytics data
type AnalyticsDashboardRequest struct {
StartDate string `form:"start_date" json:"start_date"`
EndDate string `form:"end_date" json:"end_date"`
DepartmentID *uuid.UUID `form:"department_id" json:"department_id,omitempty"`
UserID *uuid.UUID `form:"user_id" json:"user_id,omitempty"`
}
// AnalyticsDashboardResponse represents the complete analytics dashboard
type AnalyticsDashboardResponse struct {
Summary LetterSummaryStats `json:"summary"`
PriorityDistribution []PriorityDistribution `json:"priority_distribution"`
DepartmentStats []DepartmentStats `json:"department_stats"`
MonthlyTrend []MonthlyTrend `json:"monthly_trend"`
DepartmentsStats []SimpleDepartmentStats `json:"departments_stats,omitempty"`
InstitutionStats []InstitutionStats `json:"institution_stats"`
DailyActivity []DailyActivity `json:"daily_activity"`
StatusDistribution []StatusDistribution `json:"status_distribution,omitempty"`
TopSenders []TopUserStats `json:"top_senders,omitempty"`
TopRecipients []TopUserStats `json:"top_recipients,omitempty"`
ApprovalMetrics *ApprovalMetrics `json:"approval_metrics,omitempty"`
ResponseTimeStats *ResponseTimeStats `json:"response_time_stats,omitempty"`
}
// LetterSummaryStats represents overall summary statistics
type LetterSummaryStats struct {
TotalIncoming int64 `json:"total_incoming"`
TotalOutgoing int64 `json:"total_outgoing"`
WeekOverWeekGrowth float64 `json:"week_over_week_growth"`
MonthOverMonthGrowth float64 `json:"month_over_month_growth"`
TotalThisWeek float64 `json:"total_this_week"`
TotalPending int64 `json:"total_pending,omitempty"`
TotalApproved int64 `json:"total_approved,omitempty"`
TotalRejected int64 `json:"total_rejected,omitempty"`
TotalArchived int64 `json:"total_archived,omitempty"`
AvgProcessingTime float64 `json:"avg_processing_time_hours,omitempty"`
CompletionRate float64 `json:"completion_rate,omitempty"`
}
// StatusDistribution represents letter distribution by status
type StatusDistribution struct {
Status string `json:"status"`
Count int64 `json:"count"`
Percentage float64 `json:"percentage"`
Type string `json:"type"` // incoming or outgoing
}
// PriorityDistribution represents letter distribution by priority
type PriorityDistribution struct {
PriorityID string `json:"priority_id"`
PriorityName string `json:"priority_name"`
Level int `json:"level"`
Count int64 `json:"count"`
Percentage float64 `json:"percentage"`
AvgResponseTime float64 `json:"avg_response_time_hours"`
}
// DepartmentStats represents statistics per department
type DepartmentStats struct {
DepartmentID uuid.UUID `json:"department_id"`
DepartmentName string `json:"department_name"`
DepartmentCode string `json:"department_code"`
IncomingCount int64 `json:"incoming_count"`
OutgoingCount int64 `json:"outgoing_count"`
PendingCount int64 `json:"pending_count"`
AvgResponseTime float64 `json:"avg_response_time_hours"`
CompletionRate float64 `json:"completion_rate"`
}
// MonthlyTrend represents monthly trend data
type MonthlyTrend struct {
Month string `json:"month"`
Year int `json:"year"`
IncomingCount int64 `json:"incoming_count"`
OutgoingCount int64 `json:"outgoing_count"`
TotalCount int64 `json:"total_count"`
GrowthRate float64 `json:"growth_rate"`
}
// TopUserStats represents top users by letter activity
type TopUserStats struct {
UserID uuid.UUID `json:"user_id"`
UserName string `json:"user_name"`
UserEmail string `json:"user_email"`
Department string `json:"department"`
LetterCount int64 `json:"letter_count"`
AvgResponseTime float64 `json:"avg_response_time_hours"`
}
// InstitutionStats represents statistics per institution
type InstitutionStats struct {
InstitutionID uuid.UUID `json:"institution_id"`
InstitutionName string `json:"institution_name"`
InstitutionType string `json:"institution_type"`
IncomingCount int64 `json:"incoming_count"`
OutgoingCount int64 `json:"outgoing_count"`
TotalCount int64 `json:"total_count"`
LastActivity time.Time `json:"last_activity"`
}
// ApprovalMetrics represents approval-related metrics
type ApprovalMetrics struct {
TotalSubmitted int64 `json:"total_submitted"`
TotalApproved int64 `json:"total_approved"`
TotalRejected int64 `json:"total_rejected"`
TotalPending int64 `json:"total_pending"`
ApprovalRate float64 `json:"approval_rate"`
RejectionRate float64 `json:"rejection_rate"`
AvgApprovalTime float64 `json:"avg_approval_time_hours"`
AvgApprovalSteps float64 `json:"avg_approval_steps"`
BottleneckSteps []BottleneckStep `json:"bottleneck_steps"`
}
// BottleneckStep represents approval steps that cause delays
type BottleneckStep struct {
StepOrder int `json:"step_order"`
ApproverName string `json:"approver_name"`
AvgProcessTime float64 `json:"avg_process_time_hours"`
PendingCount int64 `json:"pending_count"`
}
// ResponseTimeStats represents response time statistics
type ResponseTimeStats struct {
MinResponseTime float64 `json:"min_response_time_hours"`
MaxResponseTime float64 `json:"max_response_time_hours"`
AvgResponseTime float64 `json:"avg_response_time_hours"`
MedianResponseTime float64 `json:"median_response_time_hours"`
P95ResponseTime float64 `json:"p95_response_time_hours"`
P99ResponseTime float64 `json:"p99_response_time_hours"`
}
// SimpleDepartmentStats represents simplified department statistics
type SimpleDepartmentStats struct {
DepartmentID uuid.UUID `json:"department_id"`
Department string `json:"department"`
LetterCount int64 `json:"letter_count"`
}
// DailyActivity represents daily activity data
type DailyActivity struct {
Date string `json:"date"`
DayOfWeek string `json:"day_of_week"`
IncomingCount int64 `json:"incoming_count"`
OutgoingCount int64 `json:"outgoing_count"`
ApprovedCount int64 `json:"approved_count,omitempty"`
RejectedCount int64 `json:"rejected_count,omitempty"`
HourlyDistribution []HourlyActivity `json:"hourly_distribution,omitempty"`
}
// HourlyActivity represents hourly activity within a day
type HourlyActivity struct {
Hour int `json:"hour"`
Count int64 `json:"count"`
}
// LetterVolumeByTypeResponse represents letter volume grouped by type
type LetterVolumeByTypeResponse struct {
Incoming IncomingLetterVolume `json:"incoming"`
Outgoing OutgoingLetterVolume `json:"outgoing"`
}
// IncomingLetterVolume represents incoming letter statistics
type IncomingLetterVolume struct {
Today int64 `json:"today"`
ThisWeek int64 `json:"this_week"`
ThisMonth int64 `json:"this_month"`
ThisYear int64 `json:"this_year"`
Total int64 `json:"total"`
}
// OutgoingLetterVolume represents outgoing letter statistics
type OutgoingLetterVolume struct {
Today int64 `json:"today"`
ThisWeek int64 `json:"this_week"`
ThisMonth int64 `json:"this_month"`
ThisYear int64 `json:"this_year"`
Total int64 `json:"total"`
}
@@ -1,73 +0,0 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type DepartmentInfo struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code string `json:"code,omitempty"`
}
type DispositionRouteResponse struct {
ID uuid.UUID `json:"id"`
FromDepartmentID uuid.UUID `json:"from_department_id"`
ToDepartmentID uuid.UUID `json:"to_department_id"`
IsActive bool `json:"is_active"`
AllowedActions map[string]interface{} `json:"allowed_actions,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Department information
FromDepartment DepartmentInfo `json:"from_department"`
ToDepartment DepartmentInfo `json:"to_department"`
}
type CreateDispositionRouteRequest struct {
FromDepartmentID uuid.UUID `json:"from_department_id" binding:"required"`
ToDepartmentIDs []uuid.UUID `json:"to_department_ids" binding:"required,min=1"`
IsActive *bool `json:"is_active,omitempty"`
AllowedActions *map[string]interface{} `json:"allowed_actions,omitempty"`
}
// BulkCreateDispositionRouteResponse response for bulk create/update operation
type BulkCreateDispositionRouteResponse struct {
Created int `json:"created"`
Updated int `json:"updated"`
Routes []DispositionRouteResponse `json:"routes"`
}
type UpdateDispositionRouteRequest struct {
IsActive *bool `json:"is_active,omitempty"`
AllowedActions *map[string]interface{} `json:"allowed_actions,omitempty"`
}
type ListDispositionRoutesResponse struct {
Routes []DispositionRouteResponse `json:"routes"`
}
// DepartmentMapping represents department ID and name mapping
type DepartmentMapping struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
}
// DispositionRouteGroupedItem represents a single grouped route item with clean department structure
type DispositionRouteGroupedItem struct {
FromDepartment DepartmentMapping `json:"from_department"`
ToDepartments []DepartmentMapping `json:"to_departments"`
}
// ListDispositionRoutesGroupedResponse returns all routes grouped by from_department_id
type ListDispositionRoutesGroupedResponse struct {
Dispositions []DispositionRouteGroupedItem `json:"dispositions"`
}
// ListDispositionRoutesDetailedResponse returns all routes with department details
type ListDispositionRoutesDetailedResponse struct {
Routes []DispositionRouteResponse `json:"routes"`
Total int `json:"total"`
}
+66
View File
@@ -0,0 +1,66 @@
package contract
// FaceMatchRequest is the inbound payload from clients of this service to
// trigger a Dukcapil 1:N face recognition lookup.
//
// Image must already be a base64 (no data:image prefix) representation of a
// jpg/png file. Threshold is forwarded to Dukcapil (1..20). IP is optional;
// when empty the configured default IP will be used.
type FaceMatchRequest struct {
TransactionID string `json:"transaction_id" validate:"required,max=20"`
TransactionSource string `json:"transaction_source" validate:"required,max=50"`
Threshold string `json:"threshold" validate:"required"`
Image string `json:"image" validate:"required"`
IP string `json:"ip,omitempty"`
}
// DukcapilFaceRequest is the exact JSON body sent to the Dukcapil
// face-recognition endpoint (CALL_FN). user_id and password are RSA encrypted
// with the provided public key and base64 encoded.
type DukcapilFaceRequest struct {
TransactionID string `json:"transactionId"`
TransactionSource string `json:"transactionSource"`
Threshold string `json:"threshold"`
Image string `json:"image"`
UserID string `json:"user_id"`
Password string `json:"password"`
IP string `json:"ip"`
}
// DukcapilFaceResponse is the standard Dukcapil response envelope (success +
// most error variants share this shape). Some error variants use a different
// shape clients should also inspect ErrorCode.
type DukcapilFaceResponse struct {
TID string `json:"tid"`
EncounterID interface{} `json:"encounter_id"`
Error string `json:"error"`
ErrorCode string `json:"errorCode"`
FingerData interface{} `json:"finger_data"`
IrisData interface{} `json:"iris_data"`
FaceData interface{} `json:"face_data"`
RequestType string `json:"request_type"`
MaxResults int `json:"maxResults"`
FaceThreshold string `json:"faceThreshold"`
FingerThreshold int `json:"fingerThreshold"`
IrisThreshold int `json:"irisThreshold"`
Response string `json:"response"`
}
// FaceMatchResponse is what we return to our API consumers.
type FaceMatchResponse struct {
TID string `json:"tid"`
ErrorCode string `json:"error_code"`
Error string `json:"error"`
RequestType string `json:"request_type"`
Threshold string `json:"threshold"`
MaxResults int `json:"max_results"`
Matches []FaceMatchResult `json:"matches"`
Raw *DukcapilFaceResponse `json:"raw,omitempty"`
}
// FaceMatchResult represents a single (NIK -> score) entry from the Dukcapil
// `response.face.FACE_T5` map.
type FaceMatchResult struct {
NIK string `json:"nik"`
Score float64 `json:"score"`
}
-291
View File
@@ -1,291 +0,0 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type SearchIncomingLettersRequest struct {
Query string `json:"query" form:"query"`
LetterNumber string `json:"letter_number" form:"letter_number"`
Subject string `json:"subject" form:"subject"`
Status string `json:"status" form:"status"`
PriorityID *uuid.UUID `json:"priority_id" form:"priority_id"`
InstitutionID *uuid.UUID `json:"institution_id" form:"institution_id"`
CreatedBy *uuid.UUID `json:"created_by" form:"created_by"`
DateFrom *time.Time `json:"date_from" form:"date_from"`
DateTo *time.Time `json:"date_to" form:"date_to"`
Page int `json:"page" form:"page"`
Limit int `json:"limit" form:"limit"`
SortBy string `json:"sort_by" form:"sort_by"`
SortOrder string `json:"sort_order" form:"sort_order"`
}
type SearchIncomingLettersResponse struct {
Letters []IncomingLetterResponse `json:"letters"`
TotalCount int64 `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
}
type CreateIncomingLetterAttachment struct {
FileURL string `json:"file_url"`
FileName string `json:"file_name"`
FileType string `json:"file_type"`
}
type CreateIncomingLetterRequest struct {
LetterNumber string `json:"-"` // Generated by service layer
ReferenceNumber *string `json:"reference_number,omitempty"`
Subject string `json:"subject"`
Description *string `json:"description,omitempty"`
PriorityID *uuid.UUID `json:"priority_id,omitempty"`
SenderInstitutionID *uuid.UUID `json:"sender_institution_id,omitempty"`
SenderName *string `json:"sender_name,omitempty"`
Addressee *string `json:"addressee,omitempty"`
ReceivedDate time.Time `json:"received_date"`
DueDate *time.Time `json:"due_date,omitempty"`
Type string `json:"type"` // UTAMA or TEMBUSAN
Attachments []CreateIncomingLetterAttachment `json:"attachments,omitempty"`
}
type IncomingLetterAttachmentResponse struct {
ID uuid.UUID `json:"id"`
FileURL string `json:"file_url"`
FileName string `json:"file_name"`
FileType string `json:"file_type"`
UploadedAt time.Time `json:"uploaded_at"`
}
type IncomingLetterResponse struct {
ID uuid.UUID `json:"id"`
LetterNumber string `json:"letter_number"`
ReferenceNumber *string `json:"reference_number,omitempty"`
Subject string `json:"subject"`
Description *string `json:"description,omitempty"`
Priority *PriorityResponse `json:"priority,omitempty"`
SenderInstitution *InstitutionResponse `json:"sender_institution,omitempty"`
SenderName *string `json:"sender_name,omitempty"`
Addressee *string `json:"addressee,omitempty"`
ReceivedDate time.Time `json:"received_date"`
DueDate *time.Time `json:"due_date,omitempty"`
Type string `json:"type"`
Status string `json:"status"`
CreatedBy uuid.UUID `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Attachments []IncomingLetterAttachmentResponse `json:"attachments"`
IsRead bool `json:"is_read"`
Dispositions []EnhancedDispositionResponse `json:"dispositions"`
}
type UpdateIncomingLetterRequest struct {
ReferenceNumber *string `json:"reference_number,omitempty"`
Subject *string `json:"subject,omitempty"`
Description *string `json:"description,omitempty"`
PriorityID *uuid.UUID `json:"priority_id,omitempty"`
SenderInstitutionID *uuid.UUID `json:"sender_institution_id,omitempty"`
SenderName *string `json:"sender_name,omitempty"`
Addressee *string `json:"addressee,omitempty"`
ReceivedDate *time.Time `json:"received_date,omitempty"`
DueDate *time.Time `json:"due_date,omitempty"`
Type *string `json:"type,omitempty"`
Status *string `json:"status,omitempty"`
}
type ListIncomingLettersRequest struct {
Page int `json:"page"`
Limit int `json:"limit"`
Status *string `json:"status,omitempty"`
Query *string `json:"query,omitempty"`
DepartmentID *uuid.UUID
IsRead *bool `json:"is_read,omitempty"`
PriorityIDs []uuid.UUID `json:"priority_ids,omitempty"`
IsDispositioned *bool `json:"is_dispositioned,omitempty"`
IsArchived *bool `json:"is_archived,omitempty"`
}
type ListIncomingLettersResponse struct {
Letters []IncomingLetterResponse `json:"letters"`
Pagination PaginationResponse `json:"pagination"`
TotalUnread int `json:"total_unread"`
}
type LetterUnreadCountResponse struct {
IncomingLetter struct {
Unread int `json:"unread"`
} `json:"incoming_letter"`
OutgoingLetter struct {
Unread int `json:"unread"`
} `json:"outgoing_letter"`
}
type MarkLetterReadResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
}
type CreateDispositionActionSelection struct {
ActionID uuid.UUID `json:"action_id"`
Note *string `json:"note,omitempty"`
}
type CreateLetterDispositionRequest struct {
FromDepartment uuid.UUID `json:"from_department"`
LetterID uuid.UUID `json:"letter_id"`
ToDepartmentIDs []uuid.UUID `json:"to_department_ids"`
Notes *string `json:"notes,omitempty"`
SelectedActions []CreateDispositionActionSelection `json:"selected_actions,omitempty"`
CreatedBy uuid.UUID `json:"created_by"`
}
type DispositionResponse struct {
ID uuid.UUID `json:"id"`
LetterID uuid.UUID `json:"letter_id"`
DepartmentID *uuid.UUID `json:"department_id,omitempty"`
Notes *string `json:"notes,omitempty"`
ReadAt *time.Time `json:"read_at,omitempty"`
CreatedBy uuid.UUID `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListDispositionsResponse struct {
Dispositions []DispositionResponse `json:"dispositions"`
}
type EnhancedDispositionResponse struct {
ID uuid.UUID `json:"id"`
LetterID uuid.UUID `json:"letter_id"`
DepartmentID *uuid.UUID `json:"department_id,omitempty"`
Notes *string `json:"notes,omitempty"`
ReadAt *time.Time `json:"read_at,omitempty"`
CreatedBy uuid.UUID `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Department DepartmentResponse `json:"department"`
Departments []DispositionDepartmentResponse `json:"departments"`
Actions []DispositionActionSelectionResponse `json:"actions"`
DispositionNotes []DispositionNoteResponse `json:"disposition_notes"`
}
type DispositionDepartmentResponse struct {
ID uuid.UUID `json:"id"`
DepartmentID uuid.UUID `json:"department_id"`
CreatedAt time.Time `json:"created_at"`
Department *DepartmentResponse `json:"department,omitempty"`
}
type DispositionActionSelectionResponse struct {
ID uuid.UUID `json:"id"`
ActionID uuid.UUID `json:"action_id"`
Action *DispositionActionResponse `json:"action,omitempty"`
Note *string `json:"note,omitempty"`
CreatedBy uuid.UUID `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
}
type DispositionNoteResponse struct {
ID uuid.UUID `json:"id"`
UserID *uuid.UUID `json:"user_id,omitempty"`
Note string `json:"note"`
CreatedAt time.Time `json:"created_at"`
User *UserResponse `json:"user,omitempty"`
}
type ListEnhancedDispositionsResponse struct {
Dispositions []EnhancedDispositionResponse `json:"dispositions"`
Discussions []LetterDiscussionResponse `json:"discussions"`
}
type GetDepartmentDispositionStatusRequest struct {
LetterIncomingID uuid.UUID `json:"letter_incoming_id"`
DepartmentID uuid.UUID `json:"department_id"`
}
type DepartmentDispositionStatusResponse struct {
ID uuid.UUID `json:"id"`
LetterID uuid.UUID `json:"letter_id"`
Letter *IncomingLetterResponse `json:"letter,omitempty"`
FromDepartmentID *uuid.UUID `json:"from_department_id,omitempty"`
FromDepartment *DepartmentResponse `json:"from_department,omitempty"`
ToDepartmentID uuid.UUID `json:"to_department_id"`
ToDepartment *DepartmentResponse `json:"to_department,omitempty"`
Status string `json:"status"`
Notes *string `json:"notes,omitempty"`
ReadAt *time.Time `json:"read_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListDepartmentDispositionStatusResponse struct {
Dispositions []DepartmentDispositionStatusResponse `json:"dispositions"`
Pagination PaginationResponse `json:"pagination"`
}
type UpdateDispositionStatusRequest struct {
LetterIncomingID uuid.UUID `json:"letter_incoming_id"`
Status string `json:"status"`
Notes *string `json:"notes,omitempty"`
}
type CreateLetterDiscussionRequest struct {
ParentID *uuid.UUID `json:"parent_id,omitempty"`
Message string `json:"message"`
Mentions map[string]interface{} `json:"mentions,omitempty"`
}
type UpdateLetterDiscussionRequest struct {
Message string `json:"message"`
Mentions map[string]interface{} `json:"mentions,omitempty"`
}
type LetterDiscussionResponse struct {
ID uuid.UUID `json:"id"`
LetterID uuid.UUID `json:"letter_id"`
ParentID *uuid.UUID `json:"parent_id,omitempty"`
UserID uuid.UUID `json:"user_id"`
Message string `json:"message"`
Mentions map[string]interface{} `json:"mentions,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
EditedAt *time.Time `json:"edited_at,omitempty"`
// Preloaded user profile who created the discussion
User *UserResponse `json:"user,omitempty"`
// Preloaded user profiles for mentions
MentionedUsers []UserResponse `json:"mentioned_users,omitempty"`
}
type GetLetterCTARequest struct {
LetterIncomingID uuid.UUID `json:"letter_incoming_id"`
}
type LetterCTAAction struct {
Type string `json:"type"` // "create_disposition", "update_status", "view"
Label string `json:"label"` // Human-readable label for the action
Path string `json:"path"` // API endpoint path
Method string `json:"method"` // HTTP method: GET, POST, PUT, etc.
Description string `json:"description"` // Description of what this action does
}
type LetterCTAResponse struct {
LetterIncomingID uuid.UUID `json:"letter_incoming_id"`
Actions []LetterCTAAction `json:"actions"`
DispositionID *uuid.UUID `json:"disposition_id,omitempty"`
CurrentStatus *string `json:"current_status,omitempty"`
Message string `json:"message"`
}
type BulkArchiveLettersRequest struct {
LetterIDs []uuid.UUID `json:"letter_ids" binding:"required,min=1"`
}
type BulkArchiveLettersResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
ArchivedCount int `json:"archived_count"`
}
@@ -1,385 +0,0 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type SearchOutgoingLettersRequest struct {
Query string `json:"query" form:"query"`
LetterNumber string `json:"letter_number" form:"letter_number"`
Subject string `json:"subject" form:"subject"`
Status string `json:"status" form:"status"`
PriorityID *uuid.UUID `json:"priority_id" form:"priority_id"`
InstitutionID *uuid.UUID `json:"institution_id" form:"institution_id"`
CreatedBy *uuid.UUID `json:"created_by" form:"created_by"`
DateFrom *time.Time `json:"date_from" form:"date_from"`
DateTo *time.Time `json:"date_to" form:"date_to"`
Page int `json:"page" form:"page"`
Limit int `json:"limit" form:"limit"`
SortBy string `json:"sort_by" form:"sort_by"`
SortOrder string `json:"sort_order" form:"sort_order"`
}
type SearchOutgoingLettersResponse struct {
Letters []OutgoingLetterResponse `json:"letters"`
TotalCount int64 `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
}
type CreateOutgoingLetterRecipient struct {
LetterID uuid.UUID `json:"letter_id"`
UserID *uuid.UUID `json:"user_id,omitempty"`
DepartmentID *uuid.UUID `json:"department_id,omitempty"`
IsPrimary bool `json:"is_primary"`
Status string `json:"status"`
Flag *string `json:"flag,omitempty"`
IsArchived bool `json:"is_archived"`
}
type CreateOutgoingLetterAttachment struct {
FileURL string `json:"file_url" validate:"required"`
FileName string `json:"file_name" validate:"required"`
FileType string `json:"file_type" validate:"required"`
}
type CreateOutgoingLetterRequest struct {
ReferenceNumber *string `json:"reference_number,omitempty"`
Subject string `json:"subject" validate:"required"`
Description *string `json:"description,omitempty"`
PriorityID *uuid.UUID `json:"priority_id,omitempty"`
ReceiverInstitutionID *uuid.UUID `json:"receiver_institution_id,omitempty"`
ReceiverName *string `json:"receiver_name,omitempty"`
IssueDate time.Time `json:"issue_date" validate:"required"`
Attachments []CreateOutgoingLetterAttachment `json:"attachments,omitempty"`
UserID uuid.UUID
ApprovalFlowID *uuid.UUID `json:"approval_flow_id,omitempty"`
}
type OutgoingLetterRecipientResponse struct {
ID uuid.UUID `json:"id"`
LetterID uuid.UUID `json:"letter_id"`
UserID *uuid.UUID `json:"user_id,omitempty"`
DepartmentID *uuid.UUID `json:"department_id,omitempty"`
IsPrimary bool `json:"is_primary"`
Status string `json:"status"`
ReadAt *time.Time `json:"read_at,omitempty"`
Flag *string `json:"flag,omitempty"`
IsArchived bool `json:"is_archived"`
CreatedAt time.Time `json:"created_at"`
User *UserResponse `json:"user,omitempty"`
Department *DepartmentResponse `json:"department,omitempty"`
}
type OutgoingLetterAttachmentResponse struct {
ID uuid.UUID `json:"id"`
FileURL string `json:"file_url"`
FileName string `json:"file_name"`
FileType string `json:"file_type"`
UploadedAt time.Time `json:"uploaded_at"`
}
type OutgoingLetterApprovalResponse struct {
ID uuid.UUID `json:"id"`
StepOrder int `json:"step_order"`
ParallelGroup int `json:"parallel_group"`
IsRequired bool `json:"is_required"`
ApproverID *uuid.UUID `json:"approver_id,omitempty"`
Status string `json:"status"`
Remarks *string `json:"remarks,omitempty"`
ActedAt *time.Time `json:"acted_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
type OutgoingLetterResponse struct {
ID uuid.UUID `json:"id"`
LetterNumber string `json:"letter_number"`
ReferenceNumber *string `json:"reference_number,omitempty"`
Subject string `json:"subject"`
Description *string `json:"description,omitempty"`
PriorityID *uuid.UUID `json:"priority_id,omitempty"`
Priority *PriorityResponse `json:"priority,omitempty"`
ReceiverInstitutionID *uuid.UUID `json:"receiver_institution_id,omitempty"`
ReceiverInstitution *InstitutionResponse `json:"receiver_institution,omitempty"`
ReceiverName *string `json:"receiver_name,omitempty"`
IssueDate time.Time `json:"issue_date"`
Status string `json:"status"`
ApprovalFlowID *uuid.UUID `json:"approval_flow_id,omitempty"`
RevisionNumber int `json:"revision_number"`
CreatedBy uuid.UUID `json:"created_by"`
CreatedName string `json:"created_name"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
IsRead bool `json:"is_read"`
Recipients []OutgoingLetterRecipientResponse `json:"recipients,omitempty"`
Attachments []OutgoingLetterAttachmentResponse `json:"attachments,omitempty"`
FinalAttachments []OutgoingLetterAttachmentResponse `json:"final_attachments,omitempty"`
Approvals []OutgoingLetterApprovalResponse `json:"approvals,omitempty"`
}
type UpdateOutgoingLetterRequest struct {
ReferenceNumber *string `json:"reference_number,omitempty"`
Subject *string `json:"subject,omitempty"`
Description *string `json:"description,omitempty"`
PriorityID *uuid.UUID `json:"priority_id,omitempty"`
ReceiverInstitutionID *uuid.UUID `json:"receiver_institution_id,omitempty"`
ReceiverName *string `json:"receiver_name,omitempty"`
IssueDate *time.Time `json:"issue_date,omitempty"`
}
type ListOutgoingLettersRequest struct {
Page int `form:"page" json:"page"`
Limit int `form:"limit" json:"limit"`
Status string `form:"status" json:"status,omitempty"`
Query string `form:"q" json:"query,omitempty"`
CreatedBy *uuid.UUID `form:"created_by" json:"created_by,omitempty"`
DepartmentID *uuid.UUID `form:"department_id" json:"department_id,omitempty"`
ReceiverInstitutionID *uuid.UUID `form:"receiver_institution_id" json:"receiver_institution_id,omitempty"`
FromDate string `form:"from_date" json:"from_date,omitempty"`
ToDate string `form:"to_date" json:"to_date,omitempty"`
PriorityID *uuid.UUID `form:"priority_id" json:"priority_id,omitempty"`
PriorityIDs []uuid.UUID `json:"priority_ids,omitempty"`
SortBy string `form:"sort_by" json:"sort_by,omitempty"`
SortOrder string `form:"sort_order" json:"sort_order,omitempty"`
IsArchived *bool `form:"is_archived" json:"is_archived,omitempty"`
IsRead *bool `form:"is_read,omitempty"`
}
type ListOutgoingLettersResponse struct {
Items []*OutgoingLetterResponse `json:"items"`
Total int64 `json:"total"`
}
type ApproveLetterRequest struct {
Remarks *string `json:"remarks,omitempty"`
}
type RejectLetterRequest struct {
Reason string `json:"reason" validate:"required"`
}
type ReviseLetterRequest struct {
FileURL string `json:"file_url" validate:"required"`
FileName string `json:"file_name" validate:"required"`
FileType string `json:"file_type" validate:"required"`
}
type AddRecipientsRequest struct {
Recipients []CreateOutgoingLetterRecipient `json:"recipients" validate:"required,dive"`
}
type UpdateRecipientRequest struct {
UserID *uuid.UUID `json:"user_id,omitempty"`
DepartmentID *uuid.UUID `json:"department_id,omitempty"`
IsPrimary bool `json:"is_primary"`
Status *string `json:"status,omitempty"`
Flag *string `json:"flag,omitempty"`
IsArchived *bool `json:"is_archived,omitempty"`
}
type AddAttachmentsRequest struct {
Attachments []CreateOutgoingLetterAttachment `json:"attachments" validate:"required,dive"`
}
type CreateDiscussionAttachment struct {
FileURL string `json:"file_url" validate:"required"`
FileName string `json:"file_name" validate:"required"`
FileType string `json:"file_type" validate:"required"`
}
type CreateDiscussionRequest struct {
ParentID *uuid.UUID `json:"parent_id,omitempty"`
Message string `json:"message" validate:"required"`
Mentions map[string]interface{} `json:"mentions,omitempty"`
Attachments []CreateDiscussionAttachment `json:"attachments,omitempty"`
}
type UpdateDiscussionRequest struct {
Message string `json:"message" validate:"required"`
Mentions map[string]interface{} `json:"mentions,omitempty"`
}
type DiscussionResponse struct {
ID uuid.UUID `json:"id"`
ParentID *uuid.UUID `json:"parent_id,omitempty"`
UserID uuid.UUID `json:"user_id"`
Message string `json:"message"`
Mentions map[string]interface{} `json:"mentions,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
EditedAt *time.Time `json:"edited_at,omitempty"`
}
type ApprovalFlowRequest struct {
DepartmentID uuid.UUID `json:"department_id" validate:"required"`
Name string `json:"name" validate:"required"`
Description *string `json:"description,omitempty"`
IsActive bool `json:"is_active"`
Steps []ApprovalFlowStepRequest `json:"steps" validate:"required,dive"`
}
type ApprovalFlowStepRequest struct {
StepOrder int `json:"step_order" validate:"required,min=1"`
ParallelGroup int `json:"parallel_group" validate:"min=1"`
ApproverRoleID *uuid.UUID `json:"approver_role_id,omitempty"`
ApproverUserID *uuid.UUID `json:"approver_user_id,omitempty"`
Required bool `json:"required"`
}
type ApprovalFlowResponse struct {
ID uuid.UUID `json:"id"`
DepartmentID uuid.UUID `json:"department_id"`
Department *DepartmentResponse `json:"department,omitempty"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
IsActive bool `json:"is_active"`
Steps []ApprovalFlowStepResponse `json:"steps,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ApprovalFlowStepResponse struct {
ID uuid.UUID `json:"id"`
StepOrder int `json:"step_order"`
ParallelGroup int `json:"parallel_group"`
ApproverRoleID *uuid.UUID `json:"approver_role_id,omitempty"`
ApproverRole *RoleResponse `json:"approver_role,omitempty"`
ApproverUserID *uuid.UUID `json:"approver_user_id,omitempty"`
ApproverUser *UserResponse `json:"approver_user,omitempty"`
Required bool `json:"required"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListApprovalFlowsRequest struct {
Limit int `json:"limit"`
Page int `json:"page"`
Search *string `json:"search"`
DepartmentID *uuid.UUID `json:"department_id,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
}
type ListApprovalFlowsResponse struct {
Items []*ApprovalFlowResponse `json:"items"`
Total int64 `json:"total"`
}
// Letter Approval Information for Approver
type LetterApprovalInfoResponse struct {
IsApproverOnActiveStep bool `json:"is_approver_on_active_step"`
DecisionStatus string `json:"decision_status"`
CanApprove bool `json:"can_approve"`
Actions []ApprovalAction `json:"actions"`
NotesVisibility string `json:"notes_visibility"`
}
type ApprovalAction struct {
Type string `json:"type"`
Href string `json:"href"`
Method string `json:"method"`
}
// OutgoingLetterApprovalDiscussionsResponse combines approvals and discussions for outgoing letters
type OutgoingLetterApprovalDiscussionsResponse struct {
Approvals []EnhancedOutgoingLetterApprovalResponse `json:"approvals"`
Discussions []OutgoingLetterDiscussionResponse `json:"discussions"`
}
// EnhancedOutgoingLetterApprovalResponse includes approval details with related data
type EnhancedOutgoingLetterApprovalResponse struct {
ID uuid.UUID `json:"id"`
LetterID uuid.UUID `json:"letter_id"`
StepID uuid.UUID `json:"step_id"`
StepOrder int `json:"step_order"`
ParallelGroup int `json:"parallel_group"`
IsRequired bool `json:"is_required"`
ApproverID *uuid.UUID `json:"approver_id,omitempty"`
RevisionNumber int `json:"revision_number"`
Status string `json:"status"`
Remarks *string `json:"remarks,omitempty"`
ActedAt *time.Time `json:"acted_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
Step *ApprovalFlowStepResponse `json:"step,omitempty"`
Approver *UserResponse `json:"approver,omitempty"`
}
type OutgoingLetterApprovalRevisionNumberResponse struct {
RevisionNumber int `json:"revision_number"`
Approvals []EnhancedOutgoingLetterApprovalResponse `json:"approvals"`
}
// GetLetterApprovalsResponse represents the list of approvals for a letter
type GetLetterApprovalsResponse struct {
LetterID uuid.UUID `json:"letter_id"`
LetterNumber string `json:"letter_number"`
LetterStatus string `json:"letter_status"`
TotalSteps int `json:"total_steps"`
CurrentStep int `json:"current_step"`
CurrentRevisionNumber int `json:"current_revision_number"`
Approvals []OutgoingLetterApprovalRevisionNumberResponse `json:"approvals"`
}
// OutgoingLetterDiscussionResponse represents a discussion on an outgoing letter
type OutgoingLetterDiscussionResponse struct {
ID uuid.UUID `json:"id"`
LetterID uuid.UUID `json:"letter_id"`
ParentID *uuid.UUID `json:"parent_id,omitempty"`
UserID uuid.UUID `json:"user_id"`
Message string `json:"message"`
Mentions map[string]interface{} `json:"mentions,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
EditedAt *time.Time `json:"edited_at,omitempty"`
User *UserResponse `json:"user,omitempty"`
MentionedUsers []UserResponse `json:"mentioned_users,omitempty"`
Attachments []OutgoingLetterDiscussionAttachmentResponse `json:"attachments,omitempty"`
}
// OutgoingLetterDiscussionAttachmentResponse represents an attachment in a discussion
type OutgoingLetterDiscussionAttachmentResponse struct {
ID uuid.UUID `json:"id"`
DiscussionID uuid.UUID `json:"discussion_id"`
FileURL string `json:"file_url"`
FileName string `json:"file_name"`
FileType string `json:"file_type"`
UploadedBy *uuid.UUID `json:"uploaded_by,omitempty"`
UploadedAt time.Time `json:"uploaded_at"`
}
// TimelineEvent represents a single event in the approval timeline
type TimelineEvent struct {
ID string `json:"id"`
Type string `json:"type"` // "approval", "discussion", "submission", "rejection"
Timestamp time.Time `json:"timestamp"`
Actor *UserResponse `json:"actor,omitempty"`
Action string `json:"action"`
Description string `json:"description"`
Status string `json:"status,omitempty"`
StepOrder int `json:"step_order,omitempty"`
Message string `json:"message,omitempty"`
Data interface{} `json:"data,omitempty"`
}
// ApprovalTimelineResponse represents the complete timeline for a letter
type ApprovalTimelineResponse struct {
LetterID uuid.UUID `json:"letter_id"`
LetterNumber string `json:"letter_number"`
Subject string `json:"subject"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
Timeline []TimelineEvent `json:"timeline"`
Summary TimelineSummary `json:"summary"`
}
// TimelineSummary provides overview statistics for the timeline
type TimelineSummary struct {
TotalSteps int `json:"total_steps"`
CompletedSteps int `json:"completed_steps"`
PendingSteps int `json:"pending_steps"`
CurrentStep int `json:"current_step"`
TotalDuration string `json:"total_duration"`
AverageStepTime string `json:"average_step_time"`
Status string `json:"status"`
}
-107
View File
@@ -1,107 +0,0 @@
package contract
import "github.com/google/uuid"
type TriggerNotificationRequest struct {
UserID uuid.UUID `json:"user_id" validate:"required"`
TemplateID string `json:"template_id" validate:"required"`
TemplateData map[string]interface{} `json:"template_data,omitempty"`
To *NotificationTo `json:"to,omitempty"`
Overrides *NotificationOverrides `json:"overrides,omitempty"`
}
type NotificationTo struct {
Email string `json:"email,omitempty"`
Phone string `json:"phone,omitempty"`
SubscriberID string `json:"subscriber_id,omitempty"`
}
type NotificationOverrides struct {
Email *EmailOverride `json:"email,omitempty"`
SMS *SMSOverride `json:"sms,omitempty"`
InApp *InAppOverride `json:"in_app,omitempty"`
Push *PushOverride `json:"push,omitempty"`
Chat *ChatOverride `json:"chat,omitempty"`
}
type EmailOverride struct {
Subject string `json:"subject,omitempty"`
Body string `json:"body,omitempty"`
From string `json:"from,omitempty"`
}
type SMSOverride struct {
Content string `json:"content,omitempty"`
From string `json:"from,omitempty"`
}
type InAppOverride struct {
Content string `json:"content,omitempty"`
}
type PushOverride struct {
Title string `json:"title,omitempty"`
Content string `json:"content,omitempty"`
}
type ChatOverride struct {
Content string `json:"content,omitempty"`
}
type TriggerNotificationResponse struct {
Success bool `json:"success"`
TransactionID string `json:"transaction_id,omitempty"`
Message string `json:"message,omitempty"`
}
type BulkTriggerNotificationRequest struct {
TemplateID string `json:"template_id" validate:"required"`
UserIDs []uuid.UUID `json:"user_ids" validate:"required,min=1"`
TemplateData map[string]interface{} `json:"template_data,omitempty"`
Overrides *NotificationOverrides `json:"overrides,omitempty"`
}
type BulkTriggerNotificationResponse struct {
Success bool `json:"success"`
TotalSent int `json:"total_sent"`
TotalFailed int `json:"total_failed"`
Results []NotificationResult `json:"results,omitempty"`
}
type NotificationResult struct {
UserID uuid.UUID `json:"user_id"`
Success bool `json:"success"`
TransactionID string `json:"transaction_id,omitempty"`
Error string `json:"error,omitempty"`
}
type GetSubscriberRequest struct {
UserID uuid.UUID `json:"user_id" validate:"required"`
}
type GetSubscriberResponse struct {
SubscriberID string `json:"subscriber_id"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Phone string `json:"phone,omitempty"`
Avatar string `json:"avatar,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
Channels []ChannelCredentials `json:"channels,omitempty"`
}
type ChannelCredentials struct {
Channel string `json:"channel"`
Credentials map[string]interface{} `json:"credentials"`
}
type UpdateSubscriberChannelRequest struct {
UserID uuid.UUID `json:"user_id" validate:"required"`
Channel string `json:"channel" validate:"required,oneof=email sms push chat in_app"`
Credentials map[string]interface{} `json:"credentials" validate:"required"`
}
type UpdateSubscriberChannelResponse struct {
Success bool `json:"success"`
Message string `json:"message,omitempty"`
}
-178
View File
@@ -1,178 +0,0 @@
package contract
import (
"time"
"github.com/google/uuid"
)
// OnlyOffice callback status codes
const (
OnlyOfficeStatusEditing = 1 // Document is being edited
OnlyOfficeStatusReady = 2 // Document is ready for saving
OnlyOfficeStatusSaveError = 3 // Document saving error occurred
OnlyOfficeStatusClosed = 4 // Document is closed with no changes
OnlyOfficeStatusForceSave = 6 // Document is being edited, but saved forcefully
OnlyOfficeStatusForceSaveError = 7 // Error during force save
)
// OnlyOfficeCallbackRequest represents the callback payload from OnlyOffice Document Server
type OnlyOfficeCallbackRequest struct {
Key string `json:"key"` // Document identifier
Status int `json:"status"` // Status code (1-7)
URL string `json:"url,omitempty"` // Document URL when status is 2 or 6
ChangesURL string `json:"changesurl,omitempty"` // URL to document changes
History *OnlyOfficeHistory `json:"history,omitempty"`
Users []string `json:"users,omitempty"` // Users currently editing
Actions []OnlyOfficeAction `json:"actions,omitempty"` // User actions
LastSave string `json:"lastsave,omitempty"` // Last save time
NotModified bool `json:"notmodified,omitempty"` // Document not modified flag
ForceSaveType int `json:"forcesavetype,omitempty"` // Force save type
UserData string `json:"userdata,omitempty"` // Custom user data
Token string `json:"token,omitempty"` // JWT token from OnlyOffice
}
// OnlyOfficeHistory represents document history information
type OnlyOfficeHistory struct {
ServerVersion string `json:"serverVersion"`
Changes []OnlyOfficeHistoryChange `json:"changes"`
}
// OnlyOfficeHistoryChange represents a single change in history
type OnlyOfficeHistoryChange struct {
User OnlyOfficeUser `json:"user"`
Created string `json:"created"`
}
// OnlyOfficeUser represents user information in OnlyOffice
type OnlyOfficeUser struct {
ID string `json:"id"`
Name string `json:"name"`
}
// OnlyOfficeAction represents user actions
type OnlyOfficeAction struct {
Type int `json:"type"` // Action type (0: user connected, 1: user disconnected)
UserID string `json:"userid"` // User identifier
User OnlyOfficeUser `json:"user"` // User information
}
// OnlyOfficeCallbackResponse is the required response format for OnlyOffice
type OnlyOfficeCallbackResponse struct {
Error int `json:"error"` // 0 = success, 1 = document key not found, 2 = callback URL error, 3 = internal server error
}
// OnlyOfficeDocument represents the document section of OnlyOffice config
type OnlyOfficeDocument struct {
FileType string `json:"fileType"` // Document file extension
Key string `json:"key"` // Unique document identifier
Title string `json:"title"` // Document title
URL string `json:"url"` // Document URL
Permissions *OnlyOfficePermissions `json:"permissions,omitempty"`
Info *OnlyOfficeDocumentInfo `json:"info,omitempty"`
}
// OnlyOfficeDocumentInfo represents additional document information
type OnlyOfficeDocumentInfo struct {
Owner string `json:"owner,omitempty"`
Uploaded string `json:"uploaded,omitempty"`
}
// OnlyOfficeConfigRequest represents the proper OnlyOffice configuration format
type OnlyOfficeConfigRequest struct {
Document *OnlyOfficeDocument `json:"document"`
DocumentType string `json:"documentType"` // text, spreadsheet, presentation
EditorConfig *OnlyOfficeEditorConfig `json:"editorConfig"`
Type string `json:"type,omitempty"` // desktop, mobile, embedded
Token string `json:"token,omitempty"` // JWT token for security
Width string `json:"width,omitempty"`
Height string `json:"height,omitempty"`
}
// OnlyOfficeUserConfig represents user configuration for OnlyOffice
type OnlyOfficeUserConfig struct {
ID string `json:"id"`
Name string `json:"name"`
}
// OnlyOfficePermissions represents document permissions
type OnlyOfficePermissions struct {
Comment bool `json:"comment"`
Download bool `json:"download"`
Edit bool `json:"edit"`
FillForms bool `json:"fillForms"`
ModifyContentControl bool `json:"modifyContentControl"`
ModifyFilter bool `json:"modifyFilter"`
Print bool `json:"print"`
Review bool `json:"review"`
}
// OnlyOfficeCustomization represents UI customization options
type OnlyOfficeCustomization struct {
Autosave bool `json:"autosave"`
Comments bool `json:"comments"`
CompactHeader bool `json:"compactHeader"`
CompactToolbar bool `json:"compactToolbar"`
ForceSave bool `json:"forcesave"`
ShowReviewChanges bool `json:"showReviewChanges"`
Zoom int `json:"zoom"`
}
// OnlyOfficeEditorConfig represents editor configuration
type OnlyOfficeEditorConfig struct {
CallbackURL string `json:"callbackUrl"`
Lang string `json:"lang"`
Mode string `json:"mode"` // edit, view
User *OnlyOfficeUserConfig `json:"user,omitempty"`
Customization *OnlyOfficeCustomization `json:"customization,omitempty"`
}
// Document session tracking for OnlyOffice
type DocumentSession struct {
ID uuid.UUID `json:"id"`
DocumentID uuid.UUID `json:"document_id"`
DocumentKey string `json:"document_key"` // OnlyOffice document key
UserID uuid.UUID `json:"user_id"`
Status int `json:"status"` // Current OnlyOffice status
IsLocked bool `json:"is_locked"` // Document lock status
LockedBy *uuid.UUID `json:"locked_by,omitempty"`
LockedAt *time.Time `json:"locked_at,omitempty"`
LastSavedAt *time.Time `json:"last_saved_at,omitempty"`
Version int `json:"version"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// DocumentVersion for tracking document versions
type DocumentVersion struct {
ID uuid.UUID `json:"id"`
DocumentID uuid.UUID `json:"document_id"`
Version int `json:"version"`
FileURL string `json:"file_url"`
FileSize int64 `json:"file_size"`
ChangesURL *string `json:"changes_url,omitempty"`
SavedBy uuid.UUID `json:"saved_by"`
SavedAt time.Time `json:"saved_at"`
IsActive bool `json:"is_active"`
Comments *string `json:"comments,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
// GetEditorConfigRequest represents request to get OnlyOffice editor configuration
type GetEditorConfigRequest struct {
DocumentID uuid.UUID `json:"document_id"`
DocumentType string `json:"document_type"` // letter_attachment, outgoing_attachment, etc.
Mode string `json:"mode"` // edit, view
}
// GetEditorConfigResponse represents OnlyOffice editor configuration response
type GetEditorConfigResponse struct {
DocumentServerURL string `json:"document_server_url"`
Config *OnlyOfficeConfigRequest `json:"config"`
}
// OnlyOfficeConfigInfo represents the OnlyOffice configuration information
type OnlyOfficeConfigInfo struct {
URL string `json:"url"`
Token string `json:"token"`
}
-107
View File
@@ -1,107 +0,0 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type PermissionResponse struct {
ID uuid.UUID `json:"id"`
Code string `json:"code"`
Action string `json:"action,omitempty"`
Description *string `json:"description,omitempty"`
}
type CreatePermissionRequest struct {
Code string `json:"code"` // unique
Description *string `json:"description,omitempty"`
}
type UpdatePermissionRequest struct {
Code *string `json:"code,omitempty"`
Description *string `json:"description,omitempty"`
}
type ListPermissionsResponse struct {
Permissions []PermissionResponse `json:"permissions"`
}
type RoleWithPermissionsResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
Description *string `json:"description,omitempty"`
Permissions []PermissionResponse `json:"permissions"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type CreateRoleRequest struct {
Name string `json:"name"`
Code string `json:"code"`
Description *string `json:"description,omitempty"`
PermissionCodes []string `json:"permission_codes,omitempty"`
}
type UpdateRoleRequest struct {
Name *string `json:"name,omitempty"`
Code *string `json:"code,omitempty"`
Description *string `json:"description,omitempty"`
PermissionCodes *[]string `json:"permission_codes,omitempty"`
}
type ListRolesResponse struct {
Roles []RoleWithPermissionsResponse `json:"roles"`
}
// Module contracts
type ModuleResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
}
type ModuleWithPermissionsResponse struct {
Module ModuleResponse `json:"module"`
Permissions []PermissionResponse `json:"permissions"`
}
type PermissionsGroupedResponse struct {
Data []ModuleWithPermissionsResponse `json:"data"`
}
// New Role contracts for the required API
type ModulePermissionInput struct {
Module string `json:"module" binding:"required"`
Actions []string `json:"actions" binding:"required"`
}
type CreateOrUpdateRoleRequest struct {
Name string `json:"name" binding:"required"`
Code string `json:"code" binding:"required"`
Description string `json:"description,omitempty"`
Permissions []ModulePermissionInput `json:"permissions" binding:"required"`
}
type RoleDetailResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
Description string `json:"description,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Permissions []RolePermissionModuleResponse `json:"permissions"`
}
type RolePermissionModuleResponse struct {
Module ModuleResponse `json:"module"`
Actions []PermissionActionResponse `json:"actions"`
}
type PermissionActionResponse struct {
ID uuid.UUID `json:"id"`
Action string `json:"action"`
Code string `json:"code"`
Description string `json:"description,omitempty"`
}
@@ -1,35 +0,0 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreateRepositoryAttachmentRequest struct {
FileURL string `json:"file_url" validate:"required"`
FileName string `json:"file_name" validate:"required"`
FileType string `json:"file_type" validate:"required"`
Category string `json:"category" validate:"required"`
}
type RepositoryAttachmentsResponse struct {
ID uuid.UUID `json:"id"`
FileURL string `json:"file_url"`
FileName string `json:"file_name"`
FileType string `json:"file_type"`
Category string `json:"category"`
UploadBy uuid.UUID `json:"upload_by"`
UploadAt time.Time `json:"upload_at"`
}
type ListRepositoryAttachmentsResponse struct {
Attachments []RepositoryAttachmentsResponse `json:"attachments"`
Pagination PaginationResponse `json:"pagination"`
}
type ListRepositoryAttachmentsRequest struct {
Page int `json:"page"`
Limit int `json:"limit"`
Search *string `json:"search,omitempty"`
}
+20 -156
View File
@@ -7,20 +7,15 @@ import (
)
type CreateUserRequest struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=6"`
RoleID *uuid.UUID `json:"role_id,omitempty" validate:"required"`
DepartmentIDs []uuid.UUID `json:"department_ids,omitempty"`
Name string `json:"name" validate:"required,min=1,max=255"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=6"`
}
type UpdateUserRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
Email *string `json:"email,omitempty" validate:"omitempty,email"`
Role *uuid.UUID `json:"role,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
Permissions *map[string]interface{} `json:"permissions,omitempty"`
DepartmentIDs *[]uuid.UUID `json:"department_ids,omitempty"`
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
Email *string `json:"email,omitempty" validate:"omitempty,email"`
IsActive *bool `json:"is_active,omitempty"`
}
type ChangePasswordRequest struct {
@@ -28,169 +23,38 @@ type ChangePasswordRequest struct {
NewPassword string `json:"new_password" validate:"required,min=6"`
}
type ChangeUserPasswordRequest struct {
NewPassword string `json:"new_password" validate:"required,min=6"`
}
type UpdateUserOutletRequest struct {
OutletID uuid.UUID `json:"outlet_id" validate:"required"`
}
type LoginRequest struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
}
type LoginResponse struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
User UserResponse `json:"user"`
Roles []RoleResponse `json:"roles"`
Permissions []string `json:"permissions"`
Departments []DepartmentResponse `json:"departments"`
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
User *UserResponse `json:"user"`
}
type RefreshTokenRequest struct {
RefreshToken string `json:"refresh_token" validate:"required"`
}
type UserResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Roles []RoleResponse `json:"roles,omitempty"`
DepartmentResponse []DepartmentResponse `json:"department_response"`
Profile *UserProfileResponse `json:"profile,omitempty"`
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListUsersRequest struct {
Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"`
Role *string `json:"role,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
Search *string `json:"search,omitempty"`
RoleCode *string `json:"role_code,omitempty"`
}
type ListUsersResponse struct {
type PaginatedUserResponse struct {
Users []UserResponse `json:"users"`
Pagination PaginationResponse `json:"pagination"`
}
type RoleResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
}
type DepartmentResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
Path string `json:"path"`
}
type ListDepartmentsRequest struct {
Search string `json:"search,omitempty" form:"search"`
Page int `json:"page,omitempty" form:"page"`
Limit int `json:"limit,omitempty" form:"limit"`
}
type ListDepartmentsResponse struct {
Departments []DepartmentResponse `json:"departments"`
Total int64 `json:"total"`
Page int `json:"page"`
Limit int `json:"limit"`
}
type CreateDepartmentRequest struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Code string `json:"code" validate:"required,min=1,max=50"`
ParentID *uuid.UUID `json:"parent_id,omitempty"`
}
type UpdateDepartmentRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
Code *string `json:"code,omitempty" validate:"omitempty,min=1,max=50"`
ParentID *uuid.UUID `json:"parent_id,omitempty"`
}
type GetDepartmentResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
Path string `json:"path"`
ParentID *uuid.UUID `json:"parent_id,omitempty"`
ParentName *string `json:"parent_name,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type DepartmentNode struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
Path string `json:"path"`
Level int `json:"level"`
Children []*DepartmentNode `json:"children,omitempty"`
}
type OrganizationalChartResponse struct {
Chart []*DepartmentNode `json:"chart"`
TotalNodes int `json:"total_nodes"`
}
type UserProfileResponse struct {
UserID uuid.UUID `json:"user_id"`
FullName string `json:"full_name"`
DisplayName *string `json:"display_name,omitempty"`
Phone *string `json:"phone,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
JobTitle *string `json:"job_title,omitempty"`
EmployeeNo *string `json:"employee_no,omitempty"`
Bio *string `json:"bio,omitempty"`
Timezone string `json:"timezone"`
Locale string `json:"locale"`
Preferences map[string]interface{} `json:"preferences"`
NotificationPrefs map[string]interface{} `json:"notification_prefs"`
LastSeenAt *time.Time `json:"last_seen_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Roles []RoleResponse `json:"roles"`
}
type UpdateUserProfileRequest struct {
FullName *string `json:"full_name,omitempty"`
DisplayName *string `json:"display_name,omitempty"`
Phone *string `json:"phone,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
JobTitle *string `json:"job_title,omitempty"`
EmployeeNo *string `json:"employee_no,omitempty"`
Bio *string `json:"bio,omitempty"`
Timezone *string `json:"timezone,omitempty"`
Locale *string `json:"locale,omitempty"`
Preferences *map[string]interface{} `json:"preferences,omitempty"`
NotificationPrefs *map[string]interface{} `json:"notification_prefs,omitempty"`
}
type TitleResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Code *string `json:"code,omitempty"`
Description *string `json:"description,omitempty"`
}
type ListTitlesResponse struct {
Titles []TitleResponse `json:"titles"`
}
// MentionUsersRequest represents the request for getting users for mention purposes
type MentionUsersRequest struct {
Search *string `json:"search,omitempty" form:"search"` // Optional search term for username
Limit *int `json:"limit,omitempty" form:"limit"` // Optional limit, defaults to 50, max 100
}
// MentionUsersResponse represents the response for getting users for mention purposes
type MentionUsersResponse struct {
Users []UserResponse `json:"users"`
Count int `json:"count"`
}