diff --git a/handlers/exports/agenda.go b/handlers/exports/agenda.go index f6de827..67f0ec2 100755 --- a/handlers/exports/agenda.go +++ b/handlers/exports/agenda.go @@ -3,9 +3,6 @@ package exports import ( "context" "fmt" - "net/http" - "sort" - "git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting" agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi" agendastorage "git.coopgo.io/coopgo-platform/agenda/storage" @@ -13,69 +10,129 @@ import ( groupsstorage "git.coopgo.io/coopgo-platform/groups-management/storage" accounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" accountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" + "github.com/gorilla/mux" "github.com/xuri/excelize/v2" + "net/http" + "sort" ) -func (h *ExportsHandler) Agenda(w http.ResponseWriter, r *http.Request) { - resp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{ - Namespaces: []string{"parcoursmob_dispositifs"}, - }) +func (h *ExportsHandler) Agenda(filter string) func(w http.ResponseWriter, r *http.Request) { + switch filter { + case "allEvents": + return func(w http.ResponseWriter, r *http.Request) { + resp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{ + Namespaces: []string{"parcoursmob_dispositifs"}, + }) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } - if err != nil { - fmt.Println(err) - w.WriteHeader(http.StatusInternalServerError) - return - } + events := []agendastorage.Event{} - events := []agendastorage.Event{} + groupids := []string{} + beneficiaries_ids := []string{} + for _, e := range resp.Events { + groupids = append(groupids, e.Owners...) + events = append(events, e.ToStorageType()) - groupids := []string{} - beneficiaries_ids := []string{} - for _, e := range resp.Events { - groupids = append(groupids, e.Owners...) - events = append(events, e.ToStorageType()) + for _, subscriptions := range e.Subscriptions { + beneficiaries_ids = append(beneficiaries_ids, subscriptions.Subscriber) + } + } + + sort.Sort(sorting.EventsByStartdate(events)) + + groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{ + Groupids: groupids, + }) + groups := map[string]groupsstorage.Group{} + + if err == nil { + for _, g := range groupsresp.Groups { + groups[g.Id] = g.ToStorageType() + } + } + + beneficiaries, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), &accounts.GetAccountsBatchRequest{ + Accountids: beneficiaries_ids, + }) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + beneficiaries_map := map[string]accountsstorage.Account{} + for _, ben := range beneficiaries.Accounts { + beneficiaries_map[ben.Id] = ben.ToStorageType() + } + + f := h.generateExcel(events, groups, beneficiaries_map) + + h.writeFileResponse(f, w) + } + + case "oneEvent": + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + eventId := vars["eventid"] + resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), &agenda.GetEventRequest{ + Id: eventId, + }) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + groupids := []string{} + beneficiaries_ids := []string{} + groupids = append(groupids, resp.Event.Owners...) + for _, subscriptions := range resp.Event.Subscriptions { + beneficiaries_ids = append(beneficiaries_ids, subscriptions.Subscriber) + } + groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{ + Groupids: groupids, + }) + groups := map[string]groupsstorage.Group{} + + if err == nil { + for _, g := range groupsresp.Groups { + groups[g.Id] = g.ToStorageType() + } + } + + beneficiaries, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), &accounts.GetAccountsBatchRequest{ + Accountids: beneficiaries_ids, + }) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + beneficiaries_map := map[string]accountsstorage.Account{} + for _, ben := range beneficiaries.Accounts { + beneficiaries_map[ben.Id] = ben.ToStorageType() + } + + f := h.generateExcel([]agendastorage.Event{resp.Event.ToStorageType()}, groups, beneficiaries_map) + h.writeFileResponse(f, w) - for _, subscriptions := range e.Subscriptions { - beneficiaries_ids = append(beneficiaries_ids, subscriptions.Subscriber) } } + return nil +} - sort.Sort(sorting.EventsByStartdate(events)) - - groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{ - Groupids: groupids, - }) - groups := map[string]groupsstorage.Group{} - - if err == nil { - for _, g := range groupsresp.Groups { - groups[g.Id] = g.ToStorageType() - } - } - - beneficiaries, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), &accounts.GetAccountsBatchRequest{ - Accountids: beneficiaries_ids, - }) - if err != nil { - fmt.Println(err) - w.WriteHeader(http.StatusInternalServerError) - return - } - - beneficiaries_map := map[string]accountsstorage.Account{} - for _, ben := range beneficiaries.Accounts { - beneficiaries_map[ben.Id] = ben.ToStorageType() - } - - /////////////// Generate file - +func (h *ExportsHandler) generateExcel(events []agendastorage.Event, groups map[string]groupsstorage.Group, + beneficiaries_map map[string]accountsstorage.Account) *excelize.File { f := excelize.NewFile() defer func() { if err := f.Close(); err != nil { fmt.Println(err) } }() - f.SetCellValue("Sheet1", "A1", "Evénement") f.SetCellValue("Sheet1", "B1", "Date de début") f.SetCellValue("Sheet1", "C1", "Date de fin") @@ -85,8 +142,6 @@ func (h *ExportsHandler) Agenda(w http.ResponseWriter, r *http.Request) { f.SetCellValue("Sheet1", "G1", "Prescipteur") f.SetCellValue("Sheet1", "H1", "Prescipteur Nom") f.SetCellValue("Sheet1", "I1", "Gestionnaire événement") - // f.SetCellValue("Sheet1", "I1", "Prescripteur téléphone") - i := 2 for _, e := range events { if len(e.Owners) == 0 { @@ -128,10 +183,14 @@ func (h *ExportsHandler) Agenda(w http.ResponseWriter, r *http.Request) { } } + return f +} + +func (h *ExportsHandler) writeFileResponse(file *excelize.File, w http.ResponseWriter) { w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Disposition", "attachment; filename="+"Workbook.xlsx") w.Header().Set("Content-Transfer-Encoding", "binary") w.Header().Set("Expires", "0") - f.Write(w) + file.Write(w) } diff --git a/main.go b/main.go index 65786c9..9284f12 100755 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ import ( func main() { cfg, err := ReadConfig() + if err != nil { panic(err) } @@ -29,17 +30,15 @@ func main() { templates_public_dir = cfg.GetString("templates.public_dir") dev_env = cfg.GetBool("dev_env") ) - svc, err := services.NewServicesHandler(cfg) if err != nil { panic(err) } - + fmt.Println(cfg) kv, err := cache.NewKVHandler(cfg) if err != nil { panic(err) } - filestorage, err := cache.NewFileStorage(cfg) idp, err := identification.NewIdentificationProvider(cfg, svc, kv) @@ -163,12 +162,11 @@ func main() { export := r.PathPrefix("/exports").Subrouter() export.HandleFunc("/fleets/bookings", exportsHandler.Bookings) - export.HandleFunc("/agenda/subscriptions", exportsHandler.Agenda) + export.HandleFunc("/agenda/subscriptions", exportsHandler.Agenda("allEvents")) + export.HandleFunc("/agenda/{eventid}", exportsHandler.Agenda("oneEvent")) export.Use(idp.Middleware) export.Use(idp.GroupsMiddleware) - fmt.Println("-> HTTP server listening on", address) - srv := &http.Server{ Handler: r, Addr: address, diff --git a/utils/storage/badger.go b/utils/storage/badger.go index c3284db..82be054 100644 --- a/utils/storage/badger.go +++ b/utils/storage/badger.go @@ -1,91 +1 @@ package storage - -import ( - "encoding/json" - "github.com/dgraph-io/badger/v4" - "github.com/spf13/viper" - "time" -) - -type BadgerHandler struct { - db *badger.DB -} - -func NewBadgerHandler(cfg *viper.Viper) (*BadgerHandler, error) { - dbPath := cfg.GetString("storage.kv.badger.dbPath") - - opts := badger.DefaultOptions(dbPath) - db, err := badger.Open(opts) - if err != nil { - return nil, err - } - - return &BadgerHandler{ - db: db, - }, nil -} - -func (bh *BadgerHandler) Put(k string, v any) error { - err := bh.db.Update(func(txn *badger.Txn) error { - bytes, err := json.Marshal(v) - if err != nil { - return err - } - return txn.Set([]byte(k), bytes) - }) - - return err -} - -func (bh *BadgerHandler) PutWithTTL(k string, v any, duration time.Duration) error { - err := bh.db.Update(func(txn *badger.Txn) error { - bytes, err := json.Marshal(v) - if err != nil { - return err - } - entry := badger.NewEntry([]byte(k), bytes).WithTTL(duration) - return txn.SetEntry(entry) - }) - - return err -} - -func (bh *BadgerHandler) Get(k string) (any, error) { - var value []byte - - err := bh.db.View(func(txn *badger.Txn) error { - item, err := txn.Get([]byte(k)) - if err != nil { - return err - } - - err = item.Value(func(val []byte) error { - value = make([]byte, len(val)) - copy(value, val) - return nil - }) - - return err - }) - - if err != nil { - return nil, err - } - - var result map[string]interface{} - err = json.Unmarshal(value, &result) - if err != nil { - return nil, err - } - - return result, nil -} - -func (bh *BadgerHandler) Delete(k string) error { - err := bh.db.Update(func(txn *badger.Txn) error { - err := txn.Delete([]byte(k)) - return err - }) - - return err -} diff --git a/utils/storage/groupcache.go b/utils/storage/groupcache.go index 01f444e..82be054 100644 --- a/utils/storage/groupcache.go +++ b/utils/storage/groupcache.go @@ -1,170 +1 @@ package storage - -import ( - "context" - "fmt" - "github.com/spf13/viper" - "gopkg.in/square/go-jose.v2/json" - "log" - "net/http" - "reflect" - "time" - - "github.com/mailgun/groupcache/v2" -) - -type GroupCacheHandler struct { - KVHandler KVHandler - Group *groupcache.Group - cacheTTL int64 -} - -func NewGroupCacheHandler(cfg *viper.Viper) (*GroupCacheHandler, error) { - var ( - endpoint = cfg.GetString("storage.kv.groupcache.endpoint") - ports = cfg.GetStringSlice("storage.kv.groupcache.ports") - cacheTTL = cfg.GetInt64("storage.kv.groupcache.cacheTTL") - cacheServers []*http.Server - ) - - var kvHandler KVHandler - var getterFunc groupcache.GetterFunc - kvType := cfg.GetString("storage.kv.groupcache.db") - getterFunc = func(ctx context.Context, key string, dest groupcache.Sink) error { - resp, err := kvHandler.Get(key) - if err != nil { - return err - } - if resp == nil { - return fmt.Errorf("key not found in etcd: %s", key) - } - jsonResp, _ := json.Marshal(resp) - dest.SetBytes(jsonResp, time.Now().Add(time.Duration(cacheTTL)*time.Minute)) - return nil - - } - switch kvType { - case "etcd": - etcdHandler, err := NewEtcdHandler(cfg) - if err != nil { - return nil, err - } - kvHandler = etcdHandler - case "badger": - badgerHandler, err := NewBadgerHandler(cfg) - if err != nil { - return nil, err - } - kvHandler = badgerHandler - default: - return nil, fmt.Errorf("unsupported kvType: %s", kvType) - } - - pool := groupcache.NewHTTPPoolOpts("", &groupcache.HTTPPoolOptions{}) - for _, port := range ports { - pool.Set("http://" + endpoint + ":" + port) - server := &http.Server{ - Addr: endpoint + ":" + port, - Handler: pool, - } - cacheServers = append(cacheServers, server) - go func(srv *http.Server) { - log.Printf("Serving cache server %s \n", srv.Addr) - if err := srv.ListenAndServe(); err != nil { - log.Fatal(err) - } - }(server) - } - - group := groupcache.NewGroup("data", 3000000, getterFunc) - handler := &GroupCacheHandler{ - KVHandler: kvHandler, - Group: group, - cacheTTL: cacheTTL, - } - - return handler, nil -} - -func (h *GroupCacheHandler) Put(k string, v any) error { - // Update the value in the underlying key-value store - err := h.KVHandler.Put(k, v) - if err != nil { - return err - } - - // Check if the key exists in the cache - var value []byte - err = h.Group.Get(nil, k, groupcache.AllocatingByteSliceSink(&value)) - if err == nil { - // Key exists in the cache, compare with the new value - if !reflect.DeepEqual(value, v) { - // Values are different, update the cache - jsonValue, err := json.Marshal(v) - if err != nil { - return err - } - expireTime := time.Now().Add(time.Duration(h.cacheTTL) * time.Minute) - err = h.Group.Set(context.Background(), k, jsonValue, expireTime, false) - if err != nil { - return err - } - } - } - - return nil -} - -func (h *GroupCacheHandler) PutWithTTL(k string, v any, duration time.Duration) error { - - err := h.KVHandler.PutWithTTL(k, v, duration) - // Check if the key exists in the cache - var value []byte - err = h.Group.Get(nil, k, groupcache.AllocatingByteSliceSink(&value)) - if err == nil { - // Key exists in the cache, compare with the new value - if !reflect.DeepEqual(value, v) { - // Values are different, update the cache - jsonValue, err := json.Marshal(v) - if err != nil { - return err - } - expireTime := time.Now().Add(time.Duration(h.cacheTTL) * time.Minute) - err = h.Group.Set(context.Background(), k, jsonValue, expireTime, false) - if err != nil { - return err - } - } - } - - return nil - -} - -func (h *GroupCacheHandler) Get(k string) (any, error) { - var value []byte - err := h.Group.Get(nil, k, groupcache.AllocatingByteSliceSink(&value)) - if err != nil { - fmt.Println("error", err) - return nil, err - } - - var result any - err = json.Unmarshal(value, &result) - if err != nil { - return nil, err - } - return result, nil -} - -func (h *GroupCacheHandler) Delete(k string) error { - err := h.KVHandler.Delete(k) - if err != nil { - return err - } - err = h.Group.Remove(context.Background(), k) - if err != nil { - return err - } - return nil -}