Skip to content

Commit

Permalink
teams model made in backen, new api for product and teams which now f…
Browse files Browse the repository at this point in the history
…etch from databvase not algolia
  • Loading branch information
sharma.yash committed Jul 6, 2023
1 parent d0c375d commit 0d8ba7a
Show file tree
Hide file tree
Showing 25 changed files with 1,045 additions and 95 deletions.
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/hermes.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

211 changes: 182 additions & 29 deletions internal/api/products.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,211 @@ package api

import (
"encoding/json"
"fmt"
"github.com/hashicorp-forge/hermes/internal/structs"
"gorm.io/gorm"
"net/http"

"github.com/hashicorp-forge/hermes/internal/config"
"github.com/hashicorp-forge/hermes/internal/structs"
"github.com/hashicorp-forge/hermes/pkg/algolia"
"github.com/hashicorp-forge/hermes/pkg/models"
"github.com/hashicorp/go-hclog"
)

type ProductRequest struct {
ProductName string `json:"productName,omitempty"`
ProductAbbreviation string `json:"productAbbreviation,omitempty"`
}

// ProductsHandler returns the product mappings to the Hermes frontend.
func ProductsHandler(cfg *config.Config, a *algolia.Client, log hclog.Logger) http.Handler {
func ProductsHandler(cfg *config.Config, ar *algolia.Client,
aw *algolia.Client, db *gorm.DB, log hclog.Logger) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Only allow GET requests.
if r.Method != http.MethodGet {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}

// Get products and associated data from Algolia
products, err := getProductsData(a)
if err != nil {
log.Error("error getting products from algolia", "error", err)
http.Error(w, "Error getting product mappings",
http.StatusInternalServerError)
return
}
switch r.Method {
case "POST":
// Decode request.
var req ProductRequest
if err := decodeRequest(r, &req); err != nil {
log.Error("error decoding products request", "error", err)
http.Error(w, fmt.Sprintf("Bad request: %q", err),
http.StatusBadRequest)
return
}

// Add the data to both algolia and the Postgres Database
err := AddNewProducts(ar, aw, db, req)
if err != nil {
log.Error("error inserting new product/Business Unit", "error", err)
http.Error(w, "Error inserting products",
http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
// Send success response
// Send success response with success message
response := struct {
Message string `json:"message"`
}{
Message: "Product/BU Inserted successfully",
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
enc := json.NewEncoder(w)
err = enc.Encode(response)

enc := json.NewEncoder(w)
err = enc.Encode(products)
if err != nil {
log.Error("error encoding products response", "error", err)
http.Error(w, "Error getting products",
http.StatusInternalServerError)
case "GET":
// Get products and associated data from Algolia
products, err := getProductsData(db)
if err != nil {
log.Error("error getting products from database", "error", err)
http.Error(w, "Error getting product mappings",
http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

enc := json.NewEncoder(w)
err = enc.Encode(products)
if err != nil {
log.Error("error encoding products response", "error", err)
http.Error(w, "Error getting products",
http.StatusInternalServerError)
return
}
default:
w.WriteHeader(http.StatusMethodNotAllowed)
return

}

})
}

// getProducts gets the product or area name and their associated
// data from Algolia
func getProductsData(a *algolia.Client) (map[string]structs.ProductData, error) {
p := structs.Products{
// data from Database
func getProductsData(db *gorm.DB) (map[string]struct {
Abbreviation string `json:"abbreviation"`
PerDocTypeData interface{} `json:"perDocTypeData"`
}, error) {
var products []models.Product

if err := db.Select("name, abbreviation").Find(&products).Error; err != nil {
return nil, err
}

productData := make(map[string]struct {
Abbreviation string `json:"abbreviation"`
PerDocTypeData interface{} `json:"perDocTypeData"`
})

for _, product := range products {
productData[product.Name] = struct {
Abbreviation string `json:"abbreviation"`
PerDocTypeData interface{} `json:"perDocTypeData"`
}{
Abbreviation: product.Abbreviation,
PerDocTypeData: nil, // You can populate this field as needed
}
}

return productData, nil
}

// AddNewProducts This helper fuction add the newly added product in both algolia and upserts it
// in the postgres Database
func AddNewProducts(ar *algolia.Client,
aw *algolia.Client, db *gorm.DB, req ProductRequest) error {

// Step 1: Update the algolia object
var productsObj = structs.Products{
ObjectID: "products",
Data: make(map[string]structs.ProductData, 0),
}
// Retrieve the existing productsObj from Algolia
err := ar.Internal.GetObject("products", &productsObj)
if err != nil {
return fmt.Errorf("error retrieving existing products object from Algolia : %w", err)
}

err := a.Internal.GetObject("products", &p)
// Add the new value to the productsObj
productsObj.Data[req.ProductName] = structs.ProductData{
Abbreviation: req.ProductAbbreviation,
}

// Save the updated productsObj back to Algolia
// this replaces the old object completely
// Save Algolia products object.
res, err := aw.Internal.SaveObject(&productsObj)
if err != nil {
return nil, err
return fmt.Errorf("error saving Algolia products object: %w", err)
}
err = res.Wait()
if err != nil {
return fmt.Errorf("error saving Algolia products object: %w", err)
}

return p.Data, nil
// Step 2: upsert in the db
pm := models.Product{
Name: req.ProductName,
Abbreviation: req.ProductAbbreviation,
}
if err := pm.Upsert(db); err != nil {
return fmt.Errorf("error upserting product: %w", err)
}

return nil
}

// Below Code uses Algolia for fetching
// ProductsHandler returns the product mappings to the Hermes frontend.
//func ProductsHandler(cfg *config.Config, ar *algolia.Client,
// aw *algolia.Client, log hclog.Logger) http.Handler {
// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// // Only allow GET requests.
// if r.Method != http.MethodGet {
// w.WriteHeader(http.StatusMethodNotAllowed)
// return
// }
//
// // Get products and associated data from Algolia
// products, err := getProductsData(ar)
// if err != nil {
// log.Error("error getting products from algolia", "error", err)
// http.Error(w, "Error getting product mappings",
// http.StatusInternalServerError)
// return
// }
//
// w.Header().Set("Content-Type", "application/json")
// w.WriteHeader(http.StatusOK)
//
// enc := json.NewEncoder(w)
// err = enc.Encode(products)
// if err != nil {
// log.Error("error encoding products response", "error", err)
// http.Error(w, "Error getting products",
// http.StatusInternalServerError)
// return
// }
// })
//}
//
//// getProducts gets the product or area name and their associated
//// data from Algolia
//func getProductsData(ar *algolia.Client) (map[string]structs.ProductData, error) {
// p := structs.Products{
// ObjectID: "products",
// Data: make(map[string]structs.ProductData, 0),
// }
//
// err := ar.Internal.GetObject("products", &p)
// if err != nil {
// return nil, err
// }
//
// return p.Data, nil
//}
//
Loading

0 comments on commit 0d8ba7a

Please sign in to comment.