first commit
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
package report
|
||||
|
||||
// Employee merepresentasikan data dari PostgreSQL
|
||||
type Employee struct {
|
||||
ID int64 `gorm:"column:id"`
|
||||
Name string `gorm:"column:name"`
|
||||
Department string `gorm:"column:department"`
|
||||
}
|
||||
|
||||
// Attendance merepresentasikan data dari MySQL
|
||||
type Attendance struct {
|
||||
EmployeeID int64 `gorm:"column:employee_id"`
|
||||
Status string `gorm:"column:status"`
|
||||
Date string `gorm:"column:date"`
|
||||
}
|
||||
|
||||
// CombinedReport adalah hasil olahan (gabungan) yang akan dikembalikan ke Client
|
||||
type CombinedReport struct {
|
||||
EmployeeName string `json:"employee_name"`
|
||||
Department string `json:"department"`
|
||||
Attendances []Attendance `json:"attendances"`
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"context"
|
||||
"service/internal/infrastructure/database"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
GetEmployeesFromPostgres(ctx context.Context) ([]Employee, error)
|
||||
GetAttendancesFromMySQL(ctx context.Context, employeeIDs []int64) ([]Attendance, error)
|
||||
}
|
||||
|
||||
type repository struct {
|
||||
dbManager database.Service
|
||||
pgDBName string // Nama koneksi PostgreSQL di config.yaml
|
||||
mySQLName string // Nama koneksi MySQL di config.yaml
|
||||
}
|
||||
|
||||
func NewRepository(dbManager database.Service, pgDBName, mySQLName string) Repository {
|
||||
return &repository{
|
||||
dbManager: dbManager,
|
||||
pgDBName: pgDBName,
|
||||
mySQLName: mySQLName,
|
||||
}
|
||||
}
|
||||
|
||||
// Mengakses PostgreSQL
|
||||
func (r *repository) GetEmployeesFromPostgres(ctx context.Context) ([]Employee, error) {
|
||||
db, err := r.dbManager.GetGormDB(r.pgDBName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var employees []Employee
|
||||
err = db.WithContext(ctx).Table("employees").Find(&employees).Error
|
||||
return employees, err
|
||||
}
|
||||
|
||||
// Mengakses MySQL
|
||||
func (r *repository) GetAttendancesFromMySQL(ctx context.Context, employeeIDs []int64) ([]Attendance, error) {
|
||||
db, err := r.dbManager.GetGormDB(r.mySQLName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var attendances []Attendance
|
||||
// Hanya ambil attendance untuk employee yang ditemukan di Postgres
|
||||
err = db.WithContext(ctx).Table("attendances").Where("employee_id IN ?", employeeIDs).Find(&attendances).Error
|
||||
return attendances, err
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"context"
|
||||
"service/pkg/errors"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
GenerateCrossDBReport(ctx context.Context) ([]CombinedReport, error)
|
||||
}
|
||||
|
||||
type service struct {
|
||||
repo Repository
|
||||
}
|
||||
|
||||
func NewService(repo Repository) Service {
|
||||
return &service{repo: repo}
|
||||
}
|
||||
|
||||
func (s *service) GenerateCrossDBReport(ctx context.Context) ([]CombinedReport, error) {
|
||||
// 1. Ambil data master karyawan dari PostgreSQL
|
||||
employees, err := s.repo.GetEmployeesFromPostgres(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.InternalError().Message("Failed to fetch employees from Postgres").Cause(err).Build()
|
||||
}
|
||||
|
||||
if len(employees) == 0 {
|
||||
return []CombinedReport{}, nil
|
||||
}
|
||||
|
||||
// 2. Ekstrak ID karyawan untuk klausa IN (?) di MySQL
|
||||
var empIDs []int64
|
||||
for _, emp := range employees {
|
||||
empIDs = append(empIDs, emp.ID)
|
||||
}
|
||||
|
||||
// 3. Ambil data transaksi kehadiran dari MySQL menggunakan list ID di atas
|
||||
attendances, err := s.repo.GetAttendancesFromMySQL(ctx, empIDs)
|
||||
if err != nil {
|
||||
return nil, errors.InternalError().Message("Failed to fetch attendances from MySQL").Cause(err).Build()
|
||||
}
|
||||
|
||||
// 4. Proses In-Memory Join (Mapping)
|
||||
// Kelompokkan attendance berdasarkan EmployeeID agar pencarian cepat O(1)
|
||||
attendanceMap := make(map[int64][]Attendance)
|
||||
for _, att := range attendances {
|
||||
attendanceMap[att.EmployeeID] = append(attendanceMap[att.EmployeeID], att)
|
||||
}
|
||||
|
||||
// Gabungkan data
|
||||
var reports []CombinedReport
|
||||
for _, emp := range employees {
|
||||
reports = append(reports, CombinedReport{
|
||||
EmployeeName: emp.Name,
|
||||
Department: emp.Department,
|
||||
Attendances: attendanceMap[emp.ID], // Ambil relasinya dari memory map
|
||||
})
|
||||
}
|
||||
|
||||
return reports, nil
|
||||
}
|
||||
Reference in New Issue
Block a user