2025-11-17 12:17:44 +07:00

254 lines
6.9 KiB
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")
}