mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 21:41:55 +00:00
204 lines
6.1 KiB
Go
204 lines
6.1 KiB
Go
package controller
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitlab.com/mbugroup/lti-api.git/internal/common/exportprogress"
|
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
|
service "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/services"
|
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/validations"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/xuri/excelize/v2"
|
|
)
|
|
|
|
type purchaseServiceStub struct {
|
|
getAllCalls []validation.Query
|
|
}
|
|
|
|
var _ service.PurchaseService = (*purchaseServiceStub)(nil)
|
|
|
|
func (s *purchaseServiceStub) GetAll(_ *fiber.Ctx, params *validation.Query) ([]entity.Purchase, int64, error) {
|
|
callCopy := *params
|
|
s.getAllCalls = append(s.getAllCalls, callCopy)
|
|
|
|
switch params.Page {
|
|
case 1:
|
|
return []entity.Purchase{
|
|
buildPurchaseForControllerTest(1, "PR-00001"),
|
|
buildPurchaseForControllerTest(2, "PR-00002"),
|
|
}, 3, nil
|
|
case 2:
|
|
return []entity.Purchase{
|
|
buildPurchaseForControllerTest(3, "PR-00003"),
|
|
}, 3, nil
|
|
default:
|
|
return []entity.Purchase{}, 3, nil
|
|
}
|
|
}
|
|
|
|
func (s *purchaseServiceStub) GetOne(_ *fiber.Ctx, _ uint) (*entity.Purchase, error) {
|
|
return &entity.Purchase{}, nil
|
|
}
|
|
|
|
func (s *purchaseServiceStub) CreateOne(_ *fiber.Ctx, _ *validation.CreatePurchaseRequest) (*entity.Purchase, error) {
|
|
return &entity.Purchase{}, nil
|
|
}
|
|
|
|
func (s *purchaseServiceStub) ApproveStaffPurchase(_ *fiber.Ctx, _ uint, _ *validation.ApproveStaffPurchaseRequest) (*entity.Purchase, error) {
|
|
return &entity.Purchase{}, nil
|
|
}
|
|
|
|
func (s *purchaseServiceStub) ApproveManagerPurchase(_ *fiber.Ctx, _ uint, _ *validation.ApproveManagerPurchaseRequest) (*entity.Purchase, error) {
|
|
return &entity.Purchase{}, nil
|
|
}
|
|
|
|
func (s *purchaseServiceStub) ReceiveProducts(_ *fiber.Ctx, _ uint, _ *validation.ReceivePurchaseRequest) (*entity.Purchase, error) {
|
|
return &entity.Purchase{}, nil
|
|
}
|
|
|
|
func (s *purchaseServiceStub) DeleteItems(_ *fiber.Ctx, _ uint, _ *validation.DeletePurchaseItemsRequest) (*entity.Purchase, error) {
|
|
return &entity.Purchase{}, nil
|
|
}
|
|
|
|
func (s *purchaseServiceStub) DeletePurchase(_ *fiber.Ctx, _ uint) error {
|
|
return nil
|
|
}
|
|
|
|
func (s *purchaseServiceStub) GetProgressRows(_ *fiber.Ctx, _ *exportprogress.Query) ([]exportprogress.Row, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func TestPurchaseControllerGetAllExportAllIgnoresRequestLimit(t *testing.T) {
|
|
app := fiber.New()
|
|
stub := &purchaseServiceStub{}
|
|
ctrl := NewPurchaseController(stub)
|
|
app.Get("/purchases", ctrl.GetAll)
|
|
|
|
req := httptest.NewRequest(
|
|
http.MethodGet,
|
|
"/purchases?export=excel&type=all&page=9&limit=1&search=po&supplier_id=7&area_id=4&location_id=2&product_category_id=1,2&approval_status=pending&po_date_from=2026-01-01&po_date_to=2026-01-31&created_from=2026-02-01&created_to=2026-02-20",
|
|
nil,
|
|
)
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("unexpected app.Test error: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != fiber.StatusOK {
|
|
t.Fatalf("expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
|
|
contentType := resp.Header.Get("Content-Type")
|
|
if !strings.Contains(contentType, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
|
|
t.Fatalf("unexpected content-type: %s", contentType)
|
|
}
|
|
|
|
disposition := resp.Header.Get("Content-Disposition")
|
|
if !strings.Contains(disposition, "purchases_all_") {
|
|
t.Fatalf("unexpected content-disposition: %s", disposition)
|
|
}
|
|
|
|
if len(stub.getAllCalls) != 2 {
|
|
t.Fatalf("expected 2 GetAll calls, got %d", len(stub.getAllCalls))
|
|
}
|
|
|
|
firstCall := stub.getAllCalls[0]
|
|
secondCall := stub.getAllCalls[1]
|
|
if firstCall.Page != 1 || secondCall.Page != 2 {
|
|
t.Fatalf("expected internal paging page 1 and 2, got %d and %d", firstCall.Page, secondCall.Page)
|
|
}
|
|
if firstCall.Limit != purchaseExcelExportFetchLimit || secondCall.Limit != purchaseExcelExportFetchLimit {
|
|
t.Fatalf("expected internal limit %d, got %d and %d", purchaseExcelExportFetchLimit, firstCall.Limit, secondCall.Limit)
|
|
}
|
|
|
|
if firstCall.Search != "po" ||
|
|
firstCall.SupplierID != 7 ||
|
|
firstCall.AreaID != 4 ||
|
|
firstCall.LocationID != 2 ||
|
|
firstCall.ProductCategoryID != "1,2" ||
|
|
firstCall.ApprovalStatus != "pending" ||
|
|
firstCall.PoDateFrom != "2026-01-01" ||
|
|
firstCall.PoDateTo != "2026-01-31" ||
|
|
firstCall.CreatedFrom != "2026-02-01" ||
|
|
firstCall.CreatedTo != "2026-02-20" {
|
|
t.Fatalf("unexpected forwarded filters: %+v", firstCall)
|
|
}
|
|
|
|
payload, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatalf("failed to read excel payload: %v", err)
|
|
}
|
|
file, err := excelize.OpenReader(bytes.NewReader(payload))
|
|
if err != nil {
|
|
t.Fatalf("failed to parse excel payload: %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
if got, _ := file.GetCellValue(purchaseExportSheetName, "A1"); got != "PR Number" {
|
|
t.Fatalf("expected A1 header to be PR Number, got %q", got)
|
|
}
|
|
if got, _ := file.GetCellValue(purchaseExportSheetName, "A2"); got != "PR-00001" {
|
|
t.Fatalf("expected first row PR-00001, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestPurchaseControllerGetAllKeepsPaginationValidationForNonExportAll(t *testing.T) {
|
|
app := fiber.New()
|
|
stub := &purchaseServiceStub{}
|
|
ctrl := NewPurchaseController(stub)
|
|
app.Get("/purchases", ctrl.GetAll)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/purchases?page=1&limit=0", nil)
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("unexpected app.Test error: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != fiber.StatusBadRequest {
|
|
t.Fatalf("expected status 400, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
func buildPurchaseForControllerTest(id uint, prNumber string) entity.Purchase {
|
|
poNumber := "PO-" + strings.TrimPrefix(prNumber, "PR-")
|
|
poDate := time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC)
|
|
notes := "catatan"
|
|
approvalAction := entity.ApprovalActionApproved
|
|
|
|
return entity.Purchase{
|
|
Id: id,
|
|
PrNumber: prNumber,
|
|
PoNumber: &poNumber,
|
|
PoDate: &poDate,
|
|
Notes: ¬es,
|
|
Supplier: entity.Supplier{
|
|
Id: 10,
|
|
Name: "Supplier A",
|
|
},
|
|
LatestApproval: &entity.Approval{
|
|
Id: 1,
|
|
StepName: "Manager Purchase",
|
|
Action: &approvalAction,
|
|
},
|
|
Items: []entity.PurchaseItem{
|
|
{
|
|
Id: id*10 + 1,
|
|
TotalPrice: 1000000,
|
|
Product: &entity.Product{
|
|
Id: id*100 + 1,
|
|
Name: "Pakan Starter",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|