feat: initial commit
- retrieve data from http xml response - parse to struct - save on database - expose rest server to list database collection documents
This commit is contained in:
commit
4075a2c39b
|
@ -0,0 +1,102 @@
|
||||||
|
.env
|
||||||
|
viper.default.yaml
|
||||||
|
.vscode
|
||||||
|
certs
|
||||||
|
coverage
|
||||||
|
.notes
|
||||||
|
|
||||||
|
# frontend
|
||||||
|
node_modules
|
||||||
|
*-error.log
|
||||||
|
*.lock
|
||||||
|
sw.*
|
||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### Node template
|
||||||
|
# Logs
|
||||||
|
/logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Nuxt generate
|
||||||
|
dist
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless
|
||||||
|
|
||||||
|
# IDE / Editor
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Service worker
|
||||||
|
sw.*
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Vim swap files
|
||||||
|
*.swp
|
|
@ -0,0 +1,141 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
_ "net/http/pprof"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/config"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/internal/request"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/internal/xml_loader"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/adapter/repository/mongodb/employee_wi"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/crono"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/domain"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
// var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// flag.Parse()
|
||||||
|
// if *cpuprofile != "" {
|
||||||
|
// f, err := os.Create(*cpuprofile)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// }
|
||||||
|
// pprof.StartCPUProfile(f)
|
||||||
|
// defer pprof.StopCPUProfile()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Add pprof endpoints
|
||||||
|
// go func() {
|
||||||
|
// log.Println(http.ListenAndServe("localhost:6060", nil))
|
||||||
|
// }()
|
||||||
|
|
||||||
|
cr := crono.New()
|
||||||
|
defer cr.Table()
|
||||||
|
cfg := config.NewConfig(".env")
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
dbOpts := options.Client()
|
||||||
|
dbOpts.ApplyURI(cfg.DbAddress)
|
||||||
|
|
||||||
|
client, err := mongo.NewClient(dbOpts)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("mongo.NewClient", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("mongodb client is connected")
|
||||||
|
|
||||||
|
if err = client.Connect(ctx); err != nil {
|
||||||
|
log.Fatalln("client.Connect", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
employeeWICollection := client.Database(cfg.DbName).Collection(cfg.EmployeeWorkInformationCollection)
|
||||||
|
if err = employeeWICollection.Drop(ctx); err != nil {
|
||||||
|
log.Fatalln("employeeWICollection.Drop", err)
|
||||||
|
}
|
||||||
|
professionalRepo := employee_wi.NewRepo(employeeWICollection)
|
||||||
|
|
||||||
|
r := request.NewRequestService(cfg.AmsApi, cfg.AmsApiKey)
|
||||||
|
|
||||||
|
employeeIDList := cfg.EmployeeIdList
|
||||||
|
|
||||||
|
ewiLoader := xml_loader.NewEmployeeWILoader(r)
|
||||||
|
from, to := "2023-01-01", "2023-01-31"
|
||||||
|
cr.MarkAndRestart("dependencies loaded")
|
||||||
|
ctx, cancel := context.WithCancel(signalContext(context.Background()))
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
ewiChan := make(chan []domain.EmployeeWorkInformation, len(employeeIDList))
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for _, v := range employeeIDList {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(v string) {
|
||||||
|
cr.Restart()
|
||||||
|
defer wg.Done()
|
||||||
|
wi, err := ewiLoader.LoadEmployee(v, from, to)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ewiChan <- wi
|
||||||
|
cr.MarkAndRestart(fmt.Sprintf("ewiLoader.LoadEmployee | %s | from: %s to: %s", v, from, to))
|
||||||
|
}(v)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := <-errChan; err != nil {
|
||||||
|
log.Fatalln("error while process", err)
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for v := range ewiChan {
|
||||||
|
log.Println("len v", len(v))
|
||||||
|
err := professionalRepo.InsertMany(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cr.MarkAndRestart(fmt.Sprintf("database inserted: %d", len(v)))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("cancel")
|
||||||
|
errChan <- nil
|
||||||
|
}()
|
||||||
|
wg.Wait()
|
||||||
|
// <-ctx.Done()
|
||||||
|
log.Println("gracefully shutdown")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signalContext(ctx context.Context) context.Context {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
|
sigs := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigs, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
log.Println("listening for shutdown signal")
|
||||||
|
<-sigs
|
||||||
|
log.Println("shutdown signal received")
|
||||||
|
signal.Stop(sigs)
|
||||||
|
close(sigs)
|
||||||
|
cancel()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/config"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/internal/api/http"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/internal/services"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/adapter/repository/mongodb/employee_wi"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfg := config.NewConfig(".env")
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
dbOpts := options.Client()
|
||||||
|
dbOpts.ApplyURI(cfg.DbAddress)
|
||||||
|
|
||||||
|
client, err := mongo.NewClient(dbOpts)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("mongo.NewClient", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("mongodb client is connected")
|
||||||
|
|
||||||
|
if err = client.Connect(ctx); err != nil {
|
||||||
|
log.Fatalln("client.Connect", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
employeeWICollection := client.Database(cfg.DbName).Collection(cfg.EmployeeWorkInformationCollection)
|
||||||
|
professionalRepo := employee_wi.NewRepo(employeeWICollection)
|
||||||
|
|
||||||
|
restServer := http.
|
||||||
|
NewRestServer(cfg).
|
||||||
|
WithProfessionalHandler(services.NewEmployeeWIService(ctx, professionalRepo))
|
||||||
|
|
||||||
|
if err = restServer.Start(cfg.ApiPort, ""); err != nil {
|
||||||
|
log.Fatalln("restServer.Start", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(signalContext(context.Background()))
|
||||||
|
defer cancel()
|
||||||
|
<-ctx.Done()
|
||||||
|
restServer.Shutdown()
|
||||||
|
log.Println("gracefully shutdown")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signalContext(ctx context.Context) context.Context {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
|
sigs := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigs, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
log.Println("listening for shutdown signal")
|
||||||
|
<-sigs
|
||||||
|
log.Println("shutdown signal received")
|
||||||
|
signal.Stop(sigs)
|
||||||
|
close(sigs)
|
||||||
|
cancel()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
root_dir "gitea.urkob.com/urko/go-root-dir"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"github.com/kelseyhightower/envconfig"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RootDir() string {
|
||||||
|
return root_dir.RootDir("ess-etl-go")
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
ApiPort string `required:"true" split_words:"true"`
|
||||||
|
AmsApi string `required:"true" split_words:"true"`
|
||||||
|
AmsApiKey string `required:"true" split_words:"true"`
|
||||||
|
DbAddress string `required:"true" split_words:"true"`
|
||||||
|
DbName string `required:"true" split_words:"true"`
|
||||||
|
EmployeeWorkInformationCollection string `required:"true" split_words:"true"`
|
||||||
|
EmployeeIdList []string `required:"true" split_words:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig(envFile string) *Config {
|
||||||
|
if envFile != "" {
|
||||||
|
err := godotenv.Load(RootDir() + "/" + envFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("godotenv.Load:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := &Config{}
|
||||||
|
err := envconfig.Process("", cfg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("envconfig.Process: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
version: "3.4"
|
||||||
|
services:
|
||||||
|
mongodb:
|
||||||
|
image: mongo
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:${MONGODB_PORT}:${MONGODB_PORT}"
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: "${MONGODB_USER}"
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: "${MONGODB_PASS}"
|
||||||
|
MONGO_INITDB_DATABASE: "${DB_NAME}"
|
||||||
|
volumes:
|
||||||
|
- mongodata:/data/db
|
||||||
|
networks:
|
||||||
|
- mongonet
|
||||||
|
networks:
|
||||||
|
mongonet:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mongodata:
|
|
@ -0,0 +1,40 @@
|
||||||
|
module gitea.urkob.com/urko/ess-etl-go
|
||||||
|
|
||||||
|
go 1.19
|
||||||
|
|
||||||
|
require (
|
||||||
|
gitea.urkob.com/urko/go-root-dir v0.0.0-20230311113851-2f6d4355888a
|
||||||
|
github.com/gofiber/fiber/v2 v2.43.0
|
||||||
|
github.com/jedib0t/go-pretty/v6 v6.4.6
|
||||||
|
github.com/joho/godotenv v1.5.1
|
||||||
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
|
go.mongodb.org/mongo-driver v1.11.3
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
|
github.com/klauspost/compress v1.16.3 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||||
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||||
|
github.com/philhofer/fwd v1.1.2 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect
|
||||||
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
|
||||||
|
github.com/tinylib/msgp v1.1.8 // indirect
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
|
github.com/valyala/fasthttp v1.45.0 // indirect
|
||||||
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
|
github.com/xdg-go/scram v1.1.1 // indirect
|
||||||
|
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
|
golang.org/x/crypto v0.7.0 // indirect
|
||||||
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
|
golang.org/x/sys v0.6.0 // indirect
|
||||||
|
golang.org/x/text v0.8.0 // indirect
|
||||||
|
)
|
|
@ -0,0 +1,144 @@
|
||||||
|
gitea.urkob.com/urko/go-root-dir v0.0.0-20230311113851-2f6d4355888a h1:s73cd3bRR6v0LGiBei841iIolbBJN2tbkUwN54X9vVg=
|
||||||
|
gitea.urkob.com/urko/go-root-dir v0.0.0-20230311113851-2f6d4355888a/go.mod h1:mU9nRHl70tBhJFbgKotpoXMV+s0wx+1uJ988p4oEpSo=
|
||||||
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gofiber/fiber/v2 v2.43.0 h1:yit3E4kHf178B60p5CQBa/3v+WVuziWMa/G2ZNyLJB0=
|
||||||
|
github.com/gofiber/fiber/v2 v2.43.0/go.mod h1:mpS1ZNE5jU+u+BA4FbM+KKnUzJ4wzTK+FT2tG3tU+6I=
|
||||||
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/jedib0t/go-pretty/v6 v6.4.6 h1:v6aG9h6Uby3IusSSEjHaZNXpHFhzqMmjXcPq1Rjl9Jw=
|
||||||
|
github.com/jedib0t/go-pretty/v6 v6.4.6/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
|
||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||||
|
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||||
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
|
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
|
||||||
|
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||||
|
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||||
|
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||||
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
|
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||||
|
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
|
||||||
|
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4=
|
||||||
|
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8=
|
||||||
|
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
|
||||||
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
||||||
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
|
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
|
||||||
|
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
|
||||||
|
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasthttp v1.45.0 h1:zPkkzpIn8tdHZUrVa6PzYd0i5verqiPSkgTd3bSUcpA=
|
||||||
|
github.com/valyala/fasthttp v1.45.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
||||||
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
|
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
|
||||||
|
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||||
|
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
|
||||||
|
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y=
|
||||||
|
go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||||
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||||
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -0,0 +1,39 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/internal/services"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EmployeeWorkInformationHandler struct {
|
||||||
|
employeeWISrv services.EmployeeWIService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEmployeeWorkInformation(employeeWISrv services.EmployeeWIService) *EmployeeWorkInformationHandler {
|
||||||
|
return &EmployeeWorkInformationHandler{
|
||||||
|
employeeWISrv: employeeWISrv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hdl *EmployeeWorkInformationHandler) Get(c *fiber.Ctx) error {
|
||||||
|
id := c.Params("id", "")
|
||||||
|
if id == "" {
|
||||||
|
return JSONError(c, fiber.StatusBadRequest, fmt.Errorf("id is empty"), defaultErrMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
employeeNumber, err := strconv.Atoi(id)
|
||||||
|
if err != nil {
|
||||||
|
return JSONError(c, fiber.StatusBadRequest, fmt.Errorf("strconv.Atoi: %s", err), defaultErrMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
employeeWI, err := hdl.employeeWISrv.GetByEmployeeNumber(c.Context(), employeeNumber)
|
||||||
|
if err != nil {
|
||||||
|
return JSONError(c, fiber.StatusBadRequest, fmt.Errorf("professionalSrv.GetByID: %s", err), defaultErrMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).JSON(employeeWI)
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultErrMessage = "couldn't process request"
|
||||||
|
)
|
||||||
|
|
||||||
|
func JSONError(c *fiber.Ctx, status int, err error, message string) error {
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("JSONError: %s\n", err)
|
||||||
|
}
|
||||||
|
return c.Status(status).SendString("error: " + message)
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/config"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/internal/api/http/handler"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/internal/services"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type restServer struct {
|
||||||
|
app *fiber.App
|
||||||
|
cfg *config.Config
|
||||||
|
employeeWIHdl *handler.EmployeeWorkInformationHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRestServer(cfg *config.Config) *restServer {
|
||||||
|
return &restServer{
|
||||||
|
cfg: cfg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *restServer) WithProfessionalHandler(employeeWISrv services.EmployeeWIService) *restServer {
|
||||||
|
s.employeeWIHdl = handler.NewEmployeeWorkInformation(employeeWISrv)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
func (s *restServer) Start(apiPort, bearerToken string) error {
|
||||||
|
s.app = fiber.New()
|
||||||
|
|
||||||
|
s.app.Use(cors.New(cors.Config{
|
||||||
|
AllowMethods: "GET,POST,OPTIONS",
|
||||||
|
AllowOrigins: "*",
|
||||||
|
AllowHeaders: "Origin, Accept, Content-Type, X-CSRF-Token, Authorization",
|
||||||
|
ExposeHeaders: "Origin",
|
||||||
|
}))
|
||||||
|
|
||||||
|
s.app.Get("/employee_wi/:id", func(c *fiber.Ctx) error {
|
||||||
|
return s.employeeWIHdl.Get(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
s.app.Get("/employee_wi/:id", func(c *fiber.Ctx) error {
|
||||||
|
return s.employeeWIHdl.Get(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := s.app.Listen(":" + apiPort); err != nil {
|
||||||
|
return fmt.Errorf("app.Listen: %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *restServer) Shutdown() {
|
||||||
|
if err := s.app.Server().Shutdown(); err != nil {
|
||||||
|
log.Printf("app.Server().Shutdown(): %s\n", err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package request
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RequestService struct {
|
||||||
|
api string
|
||||||
|
apiKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRequestService(api, apiKey string) RequestService {
|
||||||
|
return RequestService{
|
||||||
|
api: api,
|
||||||
|
apiKey: apiKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPayload(employeeIDList []string) (string, error) {
|
||||||
|
employees := strings.Builder{}
|
||||||
|
_, err := employees.Write([]byte(`<EmployeeWorkInformationQuery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><EmployeeNumbers>`))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error while write headers: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, employeeID := range employeeIDList {
|
||||||
|
employees.Write([]byte("<string>" + employeeID + "</string>"))
|
||||||
|
}
|
||||||
|
_, err = employees.Write([]byte("</EmployeeNumbers></EmployeeWorkInformationQuery>"))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error while write footer: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return employees.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r RequestService) EmployeeWorkInformation(employeeIDList []string, from, to string) (io.Reader, error) {
|
||||||
|
url := r.api + "/EmployeeWorkInformation/Search/" + from + "/" + to + "/"
|
||||||
|
method := "POST"
|
||||||
|
|
||||||
|
stringPayload, err := getPayload(employeeIDList)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getPayload: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := strings.NewReader(stringPayload)
|
||||||
|
client := &http.Client{}
|
||||||
|
req, err := http.NewRequest(method, url, payload)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("http.NewRequest: %s", err)
|
||||||
|
}
|
||||||
|
req.Header.Add("Cache-Control", "no-cache")
|
||||||
|
req.Header.Add("Authorization", r.apiKey)
|
||||||
|
req.Header.Add("Content-Type", "application/xml")
|
||||||
|
|
||||||
|
res, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("client.Do: %s", err)
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("ioutil.ReadAll: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//log.Println("readed", string(body))
|
||||||
|
|
||||||
|
return bytes.NewReader(body), nil
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/adapter/repository/mongodb"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/adapter/repository/mongodb/employee_wi"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/domain"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EmployeeWIService struct {
|
||||||
|
ctx context.Context
|
||||||
|
repo *employee_wi.Repo
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEmployeeWIService(ctx context.Context, repo *employee_wi.Repo) EmployeeWIService {
|
||||||
|
return EmployeeWIService{
|
||||||
|
ctx: ctx,
|
||||||
|
repo: repo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EmployeeWIService) GetByEmployeeNumber(ctx context.Context, employeeNumber int) ([]domain.EmployeeWorkInformation, error) {
|
||||||
|
model, err := p.repo.Find(ctx, bson.M{
|
||||||
|
"employee_number": employeeNumber,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("repo.FindById: %s", err)
|
||||||
|
}
|
||||||
|
return model, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EmployeeWIService) GetByAll(ctx context.Context, id string) (*domain.EmployeeWorkInformation, error) {
|
||||||
|
model, err := p.repo.FindById(ctx, mongodb.MustObjectID(id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("repo.FindById: %s", err)
|
||||||
|
}
|
||||||
|
return model, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EmployeeWIService) InsertMany(ctx context.Context, ei []domain.EmployeeWorkInformation) error {
|
||||||
|
err := p.repo.InsertMany(ctx, ei)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("repo.AddAppointmentTo: %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package xml_loader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/internal/request"
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EmployeeWILoader struct {
|
||||||
|
r request.RequestService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEmployeeWILoader(r request.RequestService) EmployeeWILoader {
|
||||||
|
return EmployeeWILoader{r: r}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EmployeeWILoader) LoadEmployeeList(employeeIDList []string, from, to string) ([]domain.EmployeeWorkInformation, error) {
|
||||||
|
reader, err := e.r.EmployeeWorkInformation(employeeIDList, from, to)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("r.EmployeeWorkInformation: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadFromXML(reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EmployeeWILoader) LoadEmployee(employeeID, from, to string) ([]domain.EmployeeWorkInformation, error) {
|
||||||
|
employeeIDList := []string{employeeID}
|
||||||
|
|
||||||
|
reader, err := e.r.EmployeeWorkInformation(employeeIDList, from, to)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("r.EmployeeWorkInformation: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadFromXML(reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadFromXML(xmlFile io.Reader) ([]domain.EmployeeWorkInformation, error) {
|
||||||
|
var awi domain.ArrayOfEmployeeWorkInformation
|
||||||
|
|
||||||
|
if err := xml.NewDecoder(xmlFile).Decode(&awi); err != nil {
|
||||||
|
return nil, fmt.Errorf("xml.NewDecoder.Decode: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return awi.EmployeeWorkInfos, nil
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package employee_wi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/domain"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *Repo) Find(ctx context.Context, filter bson.M) ([]domain.EmployeeWorkInformation, error) {
|
||||||
|
cursor, err := p.collection.Find(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("p.collection.Find: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pList []domain.EmployeeWorkInformation
|
||||||
|
if err := cursor.All(ctx, &pList); err != nil {
|
||||||
|
return nil, fmt.Errorf("p.cursor.All: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Repo) FindOne(ctx context.Context) (*domain.EmployeeWorkInformation, error) {
|
||||||
|
res := p.collection.FindOne(ctx, bson.M{})
|
||||||
|
var model *domain.EmployeeWorkInformation
|
||||||
|
if err := res.Decode(&model); err != nil {
|
||||||
|
return nil, fmt.Errorf("doc.Decode: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return model, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Repo) FindById(ctx context.Context, id primitive.ObjectID) (*domain.EmployeeWorkInformation, error) {
|
||||||
|
res := p.collection.FindOne(ctx, bson.M{"_id": id})
|
||||||
|
var model *domain.EmployeeWorkInformation
|
||||||
|
if err := res.Decode(model); err != nil {
|
||||||
|
return nil, fmt.Errorf("doc.Decode: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return model, nil
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package employee_wi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gitea.urkob.com/urko/ess-etl-go/pkg/domain"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *Repo) InsertOne(ctx context.Context, dto *domain.EmployeeWorkInformation) (string, error) {
|
||||||
|
inserted, err := p.collection.InsertOne(ctx, dto)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("p.collection.InsertOne: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
oid, ok := inserted.InsertedID.(primitive.ObjectID)
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("res.InsertedID is not valid _id")
|
||||||
|
}
|
||||||
|
|
||||||
|
return oid.Hex(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Repo) InsertMany(ctx context.Context, dto []domain.EmployeeWorkInformation) error {
|
||||||
|
elements := make([]interface{}, 0, len(dto))
|
||||||
|
for _, v := range dto {
|
||||||
|
v.ID = primitive.NewObjectID()
|
||||||
|
elements = append(elements, v)
|
||||||
|
}
|
||||||
|
_, err := p.collection.InsertMany(ctx, elements)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("p.collection.InsertMany: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package employee_wi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRepo(collection *mongo.Collection) *Repo {
|
||||||
|
return &Repo{collection: collection}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Repo struct {
|
||||||
|
collection *mongo.Collection
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package mongodb
|
||||||
|
|
||||||
|
import "go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
|
||||||
|
func MustObjectID(id string) primitive.ObjectID {
|
||||||
|
objectID, err := primitive.ObjectIDFromHex(id)
|
||||||
|
if err != nil {
|
||||||
|
return primitive.NilObjectID
|
||||||
|
}
|
||||||
|
return objectID
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package crono
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Timing struct {
|
||||||
|
Msg string
|
||||||
|
Elapsed time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type Crono struct {
|
||||||
|
Begin time.Time
|
||||||
|
Cursor time.Time
|
||||||
|
Timings []Timing
|
||||||
|
}
|
||||||
|
|
||||||
|
// new cronograph with autostart.
|
||||||
|
func New() *Crono {
|
||||||
|
c := new(Crono)
|
||||||
|
c.Timings = make([]Timing, 0)
|
||||||
|
c.Begin = time.Now()
|
||||||
|
c.Cursor = c.Begin
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// restart the crono
|
||||||
|
// keeps the begin time.
|
||||||
|
func (c *Crono) Restart() {
|
||||||
|
c.Cursor = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// push a mark.
|
||||||
|
func (c *Crono) Mark(msg string) {
|
||||||
|
c.Timings = append(c.Timings, Timing{msg, c.GetElapsed()})
|
||||||
|
}
|
||||||
|
|
||||||
|
// push a mark and restart the cursor time.
|
||||||
|
func (c *Crono) MarkAndRestart(msg string) {
|
||||||
|
c.Mark(msg)
|
||||||
|
c.Restart()
|
||||||
|
}
|
||||||
|
|
||||||
|
// time in seconds since last start
|
||||||
|
// it doesn't restart the crono.
|
||||||
|
func (c *Crono) GetElapsed() time.Duration {
|
||||||
|
return time.Since(c.Cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// total time sice start.
|
||||||
|
func (c *Crono) Total() time.Duration {
|
||||||
|
return time.Since(c.Begin)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Crono) Table() {
|
||||||
|
t := table.NewWriter()
|
||||||
|
t.SetOutputMirror(os.Stdout)
|
||||||
|
t.AppendHeader(table.Row{"#", "Description", "Elapsed"})
|
||||||
|
for i, e := range c.Timings {
|
||||||
|
t.AppendRow([]interface{}{i, e.Msg, durationToString(e.Elapsed)})
|
||||||
|
}
|
||||||
|
t.AppendSeparator()
|
||||||
|
t.AppendFooter(table.Row{"", "Total", durationToString(c.Total())})
|
||||||
|
t.Render()
|
||||||
|
}
|
||||||
|
|
||||||
|
func durationToString(t time.Duration) string {
|
||||||
|
timeString := fmt.Sprintf("%dms", t.Milliseconds())
|
||||||
|
if t.Seconds() > 3 {
|
||||||
|
timeString += " !!!"
|
||||||
|
} else if t.Seconds() > 2 {
|
||||||
|
timeString += " .!!"
|
||||||
|
} else if t.Seconds() > 1 {
|
||||||
|
timeString += " ..!"
|
||||||
|
} else {
|
||||||
|
timeString += " ..."
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeString
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WorkInfo struct {
|
||||||
|
EmployeeNumber int `xml:"EmployeeNumber" json:"employee_number" bson:"employee_number"`
|
||||||
|
Date string `xml:"Date" json:"date" bson:"date"`
|
||||||
|
Shifts []Shift `xml:"Shifts>Shift" json:"shifts" bson:"shifts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Shift struct {
|
||||||
|
Start string `xml:"Start" json:"start" bson:"start"`
|
||||||
|
End string `xml:"End" json:"end" bson:"end"`
|
||||||
|
ShiftCode string `xml:"ShiftCode" json:"shift_code" bson:"shift_code"`
|
||||||
|
ActualStart string `xml:"ActualStart" json:"actual_start" bson:"actual_start"`
|
||||||
|
ActualEnd string `xml:"ActualEnd" json:"actual_end" bson:"actual_end"`
|
||||||
|
RoleCode string `xml:"RoleCode" json:"role_code" bson:"role_code"`
|
||||||
|
ShiftCategoryCode string `xml:"ShiftCategoryCode" json:"shift_category_code" bson:"shift_category_code"`
|
||||||
|
CustomFields []CustomField `xml:"CustomFields>CustomField" json:"custom_fields" bson:"custom_fields"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Baseline struct {
|
||||||
|
BaselineType string `xml:"BaselineType,attr" json:"baseline_type" bson:"baseline_type"`
|
||||||
|
Shifts []Shift `xml:"Shifts>Shift" json:"shifts" bson:"shifts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomField struct {
|
||||||
|
Name string `xml:"Name" json:"name" bson:"name"`
|
||||||
|
Value string `xml:"Value" json:"value" bson:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EmployeeWorkInformation struct {
|
||||||
|
ID primitive.ObjectID `json:"id" bson:"_id"`
|
||||||
|
EmployeeNumber int `xml:"EmployeeNumber" json:"employee_number" bson:"employee_number"`
|
||||||
|
Date string `xml:"Date" json:"date"`
|
||||||
|
WorkInformation WorkInfo `xml:"WorkInformation" json:"work_information" bson:"work_information"`
|
||||||
|
Baselines []Baseline `json:"baselines" bson:"baselines"`
|
||||||
|
CustomFields []CustomField `json:"custom_fields" bson:"custom_fields"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArrayOfEmployeeWorkInformation struct {
|
||||||
|
XMLName xml.Name `xml:"ArrayOfEmployeeWorkInformation"`
|
||||||
|
EmployeeWorkInfos []EmployeeWorkInformation `xml:"EmployeeWorkInformation"`
|
||||||
|
}
|
Loading…
Reference in New Issue