diff --git a/backend/api/items.go b/backend/api/items.go index 80b8cee..eac054c 100644 --- a/backend/api/items.go +++ b/backend/api/items.go @@ -299,3 +299,65 @@ func (s *Server) GetAllItems(c echo.Context, params autogen.GetAllItemsParams) e return nil } + +// (GET /items/incoherent) +func (s *Server) GetAllIncoherentItems(c echo.Context, params autogen.GetAllIncoherentItemsParams) error { + // Get account from cookie + account, err := MustGetAdmin(c) + if err != nil { + return nil + } + + state := "" + categoryId := "" + name := "" + if params.State != nil { + state = string(*params.State) + } + if params.CategoryId != nil { + categoryId = params.CategoryId.String() + } + if params.Name != nil { + name = string(*params.Name) + } + + count, err := s.DBackend.CountIncoherentItems(c.Request().Context(), categoryId, state, name) + if err != nil { + logrus.Error(err) + return Error500(c) + } + + // Make sure the last page is not empty + dbpage, page, limit, maxPage := autogen.Pager(params.Page, params.Limit, &count) + + data, err := s.DBackend.GetIncoherentItems(c.Request().Context(), dbpage, limit, categoryId, state, name) + if err != nil { + logrus.Error(err) + return Error500(c) + } + + + + var items []autogen.Item + + for _, item := range data { + rp := item.RealPrice(account.PriceRole) + item.DisplayPrice = &rp + + if account.HasPrivileges() { + rp := item.RealPrices() + item.DisplayPrices = &rp + } + + items = append(items, item.Item) + } + + autogen.GetAllIncoherentItems200JSONResponse{ + Items: items, + Page: page, + Limit: limit, + MaxPage: maxPage, + }.VisitGetAllIncoherentItemsResponse(c.Response()) + + return nil +} \ No newline at end of file diff --git a/backend/autogen/bar.gen.go b/backend/autogen/bar.gen.go index be27516..9c5ef07 100644 --- a/backend/autogen/bar.gen.go +++ b/backend/autogen/bar.gen.go @@ -887,6 +887,24 @@ type GetAllItemsParams struct { Fournisseur *Fournisseur `form:"fournisseur,omitempty" json:"fournisseur,omitempty" bson:"fournisseur"` } +// GetAllIncoherentItemsParams defines parameters for GetAllIncoherentItems. +type GetAllIncoherentItemsParams struct { + // Page Page number + Page *uint64 `form:"page,omitempty" json:"page,omitempty" bson:"page"` + + // Limit Number of items per page + Limit *uint64 `form:"limit,omitempty" json:"limit,omitempty" bson:"limit"` + + // State Filter by state + State *ItemState `form:"state,omitempty" json:"state,omitempty" bson:"state"` + + // CategoryId Filter by category + CategoryId *UUID `form:"category_id,omitempty" json:"category_id,omitempty" bson:"category_id"` + + // Name Filter by name + Name *string `form:"name,omitempty" json:"name,omitempty" bson:"name"` +} + // GetRefillsParams defines parameters for GetRefills. type GetRefillsParams struct { // Page Page number @@ -1232,6 +1250,9 @@ type ServerInterface interface { // (GET /items) GetAllItems(ctx echo.Context, params GetAllItemsParams) error + // (GET /items/incoherent) + GetAllIncoherentItems(ctx echo.Context, params GetAllIncoherentItemsParams) error + // (GET /logout) Logout(ctx echo.Context) error @@ -2933,6 +2954,54 @@ func (w *ServerInterfaceWrapper) GetAllItems(ctx echo.Context) error { return err } +// GetAllIncoherentItems converts echo context to params. +func (w *ServerInterfaceWrapper) GetAllIncoherentItems(ctx echo.Context) error { + var err error + + ctx.Set(Admin_authScopes, []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetAllIncoherentItemsParams + // ------------- Optional query parameter "page" ------------- + + err = runtime.BindQueryParameter("form", true, false, "page", ctx.QueryParams(), ¶ms.Page) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter page: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "state" ------------- + + err = runtime.BindQueryParameter("form", true, false, "state", ctx.QueryParams(), ¶ms.State) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter state: %s", err)) + } + + // ------------- Optional query parameter "category_id" ------------- + + err = runtime.BindQueryParameter("form", true, false, "category_id", ctx.QueryParams(), ¶ms.CategoryId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter category_id: %s", err)) + } + + // ------------- Optional query parameter "name" ------------- + + err = runtime.BindQueryParameter("form", true, false, "name", ctx.QueryParams(), ¶ms.Name) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter name: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetAllIncoherentItems(ctx, params) + return err +} + // Logout converts echo context to params. func (w *ServerInterfaceWrapper) Logout(ctx echo.Context) error { var err error @@ -3221,6 +3290,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.PATCH(baseURL+"/deleted/transactions/:transaction_id", wrapper.RestoreDeletedTransaction) router.POST(baseURL+"/import/accounts", wrapper.ImportAccounts) router.GET(baseURL+"/items", wrapper.GetAllItems) + router.GET(baseURL+"/items/incoherent", wrapper.GetAllIncoherentItems) router.GET(baseURL+"/logout", wrapper.Logout) router.GET(baseURL+"/refills", wrapper.GetRefills) router.GET(baseURL+"/restocks", wrapper.GetRestocks) @@ -7325,6 +7395,46 @@ func (response GetAllItems500JSONResponse) VisitGetAllItemsResponse(w http.Respo return json.NewEncoder(w).Encode(response) } +type GetAllIncoherentItemsRequestObject struct { + Params GetAllIncoherentItemsParams `bson:"params"` +} + +type GetAllIncoherentItemsResponseObject interface { + VisitGetAllIncoherentItemsResponse(w http.ResponseWriter) error +} + +type GetAllIncoherentItems200JSONResponse struct { + Items []Item `json:"items" bson:"items"` + Limit uint64 `json:"limit" bson:"limit"` + MaxPage uint64 `json:"max_page" bson:"max_page"` + Page uint64 `json:"page" bson:"page"` +} + +func (response GetAllIncoherentItems200JSONResponse) VisitGetAllIncoherentItemsResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type GetAllIncoherentItems403JSONResponse HTTPError + +func (response GetAllIncoherentItems403JSONResponse) VisitGetAllIncoherentItemsResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + +type GetAllIncoherentItems500JSONResponse HTTPError + +func (response GetAllIncoherentItems500JSONResponse) VisitGetAllIncoherentItemsResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(500) + + return json.NewEncoder(w).Encode(response) +} + type LogoutRequestObject struct { } @@ -7912,6 +8022,9 @@ type StrictServerInterface interface { // (GET /items) GetAllItems(ctx context.Context, request GetAllItemsRequestObject) (GetAllItemsResponseObject, error) + // (GET /items/incoherent) + GetAllIncoherentItems(ctx context.Context, request GetAllIncoherentItemsRequestObject) (GetAllIncoherentItemsResponseObject, error) + // (GET /logout) Logout(ctx context.Context, request LogoutRequestObject) (LogoutResponseObject, error) @@ -9998,6 +10111,31 @@ func (sh *strictHandler) GetAllItems(ctx echo.Context, params GetAllItemsParams) return nil } +// GetAllIncoherentItems operation middleware +func (sh *strictHandler) GetAllIncoherentItems(ctx echo.Context, params GetAllIncoherentItemsParams) error { + var request GetAllIncoherentItemsRequestObject + + request.Params = params + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.GetAllIncoherentItems(ctx.Request().Context(), request.(GetAllIncoherentItemsRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "GetAllIncoherentItems") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(GetAllIncoherentItemsResponseObject); ok { + return validResponse.VisitGetAllIncoherentItemsResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + // Logout operation middleware func (sh *strictHandler) Logout(ctx echo.Context) error { var request LogoutRequestObject @@ -10178,134 +10316,135 @@ func (sh *strictHandler) GetTransactionsItems(ctx echo.Context, params GetTransa // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "+fOX5/8LAAD//wrNSI3ApQEA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/backend/internal/db/database.go b/backend/internal/db/database.go index 51071fc..9e2458c 100644 --- a/backend/internal/db/database.go +++ b/backend/internal/db/database.go @@ -163,7 +163,9 @@ type DBackend interface { GetRefills(ctx context.Context, account string, page uint64, size uint64, startAt, endAt uint64) ([]*models.Refill, error) CountRefills(ctx context.Context, account string, startAt, endAt uint64) (uint64, error) GetItems(ctx context.Context, categoryID string, page, size uint64, state string, name string, fournisseur string) ([]*models.Item, error) + GetIncoherentItems(ctx context.Context, page, size uint64, categoryID string, state string, name string) ([]*models.Item, error) CountItems(ctx context.Context, categoryID string, state string, name string, fournisseur string) (uint64, error) + CountIncoherentItems(ctx context.Context, categoryID string, state string, name string) (uint64, error) GetAllRefills(ctx context.Context, page uint64, size uint64, startAt, endAt uint64) ([]*models.Refill, error) CountAllRefills(ctx context.Context, startAt, endAt uint64) (uint64, error) diff --git a/backend/internal/db/mongo/item_misc.go b/backend/internal/db/mongo/item_misc.go index fa61183..24099e4 100644 --- a/backend/internal/db/mongo/item_misc.go +++ b/backend/internal/db/mongo/item_misc.go @@ -88,6 +88,99 @@ func (b *Backend) GetItems(ctx context.Context, categoryID string, page, size ui return items, nil } +func (b *Backend) GetIncoherentItems(ctx context.Context, page, size uint64, categoryID string, state string, name string) ([]*models.Item, error) { + ctx, cancel := b.TimeoutContext(ctx) + defer cancel() + + var items []*models.Item + + filter := bson.M{ + "$and": []bson.M{ + { + "deleted_at": nil, + }, + { + "$or": []bson.M{ + { + "$and": []bson.M{ + { + "amount_left": bson.M{ + "$gt": 0, + }, + }, + { + "state": bson.M{ + "$ne": "buyable", + }, + }, + }, + }, + {"prices.ceten": 0}, + {"prices.coutant": 0}, + {"prices.externe": 0}, + {"prices.menu": 0}, + {"prices.privilegies": 0}, + {"prices.staff_bar": 0}, + }, + }, + }, + } + if state != "" { + filter["state"] = state + if state == string(autogen.ItemBuyable) { + // Get seconds since day start + t := time.Since(time.Now().Truncate(24 * time.Hour)).Seconds() + // available_from <= t <= available_until or (available_from == nil && available_until == nil) + filter["$and"] = []bson.M{ + { + "$or": []bson.M{ + { + "available_from": bson.M{ + "$lte": t, + }, + }, + { + "available_from": nil, + }, + }, + }, + { + "$or": []bson.M{ + { + "available_until": bson.M{ + "$gte": t, + }, + }, + { + "available_until": nil, + }, + }, + }, + } + } + } + if categoryID != "" { + filter["category_id"] = uuid.MustParse(categoryID) + } + if name != "" { + filter["name"] = bson.M{ + "$regex": name, + "$options": "i", + } + } + + cursor, err := b.db.Collection(ItemsCollection).Find(ctx, filter, options.Find().SetSkip(int64(page*size)).SetLimit(int64(size))) + if err != nil { + return nil, err + } + + if err := cursor.All(ctx, &items); err != nil { + return nil, err + } + + return items, nil +} + func (b *Backend) CountItems(ctx context.Context, categoryID string, state string, name string, fournisseur string) (uint64, error) { ctx, cancel := b.TimeoutContext(ctx) defer cancel() @@ -156,3 +249,89 @@ func (b *Backend) CountItems(ctx context.Context, categoryID string, state strin return uint64(count), nil } + +func (b *Backend) CountIncoherentItems(ctx context.Context, categoryID string, state string, name string) (uint64, error) { + ctx, cancel := b.TimeoutContext(ctx) + defer cancel() + + filter := bson.M{ + "$and": []bson.M{ + { + "deleted_at": nil, + }, + { + "$or": []bson.M{ + { + "$and": []bson.M{ + { + "amount_left": bson.M{ + "$gt": 0, + }, + }, + { + "state": bson.M{ + "$ne": "buyable", + }, + }, + }, + }, + {"prices.ceten": 0}, + {"prices.coutant": 0}, + {"prices.externe": 0}, + {"prices.menu": 0}, + {"prices.privilegies": 0}, + {"prices.staff_bar": 0}, + }, + }, + }, + } + + if state != "" { + filter["state"] = state + if state == string(autogen.ItemBuyable) { + t := time.Since(time.Now().Truncate(24 * time.Hour)).Seconds() + filter["$and"] = []bson.M{ + { + "$or": []bson.M{ + { + "available_from": bson.M{ + "$lte": t, + }, + }, + { + "available_from": nil, + }, + }, + }, + { + "$or": []bson.M{ + { + "available_until": bson.M{ + "$gte": t, + }, + }, + { + "available_until": nil, + }, + }, + }, + } + } + } + if categoryID != "" { + filter["category_id"] = uuid.MustParse(categoryID) + } + if name != "" { + filter["name"] = bson.M{ + "$regex": name, + "$options": "i", + } + } + + count, err := b.db.Collection(ItemsCollection).CountDocuments(ctx, filter) + if err != nil { + return 0, err + } + + return uint64(count), nil +} diff --git a/bar.openapi.yml b/bar.openapi.yml index 0fa4af3..25fcd1f 100644 --- a/bar.openapi.yml +++ b/bar.openapi.yml @@ -2442,6 +2442,86 @@ paths: - admin_auth: [] tags: - items + /items/incoherent: + get: + description: (admin) Get all incoherent items with filters and pagination + operationId: getAllIncoherentItems + parameters: + - name: page + in: query + description: Page number + required: false + schema: + type: integer + format: uint64 + - name: limit + in: query + description: Number of items per page + required: false + schema: + type: integer + format: uint64 + - name: state + in: query + description: Filter by state + required: false + schema: + type: string + $ref: "#/components/schemas/ItemState" + - name: category_id + in: query + description: Filter by category + required: false + schema: + $ref: "#/components/schemas/UUID" + - name: name + in: query + description: Filter by name + required: false + schema: + type: string + responses: + "200": + description: "" + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + $ref: "#/components/schemas/Item" + page: + type: integer + format: uint64 + limit: + type: integer + format: uint64 + max_page: + type: integer + format: uint64 + required: + - items + - page + - limit + - max_page + "403": + description: "Forbidden" + content: + application/json: + schema: + $ref: "#/components/schemas/HTTPError" + "500": + description: "Internal server error" + content: + application/json: + schema: + $ref: "#/components/schemas/HTTPError" + security: + - admin_auth: [] + tags: + - items /categories/{category_id}/items: get: description: Get all items of a category diff --git a/frontend/src/lib/api/api.ts b/frontend/src/lib/api/api.ts index 2156800..1646f21 100644 --- a/frontend/src/lib/api/api.ts +++ b/frontend/src/lib/api/api.ts @@ -6825,6 +6825,62 @@ export class DeletedApi extends BaseAPI { */ export const ItemsApiAxiosParamCreator = function (configuration?: Configuration) { return { + /** + * (admin) Get all incoherent items with filters and pagination + * @param {number} [page] Page number + * @param {number} [limit] Number of items per page + * @param {ItemState} [state] Filter by state + * @param {string} [categoryId] Filter by category + * @param {string} [name] Filter by name + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAllIncoherentItems: async (page?: number, limit?: number, state?: ItemState, categoryId?: string, name?: string, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/items/incoherent`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication admin_auth required + + if (page !== undefined) { + localVarQueryParameter['page'] = page; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (state !== undefined) { + localVarQueryParameter['state'] = state; + } + + if (categoryId !== undefined) { + localVarQueryParameter['category_id'] = categoryId; + } + + if (name !== undefined) { + localVarQueryParameter['name'] = name; + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * (admin) Get all items with filters and pagination * @param {number} [page] Page number @@ -7110,6 +7166,20 @@ export const ItemsApiAxiosParamCreator = function (configuration?: Configuration export const ItemsApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = ItemsApiAxiosParamCreator(configuration) return { + /** + * (admin) Get all incoherent items with filters and pagination + * @param {number} [page] Page number + * @param {number} [limit] Number of items per page + * @param {ItemState} [state] Filter by state + * @param {string} [categoryId] Filter by category + * @param {string} [name] Filter by name + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getAllIncoherentItems(page?: number, limit?: number, state?: ItemState, categoryId?: string, name?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getAllIncoherentItems(page, limit, state, categoryId, name, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * (admin) Get all items with filters and pagination * @param {number} [page] Page number @@ -7193,6 +7263,19 @@ export const ItemsApiFp = function(configuration?: Configuration) { export const ItemsApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = ItemsApiFp(configuration) return { + /** + * (admin) Get all incoherent items with filters and pagination + * @param {number} [page] Page number + * @param {number} [limit] Number of items per page + * @param {ItemState} [state] Filter by state + * @param {string} [categoryId] Filter by category + * @param {string} [name] Filter by name + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAllIncoherentItems(page?: number, limit?: number, state?: ItemState, categoryId?: string, name?: string, options?: any): AxiosPromise { + return localVarFp.getAllIncoherentItems(page, limit, state, categoryId, name, options).then((request) => request(axios, basePath)); + }, /** * (admin) Get all items with filters and pagination * @param {number} [page] Page number @@ -7270,6 +7353,21 @@ export const ItemsApiFactory = function (configuration?: Configuration, basePath * @extends {BaseAPI} */ export class ItemsApi extends BaseAPI { + /** + * (admin) Get all incoherent items with filters and pagination + * @param {number} [page] Page number + * @param {number} [limit] Number of items per page + * @param {ItemState} [state] Filter by state + * @param {string} [categoryId] Filter by category + * @param {string} [name] Filter by name + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ItemsApi + */ + public getAllIncoherentItems(page?: number, limit?: number, state?: ItemState, categoryId?: string, name?: string, options?: AxiosRequestConfig) { + return ItemsApiFp(this.configuration).getAllIncoherentItems(page, limit, state, categoryId, name, options).then((request) => request(this.axios, this.basePath)); + } + /** * (admin) Get all items with filters and pagination * @param {number} [page] Page number diff --git a/frontend/src/routes/panel/products/fournisseur/+page.svelte b/frontend/src/routes/panel/products/fournisseur/+page.svelte index 1ca0f20..5eb2057 100644 --- a/frontend/src/routes/panel/products/fournisseur/+page.svelte +++ b/frontend/src/routes/panel/products/fournisseur/+page.svelte @@ -6,7 +6,7 @@ ItemPrices, UpdateItem, AccountPriceRole, - RestockType + Fournisseur } from '$lib/api'; import ConfirmationPopup from '$lib/components/confirmationPopup.svelte'; import { api } from '$lib/config/config'; @@ -61,7 +61,7 @@ let rebounceTimeout: number | null = null; - let searchFournisseur: RestockType | undefined = undefined; + let searchFournisseur: Fournisseur | undefined = undefined; let searchCategory: string | undefined = undefined; let searchName: string | undefined = undefined; diff --git a/frontend/src/routes/panel/products/incoherants/+page.svelte b/frontend/src/routes/panel/products/incoherants/+page.svelte index e91deda..3bd63e9 100644 --- a/frontend/src/routes/panel/products/incoherants/+page.svelte +++ b/frontend/src/routes/panel/products/incoherants/+page.svelte @@ -76,7 +76,7 @@ function reloadItems() { itemsApi() - .getAllItems(page, itemsPerPage, searchState, searchCategory, searchName, undefined, { + .getAllIncoherentItems(page, itemsPerPage, searchState, searchCategory, searchName, { withCredentials: true }) .then((res) => { @@ -84,7 +84,6 @@ page = res.data.page ?? 0; itemsPerPage = res.data.limit ?? 0; items = res.data.items ?? []; - items = items.filter(item => item.amount_left > 0 && item.state !== 'buyable'); }); }