Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add create item endpoint #8

Merged
merged 28 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5fbccf8
feat: add create items table migration
Jibaru Jan 25, 2024
2ca9bce
feat: add create item keywords table migration
Jibaru Jan 25, 2024
932fde4
feat: add item entity
Jibaru Jan 25, 2024
bc40348
feat: add item entity test
Jibaru Jan 25, 2024
5005d64
feat: add item repository interface
Jibaru Jan 25, 2024
cfd21bf
feat: add item keyword entity
Jibaru Jan 25, 2024
8b2bbf5
feat: add item keyword entity test
Jibaru Jan 25, 2024
c0f2193
feat: add item keyword repository interface
Jibaru Jan 25, 2024
00e8019
feat: add gorm item repository
Jibaru Jan 25, 2024
26fbfee
feat: add gorm item repository test
Jibaru Jan 25, 2024
dc1660e
feat: add gorm item keyword repository
Jibaru Jan 25, 2024
ddcd8a1
feat: add gorm item keyword repository test
Jibaru Jan 25, 2024
7e760b9
feat: add stub item repository
Jibaru Jan 25, 2024
522976e
feat: add stub item keyword repository
Jibaru Jan 25, 2024
804e29b
feat: update asset repository interface
Jibaru Jan 25, 2024
5403926
feat: update gorm asset repository
Jibaru Jan 25, 2024
4a5f78a
feat: update gorm asset repository test
Jibaru Jan 25, 2024
dbad023
feat: update stub asset repository
Jibaru Jan 25, 2024
fb40296
feat: update file manager interface
Jibaru Jan 25, 2024
fe177f4
feat: update aws file manager
Jibaru Jan 25, 2024
49898a7
feat: update aws file manager test
Jibaru Jan 25, 2024
90ba9d3
feat: update stub file manager
Jibaru Jan 25, 2024
b8ddeec
feat: update asset service
Jibaru Jan 25, 2024
cd01278
feat: update asset service test
Jibaru Jan 25, 2024
b69c553
feat: add item service
Jibaru Jan 25, 2024
30a755b
feat: add item service test
Jibaru Jan 25, 2024
8939b9e
feat: add create item controller
Jibaru Jan 25, 2024
2a537d4
feat: update http server
Jibaru Jan 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions internal/app/application/services/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ import (
"github.com/jibaru/home-inventory-api/m/internal/app/domain/entities"
"github.com/jibaru/home-inventory-api/m/internal/app/domain/repositories"
"github.com/jibaru/home-inventory-api/m/internal/app/domain/services"
"github.com/stretchr/testify/mock"
"os"
)

type AssetServiceInterface interface {
CreateFromFile(file *os.File, entity entities.Entity) (*entities.Asset, error)
GetUrl(asset *entities.Asset) string
GetByEntity(entity entities.Entity, pageFilter *PageFilter) ([]*entities.Asset, error)
Delete(asset *entities.Asset) error
}

