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:
1
Makefile
1
Makefile
@@ -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
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
|
||||
8
db/migration/000017_incident_products_tables.up.sql
Normal file
8
db/migration/000017_incident_products_tables.up.sql
Normal 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)
|
||||
);
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
19
model/incident_products/entity.go
Normal file
19
model/incident_products/entity.go
Normal 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"
|
||||
}
|
||||
14
model/incident_products/incident_products_repository.go
Normal file
14
model/incident_products/incident_products_repository.go
Normal 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}
|
||||
}
|
||||
30
model/incident_products/incident_products_repository_impl.go
Normal file
30
model/incident_products/incident_products_repository_impl.go
Normal 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
|
||||
}
|
||||
@@ -961,6 +961,7 @@ func buildCreateIncidentDTO(
|
||||
createIncidentRequest.StartTime = time.Now()
|
||||
createIncidentRequest.EnableReminder = false
|
||||
createIncidentRequest.MetaData = rawJson
|
||||
createIncidentRequest.ProductIds = createIncRequest.ProductIds
|
||||
return &createIncidentRequest, nil
|
||||
}
|
||||
|
||||
|
||||
14
service/incidentProducts/incident_products_service.go
Normal file
14
service/incidentProducts/incident_products_service.go
Normal 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)
|
||||
}
|
||||
26
service/incidentProducts/incident_products_service_impl.go
Normal file
26
service/incidentProducts/incident_products_service_impl.go
Normal 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
|
||||
}
|
||||
48
service/incidentProducts/incident_products_service_test.go
Normal file
48
service/incidentProducts/incident_products_service_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user