turash/bugulma/backend/internal/service/organization_service_test.go
Damir Mukimov 000eab4740
Major repository reorganization and missing backend endpoints implementation
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools

Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
  * GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
  * GET /api/v1/users/me/organizations - User organizations
  * POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue

API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules

Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
2025-11-25 06:01:16 +01:00

269 lines
7.7 KiB
Go

package service_test
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"bugulma/backend/internal/domain"
"bugulma/backend/internal/repository"
"bugulma/backend/internal/service"
)
type OrganizationServiceTestSuite struct {
suite.Suite
db *gorm.DB
repo domain.OrganizationRepository
svc *service.OrganizationService
}
func (suite *OrganizationServiceTestSuite) SetupTest() {
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
suite.Require().NoError(err)
// Migrate
err = db.AutoMigrate(&domain.Organization{})
suite.Require().NoError(err)
suite.db = db
suite.repo = repository.NewOrganizationRepository(db)
suite.svc = service.NewOrganizationService(suite.repo, nil) // No graph repo for tests
}
func (suite *OrganizationServiceTestSuite) TearDownTest() {
sqlDB, _ := suite.db.DB()
sqlDB.Close()
}
func (suite *OrganizationServiceTestSuite) TestCreate() {
req := service.CreateOrganizationRequest{
Name: "Test Org",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
org, err := suite.svc.Create(context.Background(), req)
assert.NoError(suite.T(), err)
assert.NotEmpty(suite.T(), org.ID)
assert.Equal(suite.T(), "Test Org", org.Name)
assert.Equal(suite.T(), domain.SubtypeCommercial, org.Subtype)
}
func (suite *OrganizationServiceTestSuite) TestGetByID() {
req := service.CreateOrganizationRequest{
Name: "Test Org",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
created, err := suite.svc.Create(context.Background(), req)
suite.Require().NoError(err)
found, err := suite.svc.GetByID(context.Background(), created.ID)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), created.ID, found.ID)
assert.Equal(suite.T(), "Test Org", found.Name)
}
func (suite *OrganizationServiceTestSuite) TestGetAll() {
req1 := service.CreateOrganizationRequest{
Name: "Org 1",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
req2 := service.CreateOrganizationRequest{
Name: "Org 2",
Sector: "Retail",
Subtype: domain.SubtypeCommercial,
}
_, err := suite.svc.Create(context.Background(), req1)
suite.Require().NoError(err)
_, err = suite.svc.Create(context.Background(), req2)
suite.Require().NoError(err)
orgs, err := suite.svc.GetAll(context.Background())
assert.NoError(suite.T(), err)
assert.Len(suite.T(), orgs, 2)
}
func (suite *OrganizationServiceTestSuite) TestGetBySubtype() {
req1 := service.CreateOrganizationRequest{
Name: "Org 1",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
req2 := service.CreateOrganizationRequest{
Name: "Org 2",
Sector: "Government",
Subtype: domain.SubtypeGovernment,
}
_, err := suite.svc.Create(context.Background(), req1)
suite.Require().NoError(err)
_, err = suite.svc.Create(context.Background(), req2)
suite.Require().NoError(err)
orgs, err := suite.svc.GetBySubtype(context.Background(), domain.SubtypeCommercial)
assert.NoError(suite.T(), err)
assert.Len(suite.T(), orgs, 1)
assert.Equal(suite.T(), "Org 1", orgs[0].Name)
}
func (suite *OrganizationServiceTestSuite) TestGetBySector() {
req1 := service.CreateOrganizationRequest{
Name: "Org 1",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
req2 := service.CreateOrganizationRequest{
Name: "Org 2",
Sector: "Retail",
Subtype: domain.SubtypeCommercial,
}
_, err := suite.svc.Create(context.Background(), req1)
suite.Require().NoError(err)
_, err = suite.svc.Create(context.Background(), req2)
suite.Require().NoError(err)
orgs, err := suite.svc.GetBySector(context.Background(), "Manufacturing")
assert.NoError(suite.T(), err)
assert.Len(suite.T(), orgs, 1)
assert.Equal(suite.T(), "Org 1", orgs[0].Name)
}
func (suite *OrganizationServiceTestSuite) TestUpdate() {
req := service.CreateOrganizationRequest{
Name: "Test Org",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
org, err := suite.svc.Create(context.Background(), req)
suite.Require().NoError(err)
org.Name = "Updated Org"
err = suite.svc.Update(context.Background(), org)
assert.NoError(suite.T(), err)
found, err := suite.svc.GetByID(context.Background(), org.ID)
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), "Updated Org", found.Name)
}
func (suite *OrganizationServiceTestSuite) TestDelete() {
req := service.CreateOrganizationRequest{
Name: "Test Org",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
org, err := suite.svc.Create(context.Background(), req)
suite.Require().NoError(err)
err = suite.svc.Delete(context.Background(), org.ID)
assert.NoError(suite.T(), err)
_, err = suite.svc.GetByID(context.Background(), org.ID)
assert.Error(suite.T(), err)
}
func (suite *OrganizationServiceTestSuite) TestGetByCertification() {
req1 := service.CreateOrganizationRequest{
Name: "Org 1",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
Certifications: []string{"ISO 9001"},
}
req2 := service.CreateOrganizationRequest{
Name: "Org 2",
Sector: "Retail",
Subtype: domain.SubtypeCommercial,
Certifications: []string{"ISO 14001"},
}
_, err := suite.svc.Create(context.Background(), req1)
suite.Require().NoError(err)
_, err = suite.svc.Create(context.Background(), req2)
suite.Require().NoError(err)
orgs, err := suite.svc.GetByCertification(context.Background(), "ISO 9001")
assert.NoError(suite.T(), err)
assert.Len(suite.T(), orgs, 1)
assert.Equal(suite.T(), "Org 1", orgs[0].Name)
}
func (suite *OrganizationServiceTestSuite) TestGetWithinRadius() {
req1 := service.CreateOrganizationRequest{
Name: "Org 1",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
Latitude: 52.5200,
Longitude: 13.4050,
}
req2 := service.CreateOrganizationRequest{
Name: "Org 2",
Sector: "Retail",
Subtype: domain.SubtypeCommercial,
Latitude: 60.0000, // Far away
Longitude: 10.0000,
}
_, err := suite.svc.Create(context.Background(), req1)
suite.Require().NoError(err)
_, err = suite.svc.Create(context.Background(), req2)
suite.Require().NoError(err)
orgs, err := suite.svc.GetWithinRadius(context.Background(), 52.5200, 13.4050, 100.0) // 100km radius
assert.NoError(suite.T(), err)
assert.Len(suite.T(), orgs, 1)
assert.Equal(suite.T(), "Org 1", orgs[0].Name)
}
func (suite *OrganizationServiceTestSuite) TestAddProduct() {
req := service.CreateOrganizationRequest{
Name: "Test Org",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
org, err := suite.svc.Create(context.Background(), req)
suite.Require().NoError(err)
product := domain.ProductJSON{
Name: "Test Product",
Category: "Industrial",
}
err = suite.svc.AddProduct(context.Background(), org.ID, product)
assert.NoError(suite.T(), err)
// Verify product was added
found, err := suite.svc.GetByID(context.Background(), org.ID)
assert.NoError(suite.T(), err)
assert.NotNil(suite.T(), found.SellsProducts)
}
func (suite *OrganizationServiceTestSuite) TestAddService() {
req := service.CreateOrganizationRequest{
Name: "Test Org",
Sector: "Manufacturing",
Subtype: domain.SubtypeCommercial,
}
org, err := suite.svc.Create(context.Background(), req)
suite.Require().NoError(err)
svc := domain.ServiceJSON{
Type: "maintenance",
Domain: "compressors",
}
err = suite.svc.AddService(context.Background(), org.ID, svc)
assert.NoError(suite.T(), err)
// Verify service was added
found, err := suite.svc.GetByID(context.Background(), org.ID)
assert.NoError(suite.T(), err)
assert.NotNil(suite.T(), found.OffersServices)
}
func TestOrganizationServiceTestSuite(t *testing.T) {
suite.Run(t, new(OrganizationServiceTestSuite))
}