// internal/services/export_service.go package services import ( "bytes" "fmt" "lost-and-found/internal/models" "lost-and-found/internal/repositories" "lost-and-found/internal/utils" "time" "gorm.io/gorm" ) type ExportService struct { itemRepo *repositories.ItemRepository archiveRepo *repositories.ArchiveRepository claimRepo *repositories.ClaimRepository auditLogRepo *repositories.AuditLogRepository } func NewExportService(db *gorm.DB) *ExportService { return &ExportService{ itemRepo: repositories.NewItemRepository(db), archiveRepo: repositories.NewArchiveRepository(db), claimRepo: repositories.NewClaimRepository(db), auditLogRepo: repositories.NewAuditLogRepository(db), } } // ExportRequest represents export request data type ExportRequest struct { Type string `json:"type"` // items, archives, claims, audit_logs Format string `json:"format"` // pdf, excel StartDate *time.Time `json:"start_date"` EndDate *time.Time `json:"end_date"` Status string `json:"status"` } // ExportItemsToPDF exports items to PDF func (s *ExportService) ExportItemsToPDF(req ExportRequest, userID uint, ipAddress, userAgent string) (*bytes.Buffer, error) { // Get items items, _, err := s.itemRepo.FindAll(1, 10000, req.Status, "", "") if err != nil { return nil, err } // Filter by date range if provided var filteredItems []models.Item for _, item := range items { if req.StartDate != nil && item.DateFound.Before(*req.StartDate) { continue } if req.EndDate != nil && item.DateFound.After(*req.EndDate) { continue } filteredItems = append(filteredItems, item) } // Generate PDF pdf := utils.NewPDFExporter() pdf.AddTitle("Laporan Barang Ditemukan") pdf.AddSubtitle(fmt.Sprintf("Periode: %s - %s", formatDate(req.StartDate), formatDate(req.EndDate))) pdf.AddNewLine() // Add table headers := []string{"No", "Nama Barang", "Kategori", "Lokasi", "Tanggal Ditemukan", "Status"} var data [][]string for i, item := range filteredItems { data = append(data, []string{ fmt.Sprintf("%d", i+1), item.Name, item.Category.Name, item.Location, item.DateFound.Format("02 Jan 2006"), item.Status, }) } pdf.AddTable(headers, data) // Add footer pdf.AddNewLine() pdf.AddText(fmt.Sprintf("Total: %d barang", len(filteredItems))) pdf.AddText(fmt.Sprintf("Dicetak pada: %s", time.Now().Format("02 January 2006 15:04"))) // Log audit s.auditLogRepo.Log(&userID, models.ActionExport, "report", nil, fmt.Sprintf("Exported items report (PDF, %d items)", len(filteredItems)), ipAddress, userAgent) return pdf.Output(), nil } // ExportItemsToExcel exports items to Excel func (s *ExportService) ExportItemsToExcel(req ExportRequest, userID uint, ipAddress, userAgent string) (*bytes.Buffer, error) { // Get items items, _, err := s.itemRepo.FindAll(1, 10000, req.Status, "", "") if err != nil { return nil, err } // Filter by date range if provided var filteredItems []models.Item for _, item := range items { if req.StartDate != nil && item.DateFound.Before(*req.StartDate) { continue } if req.EndDate != nil && item.DateFound.After(*req.EndDate) { continue } filteredItems = append(filteredItems, item) } // Generate Excel excel := utils.NewExcelExporter() excel.SetSheetName("Barang Ditemukan") // Add headers headers := []string{"No", "Nama Barang", "Kategori", "Lokasi", "Deskripsi", "Tanggal Ditemukan", "Status", "Pelapor", "Kontak"} excel.AddRow(headers) // Add data for i, item := range filteredItems { excel.AddRow([]string{ fmt.Sprintf("%d", i+1), item.Name, item.Category.Name, item.Location, item.Description, item.DateFound.Format("02 Jan 2006"), item.Status, item.ReporterName, item.ReporterContact, }) } // Auto-size columns excel.AutoSizeColumns(len(headers)) // Log audit s.auditLogRepo.Log(&userID, models.ActionExport, "report", nil, fmt.Sprintf("Exported items report (Excel, %d items)", len(filteredItems)), ipAddress, userAgent) return excel.Output() } // ExportArchivesToPDF exports archives to PDF func (s *ExportService) ExportArchivesToPDF(req ExportRequest, userID uint, ipAddress, userAgent string) (*bytes.Buffer, error) { archives, _, err := s.archiveRepo.FindAll(1, 10000, "", "") if err != nil { return nil, err } // Filter by date range var filteredArchives []models.Archive for _, archive := range archives { if req.StartDate != nil && archive.ArchivedAt.Before(*req.StartDate) { continue } if req.EndDate != nil && archive.ArchivedAt.After(*req.EndDate) { continue } filteredArchives = append(filteredArchives, archive) } pdf := utils.NewPDFExporter() pdf.AddTitle("Laporan Barang yang Diarsipkan") pdf.AddSubtitle(fmt.Sprintf("Periode: %s - %s", formatDate(req.StartDate), formatDate(req.EndDate))) pdf.AddNewLine() headers := []string{"No", "Nama Barang", "Kategori", "Alasan Arsip", "Tanggal Arsip"} var data [][]string for i, archive := range filteredArchives { data = append(data, []string{ fmt.Sprintf("%d", i+1), archive.Name, archive.Category.Name, archive.ArchivedReason, archive.ArchivedAt.Format("02 Jan 2006"), }) } pdf.AddTable(headers, data) pdf.AddNewLine() pdf.AddText(fmt.Sprintf("Total: %d barang", len(filteredArchives))) s.auditLogRepo.Log(&userID, models.ActionExport, "report", nil, fmt.Sprintf("Exported archives report (PDF, %d items)", len(filteredArchives)), ipAddress, userAgent) return pdf.Output(), nil } // ExportClaimsToPDF exports claims to PDF func (s *ExportService) ExportClaimsToPDF(req ExportRequest, userID uint, ipAddress, userAgent string) (*bytes.Buffer, error) { claims, _, err := s.claimRepo.FindAll(1, 10000, req.Status, nil, nil) if err != nil { return nil, err } // Filter by date range var filteredClaims []models.Claim for _, claim := range claims { if req.StartDate != nil && claim.CreatedAt.Before(*req.StartDate) { continue } if req.EndDate != nil && claim.CreatedAt.After(*req.EndDate) { continue } filteredClaims = append(filteredClaims, claim) } pdf := utils.NewPDFExporter() pdf.AddTitle("Laporan Klaim Barang") pdf.AddSubtitle(fmt.Sprintf("Periode: %s - %s", formatDate(req.StartDate), formatDate(req.EndDate))) pdf.AddNewLine() headers := []string{"No", "Barang", "Pengklaim", "Status", "Tanggal Klaim"} var data [][]string for i, claim := range filteredClaims { data = append(data, []string{ fmt.Sprintf("%d", i+1), claim.Item.Name, claim.User.Name, claim.Status, claim.CreatedAt.Format("02 Jan 2006"), }) } pdf.AddTable(headers, data) pdf.AddNewLine() pdf.AddText(fmt.Sprintf("Total: %d klaim", len(filteredClaims))) s.auditLogRepo.Log(&userID, models.ActionExport, "report", nil, fmt.Sprintf("Exported claims report (PDF, %d claims)", len(filteredClaims)), ipAddress, userAgent) return pdf.Output(), nil } // Helper function to format date func formatDate(date *time.Time) string { if date == nil { return "N/A" } return date.Format("02 Jan 2006") }