type AssetService struct {
fileManager services.FileManager
assetRepository repositories.AssetRepository
Expand Down Expand Up @@ -65,3 +73,51 @@ func (s *AssetService) GetByEntity(entity entities.Entity, pageFilter *PageFilte

return assets, nil
}

func (s *AssetService) Delete(asset *entities.Asset) error {
err := s.fileManager.Delete(asset.FileID, asset.Extension)
if err != nil {
return err
}

err = s.assetRepository.Delete(asset.ID)
if err != nil {
return err
}

return nil
}

type AssetServiceMock struct {
mock.Mock
}

func (s *AssetServiceMock) CreateFromFile(file *os.File, entity entities.Entity) (*entities.Asset, error) {
args := s.Called(file, entity)

if args.Get(0) == nil {
return nil, args.Error(1)
}

return args.Get(0).(*entities.Asset), args.Error(1)
}

func (s *AssetServiceMock) GetUrl(asset *entities.Asset) string {
args := s.Called(asset)
return args.String(0)
}

func (s *AssetServiceMock) GetByEntity(entity entities.Entity, pageFilter *PageFilter) ([]*entities.Asset, error) {
args := s.Called(entity, pageFilter)

if args.Get(0) == nil {
return nil, args.Error(1)
}

return args.Get(0).([]*entities.Asset), args.Error(1)
}

func (s *AssetServiceMock) Delete(asset *entities.Asset) error {
args := s.Called(asset)
return args.Error(0)
}
67 changes: 67 additions & 0 deletions internal/app/application/services/asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,70 @@ func TestAssetServiceGetByEntityErrorFromAssetRepository(t *testing.T) {
assert.Nil(t, assets)
assetRepository.AssertExpectations(t)
}

func TestAssetServiceDelete(t *testing.T) {
assetRepository := &stub.AssetRepositoryMock{}
fileManager := &serviceStubs.FileManagerMock{}
service := NewAssetService(fileManager, assetRepository)

asset := &entities.Asset{
ID: uuid.NewString(),
Extension: ".png",
FileID: uuid.NewString(),
}

fileManager.On("Delete", asset.FileID, asset.Extension).
Return(nil)
assetRepository.On("Delete", asset.ID).
Return(nil)

err := service.Delete(asset)

assert.NoError(t, err)
assetRepository.AssertExpectations(t)
fileManager.AssertExpectations(t)
}

func TestAssetServiceDeleteErrorFromAssetRepository(t *testing.T) {
assetRepository := &stub.AssetRepositoryMock{}
fileManager := &serviceStubs.FileManagerMock{}
service := NewAssetService(fileManager, assetRepository)

asset := &entities.Asset{
ID: uuid.NewString(),
Extension: ".png",
FileID: uuid.NewString(),
}

fileManager.On("Delete", asset.FileID, asset.Extension).
Return(nil)
assetRepository.On("Delete", asset.ID).
Return(errors.New("repository error"))

err := service.Delete(asset)

assert.Error(t, err)
assetRepository.AssertExpectations(t)
fileManager.AssertExpectations(t)
}

func TestAssetServiceDeleteErrorFromFileManager(t *testing.T) {
assetRepository := &stub.AssetRepositoryMock{}
fileManager := &serviceStubs.FileManagerMock{}
service := NewAssetService(fileManager, assetRepository)

asset := &entities.Asset{
ID: uuid.NewString(),
Extension: ".png",
FileID: uuid.NewString(),
}

fileManager.On("Delete", asset.FileID, asset.Extension).
Return(errors.New("file manager error"))

err := service.Delete(asset)

assert.Error(t, err)
assetRepository.AssertExpectations(t)
fileManager.AssertExpectations(t)
}
80 changes: 80 additions & 0 deletions internal/app/application/services/item.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package services

import (
"github.com/jibaru/home-inventory-api/m/internal/app/domain/entities"
"github.com/jibaru/home-inventory-api/m/internal/app/domain/repositories"
"log"
"os"
)

type ItemService struct {
itemRepository repositories.ItemRepository
itemKeywordRepository repositories.ItemKeywordRepository
assetService AssetServiceInterface
}

func NewItemService(
itemRepository repositories.ItemRepository,
itemKeywordRepository repositories.ItemKeywordRepository,
assetService AssetServiceInterface,
) *ItemService {
return &ItemService{
itemRepository,
itemKeywordRepository,
assetService,
}
}

func (s *ItemService) Create(
sku string,
name string,
description *string,
unit string,
userID string,
keywords []string,
imageFile *os.File,
) (*entities.Item, error) {
item, err := entities.NewItem(sku, name, description, unit, userID)
if err != nil {
return nil, err
}

var itemKeywords []*entities.ItemKeyword
for _, keyword := range keywords {
itemKeyword, err := entities.NewItemKeyword(item.ID, keyword)
if err != nil {
return nil, err
}

itemKeywords = append(itemKeywords, itemKeyword)
}

asset, err := s.assetService.CreateFromFile(imageFile, item)
if err != nil {
return nil, err
}

err = s.itemRepository.Create(item)
if err != nil {
go func() {
err := s.assetService.Delete(asset)
if err != nil {
log.Println(err)
}
}()
return nil, err
}

err = s.itemKeywordRepository.CreateMany(itemKeywords)
if err != nil {
go func() {
err := s.assetService.Delete(asset)
if err != nil {
log.Println(err)
}
}()
return nil, err
}

return item, nil
}
Loading
Loading