INFRA-2945 | incident_products entity, repo, service and handler (#382)

* INFRA-2945 | incident_products entity, repo, service and handler

* INFRA-2945 | added product details in the incident DTO and removed incident_product_handler
This commit is contained in:
Shashank Shekhar
2024-02-28 14:35:22 +05:30
committed by GitHub
parent 983c743609
commit c349cd65d5
15 changed files with 249 additions and 21 deletions

View File

@@ -64,6 +64,7 @@ generatemocks:
cd $(CURDIR)/model/incident_jira && minimock -i IncidentJiraRepository -s _mock.go -o $(CURDIR)/mocks
cd $(CURDIR)/model/product && minimock -i ProductRepository -s _mock.go -o $(CURDIR)/mocks
cd $(CURDIR)/model/products_teams && minimock -i ProductsTeamsRepository -s _mock.go -o $(CURDIR)/mocks
cd $(CURDIR)/model/incident_products && minimock -i IncidentProductsRepository -s _mock.go -o $(CURDIR)/mocks
cd $(CURDIR)/service/google && minimock -i IDriveService -s _mock.go -o $(CURDIR)/mocks
cd $(CURDIR)/service/rca && minimock -i IRcaService -s _mock.go -o $(CURDIR)/mocks
cd $(CURDIR)/pkg/alertClient && minimock -i AlertClient -s _mock.go -o $(CURDIR)/mocks

View File

@@ -5,6 +5,7 @@ import (
"github.com/spf13/viper"
"gorm.io/gorm"
"houston/model/incident"
"houston/model/incident_products"
"houston/model/log"
productModel "houston/model/product"
"houston/model/products_teams"
@@ -26,6 +27,7 @@ import (
"houston/service/documentService"
"houston/service/google"
incidentService "houston/service/incident/impl"
"houston/service/incidentProducts"
"houston/service/products"
"houston/service/productsTeams"
rcaService "houston/service/rca/impl"
@@ -64,6 +66,7 @@ type houstonServices struct {
calendarService *conference.CalendarService
tagService *tagService.TagService
productsService products.ProductService
incidentProductsService incidentProducts.IncidentProductsService
productTeamsService productsTeams.ProductTeamsService
severityService severityService.ISeverityService
teamSeverityService teamSeverity.ITeamSeverityService
@@ -103,6 +106,7 @@ func InitializeServices() {
calendarService: initCalendarService(),
tagService: initTagService(),
productsService: initProductsService(),
incidentProductsService: initIncidentProductsService(),
productTeamsService: initProductTeamsService(),
severityService: initSeverityService(),
teamSeverityService: initTeamSeverityService(),
@@ -215,6 +219,14 @@ func GetProductsService() products.ProductService {
return services.productsService
}
func initIncidentProductsService() incidentProducts.IncidentProductsService {
return incidentProducts.NewIncidentProductsService(incident_products.NewIncidentProductsRepo(GetDB()))
}
func GetIncidentProductsService() incidentProducts.IncidentProductsService {
return services.incidentProductsService
}
func initProductTeamsService() productsTeams.ProductTeamsService {
return productsTeams.NewProductTeamsService(products_teams.NewProductsTeamsRepo(GetDB()))
}

View File

@@ -0,0 +1,8 @@
-- Table Definition ----------------------------------------------
CREATE TABLE IF NOT EXISTS incident_products
(
incident_entity_id bigint REFERENCES incident (id),
product_entity_id bigint REFERENCES product (id),
CONSTRAINT incident_products_pkey PRIMARY KEY (incident_entity_id, product_entity_id)
);

View File

@@ -1,6 +1,7 @@
package incident
import (
"houston/model/product"
"time"
"github.com/lib/pq"
@@ -54,23 +55,47 @@ type IncidentEntity struct {
StartTime time.Time `gorm:"column:start_time"`
EndTime *time.Time `gorm:"column:end_time"`
TeamId uint `gorm:"column:team_id"`
JiraLinks pq.StringArray `gorm:"column:jira_links;type:string[]"`
JiraLinks pq.StringArray `gorm:"column:jira_links;type:text[]"`
ConfluenceId *string `gorm:"column:confluence_id"`
SeverityTat time.Time `gorm:"column:severity_tat"`
RemindMeAt *time.Time `gorm:"column:remind_me_at"`
EnableReminder bool `gorm:"column:enable_reminder"`
CreatedBy string `gorm:"column:created_by"`
UpdatedBy string `gorm:"column:updated_by"`
MetaData JSON `gorm:"column:meta_data"`
MetaData JSON `gorm:"column:meta_data;type:jsonb"`
RCA string `gorm:"column:rca_text"`
ConferenceId string `gorm:"column:conference_id"`
ConferenceLink string `gorm:"column:conference_link"`
Products []product.ProductEntity `gorm:"many2many:incident_products;"`
}
func (IncidentEntity) TableName() string {
return "incident"
}
func (i *IncidentEntity) ToDTO() IncidentDTO {
var products []product.ProductDTO
for _, p := range i.Products {
products = append(products, *p.ToDTO())
}
return IncidentDTO{
ID: i.ID,
Title: i.Title,
Description: i.Description,
Status: i.Status,
SeverityId: i.SeverityId,
IncidentName: i.IncidentName,
SlackChannel: i.SlackChannel,
TeamId: i.TeamId,
JiraLinks: i.JiraLinks,
ConfluenceId: i.ConfluenceId,
CreatedBy: i.CreatedBy,
RCA: i.RCA,
ConferenceId: i.ConferenceId,
Products: products,
}
}
// IncidentRoleEntity this table will contain the role of the people assigned to the incident, mapping between incident
// and incident role entity will be one to many
type IncidentRoleEntity struct {

View File

@@ -8,6 +8,7 @@ import (
"github.com/spf13/viper"
"houston/logger"
"houston/model/log"
"houston/model/product"
"houston/model/severity"
"houston/model/team"
utils "houston/service/utils"
@@ -61,6 +62,10 @@ func (r *Repository) CreateIncidentEntity(request *CreateIncidentDTO, tx *gorm.D
teamId, _ := strconv.Atoi(request.TeamId)
incidentStatusEntity, _ := r.GetIncidentStatusByStatusName(string(request.Status))
var products = make([]product.ProductEntity, 0)
for _, productId := range request.ProductIds {
products = append(products, product.ProductEntity{ID: productId})
}
incidentEntity := &IncidentEntity{
Title: request.Title,
@@ -75,6 +80,7 @@ func (r *Repository) CreateIncidentEntity(request *CreateIncidentDTO, tx *gorm.D
CreatedBy: request.CreatedBy,
UpdatedBy: request.UpdatedBy,
MetaData: request.MetaData,
Products: products,
}
tx.Create(incidentEntity)

View File

@@ -5,6 +5,8 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/lib/pq"
"houston/model/product"
"time"
)
@@ -51,6 +53,7 @@ type CreateIncidentDTO struct {
CreatedBy string `json:"created_by,omitempty"`
UpdatedBy string `json:"updated_by,omitempty"`
MetaData JSON `json:"meta_data,omitempty"`
ProductIds []uint `json:"product_ids,omitempty"`
}
type IncidentSeverityTeamDTO struct {
@@ -86,3 +89,21 @@ type TeamMetricDetailsOfIncident struct {
Severity string
ManagerId string
}
type IncidentDTO struct {
ID uint `json:"id,omitempty"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
SeverityId uint `json:"severity_id,omitempty"`
Status uint `json:"status,omitempty"`
IncidentName string `json:"incident_name,omitempty"`
SlackChannel string `json:"slack_channel,omitempty"`
TeamId uint `json:"team_id,omitempty"`
JiraLinks pq.StringArray `json:"jira_links,omitempty"`
ConfluenceId *string `json:"confluence_id,omitempty"`
CreatedBy string `json:"created_by,omitempty"`
RCA string `json:"rca,omitempty"`
ConferenceId string `json:"conference_id,omitempty"`
ConferenceLink string `json:"conference_link,omitempty"`
Products []product.ProductDTO `json:"products,omitempty"`
}

View File

@@ -0,0 +1,19 @@
package incident_products
import (
"houston/model/incident"
"houston/model/product"
)
type IncidentProductEntity struct {
IncidentID uint `gorm:"primaryKey;column:incident_entity_id"`
ProductID uint `gorm:"primaryKey;column:product_entity_id"`
// Add foreign key constraints
Incident incident.IncidentEntity `gorm:"foreignKey:IncidentID"`
Product product.ProductEntity `gorm:"foreignKey:ProductID"`
}
func (IncidentProductEntity) TableName() string {
return "incident_products"
}

View File

@@ -0,0 +1,14 @@
package incident_products
import (
"gorm.io/gorm"
"houston/model/incident"
)
type IncidentProductsRepository interface {
GetAllIncidentsForProduct(productIDs ...uint) ([]incident.IncidentEntity, error)
}
func NewIncidentProductsRepo(db *gorm.DB) IncidentProductsRepository {
return &incidentProductsRepositoryImpl{db: db}
}

View File

@@ -0,0 +1,30 @@
package incident_products
import (
"errors"
"gorm.io/gorm"
"houston/model/incident"
)
type incidentProductsRepositoryImpl struct {
db *gorm.DB
}
func (repo *incidentProductsRepositoryImpl) GetAllIncidentsForProduct(productIDs ...uint) ([]incident.IncidentEntity, error) {
var entities []IncidentProductEntity
result := repo.db.Preload("Incident").Preload("Product").Find(&entities, "product_entity_id IN ?", productIDs)
if result.Error != nil {
return nil, result.Error
}
if result.RowsAffected == 0 {
return nil, errors.New("no incidents found")
}
var incidentEntities []incident.IncidentEntity
for _, entity := range entities {
ie := entity.Incident
ie.Products = append(ie.Products, entity.Product)
incidentEntities = append(incidentEntities, ie)
}
return incidentEntities, nil
}

View File

@@ -961,6 +961,7 @@ func buildCreateIncidentDTO(
createIncidentRequest.StartTime = time.Now()
createIncidentRequest.EnableReminder = false
createIncidentRequest.MetaData = rawJson
createIncidentRequest.ProductIds = createIncRequest.ProductIds
return &createIncidentRequest, nil
}

View File

@@ -0,0 +1,14 @@
package incidentProducts
import (
"houston/model/incident"
"houston/model/incident_products"
)
type IncidentProductsService interface {
GetAllIncidentsForProduct(productIDs ...uint) ([]incident.IncidentDTO, error)
}
func NewIncidentProductsService(repo incident_products.IncidentProductsRepository) IncidentProductsService {
return newIncidentProductsServiceImpl(repo)
}

View File

@@ -0,0 +1,26 @@
package incidentProducts
import (
"houston/model/incident"
"houston/model/incident_products"
)
type incidentProductsServiceImpl struct {
repo incident_products.IncidentProductsRepository
}
func newIncidentProductsServiceImpl(repo incident_products.IncidentProductsRepository) *incidentProductsServiceImpl {
return &incidentProductsServiceImpl{repo}
}
func (s *incidentProductsServiceImpl) GetAllIncidentsForProduct(productIDs ...uint) ([]incident.IncidentDTO, error) {
incidentEntities, err := s.repo.GetAllIncidentsForProduct(productIDs...)
if err != nil {
return nil, err
}
var incidentDTOs []incident.IncidentDTO
for _, entity := range incidentEntities {
incidentDTOs = append(incidentDTOs, entity.ToDTO())
}
return incidentDTOs, nil
}

View File

@@ -0,0 +1,48 @@
package incidentProducts
import (
"errors"
"github.com/gojuno/minimock/v3"
"github.com/stretchr/testify/suite"
"houston/logger"
"houston/mocks"
"houston/model/incident"
"testing"
)
type IncidentProductsServiceSuite struct {
suite.Suite
controller *minimock.Controller
repoMock *mocks.IncidentProductsRepositoryMock
service IncidentProductsService
}
func (suite *IncidentProductsServiceSuite) SetupTest() {
logger.InitLogger()
suite.controller = minimock.NewController(suite.T())
suite.T().Cleanup(suite.controller.Finish)
suite.repoMock = mocks.NewIncidentProductsRepositoryMock(suite.controller)
suite.service = NewIncidentProductsService(suite.repoMock)
}
func TestIncidentProducts(t *testing.T) {
suite.Run(t, new(IncidentProductsServiceSuite))
}
func (suite *IncidentProductsServiceSuite) TestIncidentProductsServiceImpl_GetAllIncidentsForProduct() {
suite.repoMock.GetAllIncidentsForProductMock.When(1).Then(make([]incident.IncidentEntity, 0), nil)
_, err := suite.service.GetAllIncidentsForProduct(1)
if err != nil {
suite.Fail("Get All Incidents For Product Failed", err)
}
}
func (suite *IncidentProductsServiceSuite) TestIncidentProductsServiceImpl_GetAllIncidentsForProduct_Error() {
suite.repoMock.GetAllIncidentsForProductMock.When(1).Then(nil, errors.New("error"))
_, err := suite.service.GetAllIncidentsForProduct(1)
if err == nil {
suite.Fail("Get All Incidents For Product Failed", err)
}
}

View File

@@ -554,6 +554,7 @@ func (i *incidentService) buildCreateIncidentDTO(createIncRequest incidentReques
createIncidentRequest.StartTime = time.Now()
createIncidentRequest.EnableReminder = false
createIncidentRequest.MetaData = rawJson
createIncidentRequest.ProductIds = createIncRequest.ProductIds
return &createIncidentRequest, nil
}

View File

@@ -12,6 +12,7 @@ type CreateIncidentRequest struct {
TeamName string `gorm:"column:teamName"`
CreatedBy string `gorm:"column:createdBy"`
MetaData CreateIncidentMetaData `gorm:"json:metaData"`
ProductIds []uint `json:"productIds"`
}
type CreateIncidentRequestV2 struct {
@@ -21,6 +22,7 @@ type CreateIncidentRequestV2 struct {
TeamID string `json:"type"`
CreatedBy string `json:"createdBy"`
MetaData CreateIncidentMetaData `json:"metaData"`
ProductIds []uint `json:"productIds"`
}
type CreateIncidentMetaData struct {