diff --git a/backend/internal/domain/models.go b/backend/internal/domain/models.go index 8430175..be0628a 100644 --- a/backend/internal/domain/models.go +++ b/backend/internal/domain/models.go @@ -71,9 +71,70 @@ type InventoryItem struct { UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } -// InventoryFilter allows filtering by expiration window. +// InventoryFilter allows filtering by expiration window with pagination. type InventoryFilter struct { ExpiringBefore *time.Time + SellerID *uuid.UUID + Limit int + Offset int +} + +// InventoryPage wraps paginated inventory results. +type InventoryPage struct { + Items []InventoryItem `json:"items"` + Total int64 `json:"total"` + Page int `json:"page"` + PageSize int `json:"page_size"` +} + +// ProductFilter captures product listing constraints. +type ProductFilter struct { + SellerID *uuid.UUID + Category string + Search string + Limit int + Offset int +} + +// ProductPage wraps paginated product results. +type ProductPage struct { + Products []Product `json:"products"` + Total int64 `json:"total"` + Page int `json:"page"` + PageSize int `json:"page_size"` +} + +// CompanyFilter captures company listing constraints. +type CompanyFilter struct { + Role string + Search string + Limit int + Offset int +} + +// CompanyPage wraps paginated company results. +type CompanyPage struct { + Companies []Company `json:"companies"` + Total int64 `json:"total"` + Page int `json:"page"` + PageSize int `json:"page_size"` +} + +// OrderFilter captures order listing constraints. +type OrderFilter struct { + BuyerID *uuid.UUID + SellerID *uuid.UUID + Status OrderStatus + Limit int + Offset int +} + +// OrderPage wraps paginated order results. +type OrderPage struct { + Orders []Order `json:"orders"` + Total int64 `json:"total"` + Page int `json:"page"` + PageSize int `json:"page_size"` } // InventoryAdjustment records manual stock corrections. diff --git a/backend/internal/http/handler/company_handler.go b/backend/internal/http/handler/company_handler.go index 618481b..f199112 100644 --- a/backend/internal/http/handler/company_handler.go +++ b/backend/internal/http/handler/company_handler.go @@ -47,12 +47,18 @@ func (h *Handler) CreateCompany(w http.ResponseWriter, r *http.Request) { // @Success 200 {array} domain.Company // @Router /api/v1/companies [get] func (h *Handler) ListCompanies(w http.ResponseWriter, r *http.Request) { - companies, err := h.svc.ListCompanies(r.Context()) + page, pageSize := parsePagination(r) + filter := domain.CompanyFilter{ + Role: r.URL.Query().Get("role"), + Search: r.URL.Query().Get("search"), + } + + result, err := h.svc.ListCompanies(r.Context(), filter, page, pageSize) if err != nil { writeError(w, http.StatusInternalServerError, err) return } - writeJSON(w, http.StatusOK, companies) + writeJSON(w, http.StatusOK, result) } // GetCompany godoc diff --git a/backend/internal/http/handler/handler_test.go b/backend/internal/http/handler/handler_test.go index 070b7b8..8a48d31 100644 --- a/backend/internal/http/handler/handler_test.go +++ b/backend/internal/http/handler/handler_test.go @@ -42,8 +42,8 @@ func (m *MockRepository) CreateCompany(ctx context.Context, company *domain.Comp return nil } -func (m *MockRepository) ListCompanies(ctx context.Context) ([]domain.Company, error) { - return m.companies, nil +func (m *MockRepository) ListCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.Company, int64, error) { + return m.companies, int64(len(m.companies)), nil } func (m *MockRepository) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) { @@ -85,8 +85,8 @@ func (m *MockRepository) CreateProduct(ctx context.Context, product *domain.Prod return nil } -func (m *MockRepository) ListProducts(ctx context.Context) ([]domain.Product, error) { - return m.products, nil +func (m *MockRepository) ListProducts(ctx context.Context, filter domain.ProductFilter) ([]domain.Product, int64, error) { + return m.products, int64(len(m.products)), nil } func (m *MockRepository) GetProduct(ctx context.Context, id uuid.UUID) (*domain.Product, error) { @@ -123,8 +123,8 @@ func (m *MockRepository) AdjustInventory(ctx context.Context, productID uuid.UUI return &domain.InventoryItem{}, nil } -func (m *MockRepository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, error) { - return []domain.InventoryItem{}, nil +func (m *MockRepository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, int64, error) { + return []domain.InventoryItem{}, 0, nil } func (m *MockRepository) CreateOrder(ctx context.Context, order *domain.Order) error { @@ -134,8 +134,8 @@ func (m *MockRepository) CreateOrder(ctx context.Context, order *domain.Order) e return nil } -func (m *MockRepository) ListOrders(ctx context.Context) ([]domain.Order, error) { - return m.orders, nil +func (m *MockRepository) ListOrders(ctx context.Context, filter domain.OrderFilter) ([]domain.Order, int64, error) { + return m.orders, int64(len(m.orders)), nil } func (m *MockRepository) GetOrder(ctx context.Context, id uuid.UUID) (*domain.Order, error) { @@ -259,10 +259,10 @@ func TestListProducts(t *testing.T) { t.Errorf("expected status %d, got %d", http.StatusOK, rec.Code) } - // Should return empty array + // Should return page with empty products array body := strings.TrimSpace(rec.Body.String()) - if body != "[]" { - t.Errorf("expected empty array, got %s", body) + if !strings.Contains(body, `"products":[]`) || !strings.Contains(body, `"total":0`) { + t.Errorf("expected paginated response with empty products, got %s", body) } } diff --git a/backend/internal/http/handler/order_handler.go b/backend/internal/http/handler/order_handler.go index ba080dd..27b3e4d 100644 --- a/backend/internal/http/handler/order_handler.go +++ b/backend/internal/http/handler/order_handler.go @@ -51,13 +51,16 @@ func (h *Handler) CreateOrder(w http.ResponseWriter, r *http.Request) { // @Success 200 {array} domain.Order // @Router /api/v1/orders [get] func (h *Handler) ListOrders(w http.ResponseWriter, r *http.Request) { - orders, err := h.svc.ListOrders(r.Context()) + page, pageSize := parsePagination(r) + filter := domain.OrderFilter{} + + result, err := h.svc.ListOrders(r.Context(), filter, page, pageSize) if err != nil { writeError(w, http.StatusInternalServerError, err) return } - writeJSON(w, http.StatusOK, orders) + writeJSON(w, http.StatusOK, result) } // GetOrder godoc diff --git a/backend/internal/http/handler/product_handler.go b/backend/internal/http/handler/product_handler.go index a6b16db..7e58abc 100644 --- a/backend/internal/http/handler/product_handler.go +++ b/backend/internal/http/handler/product_handler.go @@ -49,12 +49,17 @@ func (h *Handler) CreateProduct(w http.ResponseWriter, r *http.Request) { // @Success 200 {array} domain.Product // @Router /api/v1/products [get] func (h *Handler) ListProducts(w http.ResponseWriter, r *http.Request) { - products, err := h.svc.ListProducts(r.Context()) + page, pageSize := parsePagination(r) + filter := domain.ProductFilter{ + Search: r.URL.Query().Get("search"), + } + + result, err := h.svc.ListProducts(r.Context(), filter, page, pageSize) if err != nil { writeError(w, http.StatusInternalServerError, err) return } - writeJSON(w, http.StatusOK, products) + writeJSON(w, http.StatusOK, result) } // GetProduct godoc @@ -174,6 +179,7 @@ func (h *Handler) DeleteProduct(w http.ResponseWriter, r *http.Request) { // @Router /api/v1/inventory [get] // ListInventory exposes stock with expiring batch filters. func (h *Handler) ListInventory(w http.ResponseWriter, r *http.Request) { + page, pageSize := parsePagination(r) var filter domain.InventoryFilter if days := r.URL.Query().Get("expires_in_days"); days != "" { n, err := strconv.Atoi(days) @@ -185,13 +191,13 @@ func (h *Handler) ListInventory(w http.ResponseWriter, r *http.Request) { filter.ExpiringBefore = &expires } - inventory, err := h.svc.ListInventory(r.Context(), filter) + result, err := h.svc.ListInventory(r.Context(), filter, page, pageSize) if err != nil { writeError(w, http.StatusInternalServerError, err) return } - writeJSON(w, http.StatusOK, inventory) + writeJSON(w, http.StatusOK, result) } // AdjustInventory godoc diff --git a/backend/internal/repository/postgres/postgres.go b/backend/internal/repository/postgres/postgres.go index 5cc534d..4ac8805 100644 --- a/backend/internal/repository/postgres/postgres.go +++ b/backend/internal/repository/postgres/postgres.go @@ -35,13 +35,41 @@ VALUES (:id, :role, :cnpj, :corporate_name, :license_number, :is_verified, :crea return err } -func (r *Repository) ListCompanies(ctx context.Context) ([]domain.Company, error) { - var companies []domain.Company - query := `SELECT id, role, cnpj, corporate_name, license_number, is_verified, created_at, updated_at FROM companies ORDER BY created_at DESC` - if err := r.db.SelectContext(ctx, &companies, query); err != nil { - return nil, err +func (r *Repository) ListCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.Company, int64, error) { + baseQuery := `FROM companies` + var args []any + var clauses []string + + if filter.Role != "" { + clauses = append(clauses, fmt.Sprintf("role = $%d", len(args)+1)) + args = append(args, filter.Role) } - return companies, nil + if filter.Search != "" { + clauses = append(clauses, fmt.Sprintf("(corporate_name ILIKE $%d OR cnpj ILIKE $%d)", len(args)+1, len(args)+1)) + args = append(args, "%"+filter.Search+"%") + } + + where := "" + if len(clauses) > 0 { + where = " WHERE " + strings.Join(clauses, " AND ") + } + + var total int64 + if err := r.db.GetContext(ctx, &total, "SELECT count(*) "+baseQuery+where, args...); err != nil { + return nil, 0, err + } + + if filter.Limit <= 0 { + filter.Limit = 20 + } + args = append(args, filter.Limit, filter.Offset) + listQuery := fmt.Sprintf("SELECT id, role, cnpj, corporate_name, license_number, is_verified, created_at, updated_at %s%s ORDER BY created_at DESC LIMIT $%d OFFSET $%d", baseQuery, where, len(args)-1, len(args)) + + var companies []domain.Company + if err := r.db.SelectContext(ctx, &companies, listQuery, args...); err != nil { + return nil, 0, err + } + return companies, total, nil } func (r *Repository) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) { @@ -133,13 +161,41 @@ VALUES (:id, :seller_id, :name, :description, :batch, :expires_at, :price_cents, return err } -func (r *Repository) ListProducts(ctx context.Context) ([]domain.Product, error) { - var products []domain.Product - query := `SELECT id, seller_id, name, description, batch, expires_at, price_cents, stock, created_at, updated_at FROM products ORDER BY created_at DESC` - if err := r.db.SelectContext(ctx, &products, query); err != nil { - return nil, err +func (r *Repository) ListProducts(ctx context.Context, filter domain.ProductFilter) ([]domain.Product, int64, error) { + baseQuery := `FROM products` + var args []any + var clauses []string + + if filter.SellerID != nil { + clauses = append(clauses, fmt.Sprintf("seller_id = $%d", len(args)+1)) + args = append(args, *filter.SellerID) } - return products, nil + if filter.Search != "" { + clauses = append(clauses, fmt.Sprintf("name ILIKE $%d", len(args)+1)) + args = append(args, "%"+filter.Search+"%") + } + + where := "" + if len(clauses) > 0 { + where = " WHERE " + strings.Join(clauses, " AND ") + } + + var total int64 + if err := r.db.GetContext(ctx, &total, "SELECT count(*) "+baseQuery+where, args...); err != nil { + return nil, 0, err + } + + if filter.Limit <= 0 { + filter.Limit = 20 + } + args = append(args, filter.Limit, filter.Offset) + listQuery := fmt.Sprintf("SELECT id, seller_id, name, description, batch, expires_at, price_cents, stock, created_at, updated_at %s%s ORDER BY created_at DESC LIMIT $%d OFFSET $%d", baseQuery, where, len(args)-1, len(args)) + + var products []domain.Product + if err := r.db.SelectContext(ctx, &products, listQuery, args...); err != nil { + return nil, 0, err + } + return products, total, nil } func (r *Repository) GetProduct(ctx context.Context, id uuid.UUID) (*domain.Product, error) { @@ -244,7 +300,40 @@ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)` return tx.Commit() } -func (r *Repository) ListOrders(ctx context.Context) ([]domain.Order, error) { +func (r *Repository) ListOrders(ctx context.Context, filter domain.OrderFilter) ([]domain.Order, int64, error) { + baseQuery := `FROM orders` + var args []any + var clauses []string + + if filter.BuyerID != nil { + clauses = append(clauses, fmt.Sprintf("buyer_id = $%d", len(args)+1)) + args = append(args, *filter.BuyerID) + } + if filter.SellerID != nil { + clauses = append(clauses, fmt.Sprintf("seller_id = $%d", len(args)+1)) + args = append(args, *filter.SellerID) + } + if filter.Status != "" { + clauses = append(clauses, fmt.Sprintf("status = $%d", len(args)+1)) + args = append(args, filter.Status) + } + + where := "" + if len(clauses) > 0 { + where = " WHERE " + strings.Join(clauses, " AND ") + } + + var total int64 + if err := r.db.GetContext(ctx, &total, "SELECT count(*) "+baseQuery+where, args...); err != nil { + return nil, 0, err + } + + if filter.Limit <= 0 { + filter.Limit = 20 + } + args = append(args, filter.Limit, filter.Offset) + listQuery := fmt.Sprintf(`SELECT id, buyer_id, seller_id, status, total_cents, shipping_recipient_name, shipping_street, shipping_number, shipping_complement, shipping_district, shipping_city, shipping_state, shipping_zip_code, shipping_country, created_at, updated_at %s%s ORDER BY created_at DESC LIMIT $%d OFFSET $%d`, baseQuery, where, len(args)-1, len(args)) + var rows []struct { ID uuid.UUID `db:"id"` BuyerID uuid.UUID `db:"buyer_id"` @@ -263,9 +352,9 @@ func (r *Repository) ListOrders(ctx context.Context) ([]domain.Order, error) { CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` } - query := `SELECT id, buyer_id, seller_id, status, total_cents, shipping_recipient_name, shipping_street, shipping_number, shipping_complement, shipping_district, shipping_city, shipping_state, shipping_zip_code, shipping_country, created_at, updated_at FROM orders ORDER BY created_at DESC` - if err := r.db.SelectContext(ctx, &rows, query); err != nil { - return nil, err + + if err := r.db.SelectContext(ctx, &rows, listQuery, args...); err != nil { + return nil, 0, err } orders := make([]domain.Order, 0, len(rows)) @@ -273,7 +362,7 @@ func (r *Repository) ListOrders(ctx context.Context) ([]domain.Order, error) { for _, row := range rows { var items []domain.OrderItem if err := r.db.SelectContext(ctx, &items, itemQuery, row.ID); err != nil { - return nil, err + return nil, 0, err } orders = append(orders, domain.Order{ ID: row.ID, @@ -297,7 +386,7 @@ func (r *Repository) ListOrders(ctx context.Context) ([]domain.Order, error) { UpdatedAt: row.UpdatedAt, }) } - return orders, nil + return orders, total, nil } func (r *Repository) GetOrder(ctx context.Context, id uuid.UUID) (*domain.Order, error) { @@ -480,25 +569,40 @@ func (r *Repository) AdjustInventory(ctx context.Context, productID uuid.UUID, d }, nil } -func (r *Repository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, error) { +func (r *Repository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, int64, error) { + baseQuery := `FROM products` args := []any{} clauses := []string{} if filter.ExpiringBefore != nil { clauses = append(clauses, fmt.Sprintf("expires_at <= $%d", len(args)+1)) args = append(args, *filter.ExpiringBefore) } + if filter.SellerID != nil { + clauses = append(clauses, fmt.Sprintf("seller_id = $%d", len(args)+1)) + args = append(args, *filter.SellerID) + } where := "" if len(clauses) > 0 { where = " WHERE " + strings.Join(clauses, " AND ") } - query := fmt.Sprintf(`SELECT id AS product_id, seller_id, name, batch, expires_at, stock AS quantity, price_cents, updated_at FROM products%s ORDER BY expires_at ASC`, where) - var items []domain.InventoryItem - if err := r.db.SelectContext(ctx, &items, query, args...); err != nil { - return nil, err + var total int64 + if err := r.db.GetContext(ctx, &total, "SELECT count(*) "+baseQuery+where, args...); err != nil { + return nil, 0, err } - return items, nil + + if filter.Limit <= 0 { + filter.Limit = 20 + } + args = append(args, filter.Limit, filter.Offset) + listQuery := fmt.Sprintf(`SELECT id AS product_id, seller_id, name, batch, expires_at, stock AS quantity, price_cents, updated_at %s%s ORDER BY expires_at ASC LIMIT $%d OFFSET $%d`, baseQuery, where, len(args)-1, len(args)) + + var items []domain.InventoryItem + if err := r.db.SelectContext(ctx, &items, listQuery, args...); err != nil { + return nil, 0, err + } + return items, total, nil } func (r *Repository) CreateUser(ctx context.Context, user *domain.User) error { diff --git a/backend/internal/usecase/usecase.go b/backend/internal/usecase/usecase.go index 3076f56..2ef2225 100644 --- a/backend/internal/usecase/usecase.go +++ b/backend/internal/usecase/usecase.go @@ -17,21 +17,22 @@ import ( // Repository defines DB contract for the core entities. type Repository interface { CreateCompany(ctx context.Context, company *domain.Company) error - ListCompanies(ctx context.Context) ([]domain.Company, error) + ListCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.Company, int64, error) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) UpdateCompany(ctx context.Context, company *domain.Company) error DeleteCompany(ctx context.Context, id uuid.UUID) error CreateProduct(ctx context.Context, product *domain.Product) error - ListProducts(ctx context.Context) ([]domain.Product, error) + ListProducts(ctx context.Context, filter domain.ProductFilter) ([]domain.Product, int64, error) GetProduct(ctx context.Context, id uuid.UUID) (*domain.Product, error) UpdateProduct(ctx context.Context, product *domain.Product) error DeleteProduct(ctx context.Context, id uuid.UUID) error AdjustInventory(ctx context.Context, productID uuid.UUID, delta int64, reason string) (*domain.InventoryItem, error) - ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, error) + ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, int64, error) CreateOrder(ctx context.Context, order *domain.Order) error - ListOrders(ctx context.Context) ([]domain.Order, error) + ListOrders(ctx context.Context, filter domain.OrderFilter) ([]domain.Order, int64, error) + GetOrder(ctx context.Context, id uuid.UUID) (*domain.Order, error) UpdateOrderStatus(ctx context.Context, id uuid.UUID, status domain.OrderStatus) error DeleteOrder(ctx context.Context, id uuid.UUID) error @@ -86,8 +87,20 @@ func (s *Service) RegisterCompany(ctx context.Context, company *domain.Company) return s.repo.CreateCompany(ctx, company) } -func (s *Service) ListCompanies(ctx context.Context) ([]domain.Company, error) { - return s.repo.ListCompanies(ctx) +func (s *Service) ListCompanies(ctx context.Context, filter domain.CompanyFilter, page, pageSize int) (*domain.CompanyPage, error) { + if pageSize <= 0 { + pageSize = 20 + } + if page <= 0 { + page = 1 + } + filter.Limit = pageSize + filter.Offset = (page - 1) * pageSize + companies, total, err := s.repo.ListCompanies(ctx, filter) + if err != nil { + return nil, err + } + return &domain.CompanyPage{Companies: companies, Total: total, Page: page, PageSize: pageSize}, nil } func (s *Service) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) { @@ -107,8 +120,20 @@ func (s *Service) RegisterProduct(ctx context.Context, product *domain.Product) return s.repo.CreateProduct(ctx, product) } -func (s *Service) ListProducts(ctx context.Context) ([]domain.Product, error) { - return s.repo.ListProducts(ctx) +func (s *Service) ListProducts(ctx context.Context, filter domain.ProductFilter, page, pageSize int) (*domain.ProductPage, error) { + if pageSize <= 0 { + pageSize = 20 + } + if page <= 0 { + page = 1 + } + filter.Limit = pageSize + filter.Offset = (page - 1) * pageSize + products, total, err := s.repo.ListProducts(ctx, filter) + if err != nil { + return nil, err + } + return &domain.ProductPage{Products: products, Total: total, Page: page, PageSize: pageSize}, nil } func (s *Service) GetProduct(ctx context.Context, id uuid.UUID) (*domain.Product, error) { @@ -123,8 +148,20 @@ func (s *Service) DeleteProduct(ctx context.Context, id uuid.UUID) error { return s.repo.DeleteProduct(ctx, id) } -func (s *Service) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, error) { - return s.repo.ListInventory(ctx, filter) +func (s *Service) ListInventory(ctx context.Context, filter domain.InventoryFilter, page, pageSize int) (*domain.InventoryPage, error) { + if pageSize <= 0 { + pageSize = 20 + } + if page <= 0 { + page = 1 + } + filter.Limit = pageSize + filter.Offset = (page - 1) * pageSize + items, total, err := s.repo.ListInventory(ctx, filter) + if err != nil { + return nil, err + } + return &domain.InventoryPage{Items: items, Total: total, Page: page, PageSize: pageSize}, nil } func (s *Service) AdjustInventory(ctx context.Context, productID uuid.UUID, delta int64, reason string) (*domain.InventoryItem, error) { @@ -137,8 +174,20 @@ func (s *Service) CreateOrder(ctx context.Context, order *domain.Order) error { return s.repo.CreateOrder(ctx, order) } -func (s *Service) ListOrders(ctx context.Context) ([]domain.Order, error) { - return s.repo.ListOrders(ctx) +func (s *Service) ListOrders(ctx context.Context, filter domain.OrderFilter, page, pageSize int) (*domain.OrderPage, error) { + if pageSize <= 0 { + pageSize = 20 + } + if page <= 0 { + page = 1 + } + filter.Limit = pageSize + filter.Offset = (page - 1) * pageSize + orders, total, err := s.repo.ListOrders(ctx, filter) + if err != nil { + return nil, err + } + return &domain.OrderPage{Orders: orders, Total: total, Page: page, PageSize: pageSize}, nil } func (s *Service) GetOrder(ctx context.Context, id uuid.UUID) (*domain.Order, error) { diff --git a/backend/internal/usecase/usecase_test.go b/backend/internal/usecase/usecase_test.go index d93ba3c..49c6122 100644 --- a/backend/internal/usecase/usecase_test.go +++ b/backend/internal/usecase/usecase_test.go @@ -38,8 +38,8 @@ func (m *MockRepository) CreateCompany(ctx context.Context, company *domain.Comp return nil } -func (m *MockRepository) ListCompanies(ctx context.Context) ([]domain.Company, error) { - return m.companies, nil +func (m *MockRepository) ListCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.Company, int64, error) { + return m.companies, int64(len(m.companies)), nil } func (m *MockRepository) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) { @@ -79,8 +79,8 @@ func (m *MockRepository) CreateProduct(ctx context.Context, product *domain.Prod return nil } -func (m *MockRepository) ListProducts(ctx context.Context) ([]domain.Product, error) { - return m.products, nil +func (m *MockRepository) ListProducts(ctx context.Context, filter domain.ProductFilter) ([]domain.Product, int64, error) { + return m.products, int64(len(m.products)), nil } func (m *MockRepository) GetProduct(ctx context.Context, id uuid.UUID) (*domain.Product, error) { @@ -116,8 +116,8 @@ func (m *MockRepository) AdjustInventory(ctx context.Context, productID uuid.UUI return &domain.InventoryItem{ProductID: productID, Quantity: delta}, nil } -func (m *MockRepository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, error) { - return []domain.InventoryItem{}, nil +func (m *MockRepository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, int64, error) { + return []domain.InventoryItem{}, 0, nil } // Order methods @@ -126,8 +126,8 @@ func (m *MockRepository) CreateOrder(ctx context.Context, order *domain.Order) e return nil } -func (m *MockRepository) ListOrders(ctx context.Context) ([]domain.Order, error) { - return m.orders, nil +func (m *MockRepository) ListOrders(ctx context.Context, filter domain.OrderFilter) ([]domain.Order, int64, error) { + return m.orders, int64(len(m.orders)), nil } func (m *MockRepository) GetOrder(ctx context.Context, id uuid.UUID) (*domain.Order, error) { @@ -296,13 +296,13 @@ func TestListCompanies(t *testing.T) { svc, _ := newTestService() ctx := context.Background() - companies, err := svc.ListCompanies(ctx) + page, err := svc.ListCompanies(ctx, domain.CompanyFilter{}, 1, 20) if err != nil { t.Fatalf("failed to list companies: %v", err) } - if len(companies) != 0 { - t.Errorf("expected 0 companies, got %d", len(companies)) + if len(page.Companies) != 0 { + t.Errorf("expected 0 companies, got %d", len(page.Companies)) } } @@ -359,13 +359,13 @@ func TestListProducts(t *testing.T) { svc, _ := newTestService() ctx := context.Background() - products, err := svc.ListProducts(ctx) + page, err := svc.ListProducts(ctx, domain.ProductFilter{}, 1, 20) if err != nil { t.Fatalf("failed to list products: %v", err) } - if len(products) != 0 { - t.Errorf("expected 0 products, got %d", len(products)) + if len(page.Products) != 0 { + t.Errorf("expected 0 products, got %d", len(page.Products)) } } diff --git a/marketplace/vite.config.d.ts b/marketplace/vite.config.d.ts new file mode 100644 index 0000000..340562a --- /dev/null +++ b/marketplace/vite.config.d.ts @@ -0,0 +1,2 @@ +declare const _default: import("vite").UserConfig; +export default _default; diff --git a/marketplace/vite.config.js b/marketplace/vite.config.js new file mode 100644 index 0000000..db2454e --- /dev/null +++ b/marketplace/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +});