diff --git a/frontend/openapi.json b/frontend/openapi.json new file mode 100644 index 0000000..491701e --- /dev/null +++ b/frontend/openapi.json @@ -0,0 +1 @@ +{"openapi":"3.0.1","info":{"title":"Effigenix Fleischerei ERP API","description":"RESTful API for Effigenix Fleischerei ERP System.\n\n## Authentication\n\nAll endpoints (except /api/auth/login and /api/auth/refresh) require JWT authentication.\n\n1. Login via POST /api/auth/login with username and password\n2. Copy the returned access token\n3. Click \"Authorize\" button (top right)\n4. Enter: Bearer \n5. Click \"Authorize\"\n\n## User Management\n\n- **Authentication**: Login, logout, refresh token\n- **User Management**: Create, update, list users (ADMIN only)\n- **Role Management**: Assign roles, lock/unlock users (ADMIN only)\n- **Password Management**: Change password (requires current password)\n\n## Error Handling\n\nAll errors return a consistent error response format:\n\n```json\n{\n \"code\": \"USER_NOT_FOUND\",\n \"message\": \"User with ID 'user-123' not found\",\n \"status\": 404,\n \"timestamp\": \"2026-02-17T12:00:00\",\n \"path\": \"/api/users/user-123\",\n \"validationErrors\": null\n}\n```\n\n## Architecture\n\nBuilt with:\n- Domain-Driven Design (DDD)\n- Clean Architecture (Hexagonal Architecture)\n- Spring Boot 3.2\n- Java 21\n- PostgreSQL\n","contact":{"name":"Effigenix Development Team","url":"https://effigenix.com","email":"dev@effigenix.com"},"license":{"name":"Proprietary","url":"https://effigenix.com/license"},"version":"0.1.0"},"servers":[{"url":"http://localhost:8080","description":"Local Development Server"},{"url":"https://api.effigenix.com","description":"Production Server"}],"tags":[{"name":"Product Categories","description":"Product category management endpoints"},{"name":"User Management","description":"User management endpoints (requires authentication)"},{"name":"Articles","description":"Article management endpoints"},{"name":"Role Management","description":"Role management endpoints (ADMIN only)"},{"name":"Customers","description":"Customer management endpoints"},{"name":"Suppliers","description":"Supplier management endpoints"},{"name":"Authentication","description":"Authentication and session management endpoints"}],"paths":{"/api/users/{id}":{"get":{"tags":["User Management"],"summary":"Get user by ID","description":"Retrieve a single user by their ID. Requires authentication.","operationId":"getUserById","parameters":[{"name":"id","in":"path","description":"User ID","required":true,"schema":{"type":"string"},"example":"user-uuid"}],"responses":{"200":{"description":"User retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"401":{"description":"Authentication required","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"404":{"description":"User not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}},"security":[{"Bearer Authentication":[]}]},"put":{"tags":["User Management"],"summary":"Update user","description":"Update user details (email, branchId). Only provided fields will be updated.","operationId":"updateUser","parameters":[{"name":"id","in":"path","description":"User ID","required":true,"schema":{"type":"string"},"example":"user-uuid"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequest"}}},"required":true},"responses":{"409":{"description":"Email already exists","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"200":{"description":"User updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"401":{"description":"Authentication required","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"404":{"description":"User not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/users/{id}/password":{"put":{"tags":["User Management"],"summary":"Change password","description":"Change user password. Requires current password for verification.","operationId":"changePassword","parameters":[{"name":"id","in":"path","description":"User ID","required":true,"schema":{"type":"string"},"example":"user-uuid"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"400":{"description":"Invalid password"},"401":{"description":"Invalid current password or authentication required"},"404":{"description":"User not found"},"204":{"description":"Password changed successfully"}},"security":[{"Bearer Authentication":[]}]}},"/api/suppliers/{id}":{"get":{"tags":["Suppliers"],"operationId":"getSupplier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Supplier"}}}}},"security":[{"Bearer Authentication":[]}]},"put":{"tags":["Suppliers"],"operationId":"updateSupplier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSupplierRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Supplier"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/customers/{id}":{"get":{"tags":["Customers"],"operationId":"getCustomer","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Customer"}}}}},"security":[{"Bearer Authentication":[]}]},"put":{"tags":["Customers"],"operationId":"updateCustomer","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomerRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Customer"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/customers/{id}/preferences":{"put":{"tags":["Customers"],"operationId":"setPreferences","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPreferencesRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Customer"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/customers/{id}/frame-contract":{"put":{"tags":["Customers"],"operationId":"setFrameContract","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetFrameContractRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Customer"}}}}},"security":[{"Bearer Authentication":[]}]},"delete":{"tags":["Customers"],"operationId":"removeFrameContract","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}},"security":[{"Bearer Authentication":[]}]}},"/api/categories/{id}":{"put":{"tags":["Product Categories"],"operationId":"updateCategory","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProductCategoryRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ProductCategory"}}}}},"security":[{"Bearer Authentication":[]}]},"delete":{"tags":["Product Categories"],"operationId":"deleteCategory","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}},"security":[{"Bearer Authentication":[]}]}},"/api/articles/{id}":{"get":{"tags":["Articles"],"operationId":"getArticle","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Article"}}}}},"security":[{"Bearer Authentication":[]}]},"put":{"tags":["Articles"],"operationId":"updateArticle","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateArticleRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Article"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/articles/{id}/sales-units/{suId}/price":{"put":{"tags":["Articles"],"operationId":"updateSalesUnitPrice","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"suId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSalesUnitPriceRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Article"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/users":{"get":{"tags":["User Management"],"summary":"List all users","description":"Get a list of all users in the system. Requires authentication.","operationId":"listUsers","responses":{"200":{"description":"Users retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"401":{"description":"Authentication required","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserDTO"}}}}}},"security":[{"Bearer Authentication":[]}]},"post":{"tags":["User Management"],"summary":"Create user (ADMIN only)","description":"Create a new user account with specified roles. Requires USER_MANAGEMENT permission.","operationId":"createUser","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRequest"}}},"required":true},"responses":{"400":{"description":"Validation error or invalid password","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"201":{"description":"User created successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"409":{"description":"Username or email already exists","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"403":{"description":"Missing USER_MANAGEMENT permission","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/users/{id}/unlock":{"post":{"tags":["User Management"],"summary":"Unlock user (ADMIN only)","description":"Unlock a user account (allows login). Requires USER_MANAGEMENT permission.","operationId":"unlockUser","parameters":[{"name":"id","in":"path","description":"User ID","required":true,"schema":{"type":"string"},"example":"user-uuid"}],"responses":{"403":{"description":"Missing USER_MANAGEMENT permission","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"200":{"description":"User unlocked successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"401":{"description":"Authentication required","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"404":{"description":"User not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/users/{id}/roles":{"post":{"tags":["User Management"],"summary":"Assign role (ADMIN only)","description":"Assign a role to a user. Requires USER_MANAGEMENT permission.","operationId":"assignRole","parameters":[{"name":"id","in":"path","description":"User ID","required":true,"schema":{"type":"string"},"example":"user-uuid"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignRoleRequest"}}},"required":true},"responses":{"404":{"description":"User or role not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"403":{"description":"Missing USER_MANAGEMENT permission","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"401":{"description":"Authentication required","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"200":{"description":"Role assigned successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/users/{id}/lock":{"post":{"tags":["User Management"],"summary":"Lock user (ADMIN only)","description":"Lock a user account (prevents login). Requires USER_MANAGEMENT permission.","operationId":"lockUser","parameters":[{"name":"id","in":"path","description":"User ID","required":true,"schema":{"type":"string"},"example":"user-uuid"}],"responses":{"200":{"description":"User locked successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"403":{"description":"Missing USER_MANAGEMENT permission","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"401":{"description":"Authentication required","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}},"404":{"description":"User not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/suppliers":{"get":{"tags":["Suppliers"],"operationId":"listSuppliers","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["ACTIVE","INACTIVE"]}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Supplier"}}}}}},"security":[{"Bearer Authentication":[]}]},"post":{"tags":["Suppliers"],"operationId":"createSupplier","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSupplierRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Supplier"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/suppliers/{id}/rating":{"post":{"tags":["Suppliers"],"operationId":"rateSupplier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateSupplierRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Supplier"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/suppliers/{id}/deactivate":{"post":{"tags":["Suppliers"],"operationId":"deactivate","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Supplier"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/suppliers/{id}/certificates":{"post":{"tags":["Suppliers"],"operationId":"addCertificate","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCertificateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Supplier"}}}}},"security":[{"Bearer Authentication":[]}]},"delete":{"tags":["Suppliers"],"operationId":"removeCertificate","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveCertificateRequest"}}},"required":true},"responses":{"200":{"description":"OK"}},"security":[{"Bearer Authentication":[]}]}},"/api/suppliers/{id}/activate":{"post":{"tags":["Suppliers"],"operationId":"activate","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Supplier"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/customers":{"get":{"tags":["Customers"],"operationId":"listCustomers","parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["B2C","B2B"]}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["ACTIVE","INACTIVE"]}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}}}}}},"security":[{"Bearer Authentication":[]}]},"post":{"tags":["Customers"],"operationId":"createCustomer","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Customer"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/customers/{id}/delivery-addresses":{"post":{"tags":["Customers"],"operationId":"addDeliveryAddress","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddDeliveryAddressRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Customer"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/customers/{id}/deactivate":{"post":{"tags":["Customers"],"operationId":"deactivate_1","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Customer"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/customers/{id}/activate":{"post":{"tags":["Customers"],"operationId":"activate_1","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Customer"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/categories":{"get":{"tags":["Product Categories"],"operationId":"listCategories","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductCategory"}}}}}},"security":[{"Bearer Authentication":[]}]},"post":{"tags":["Product Categories"],"operationId":"createCategory","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProductCategoryRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ProductCategory"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/auth/refresh":{"post":{"tags":["Authentication"],"summary":"Refresh access token","description":"Refresh an expired access token using a valid refresh token. Returns new access token and refresh token.","operationId":"refresh","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenRequest"}}},"required":true},"responses":{"401":{"description":"Invalid or expired refresh token","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"200":{"description":"Token refresh successful","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"400":{"description":"Validation error (missing refresh token)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}}}}},"/api/auth/logout":{"post":{"tags":["Authentication"],"summary":"User logout","description":"Invalidate current JWT token. Requires authentication.","operationId":"logout","responses":{"401":{"description":"Invalid or missing authentication token"},"204":{"description":"Logout successful"}}}},"/api/auth/login":{"post":{"tags":["Authentication"],"summary":"User login","description":"Authenticate user with username and password. Returns JWT access token and refresh token.","operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Login successful","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"401":{"description":"Invalid credentials, user locked, or user inactive","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"400":{"description":"Validation error (missing username or password)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}}}}},"/api/articles":{"get":{"tags":["Articles"],"operationId":"listArticles","parameters":[{"name":"categoryId","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["ACTIVE","INACTIVE"]}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Article"}}}}}},"security":[{"Bearer Authentication":[]}]},"post":{"tags":["Articles"],"operationId":"createArticle","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateArticleRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Article"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/articles/{id}/suppliers":{"post":{"tags":["Articles"],"operationId":"assignSupplier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignSupplierRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Article"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/articles/{id}/sales-units":{"post":{"tags":["Articles"],"operationId":"addSalesUnit","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSalesUnitRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Article"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/articles/{id}/deactivate":{"post":{"tags":["Articles"],"operationId":"deactivate_2","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Article"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/articles/{id}/activate":{"post":{"tags":["Articles"],"operationId":"activate_2","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Article"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/roles":{"get":{"tags":["Role Management"],"summary":"List all roles (ADMIN only)","description":"Get a list of all available roles in the system. Requires USER_MANAGEMENT permission.","operationId":"listRoles","responses":{"200":{"description":"Roles retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/RoleDTO"}}}},"403":{"description":"Missing USER_MANAGEMENT permission","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RoleDTO"}}}}},"401":{"description":"Authentication required","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RoleDTO"}}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/users/{id}/roles/{roleName}":{"delete":{"tags":["User Management"],"summary":"Remove role (ADMIN only)","description":"Remove a role from a user. Requires USER_MANAGEMENT permission.","operationId":"removeRole","parameters":[{"name":"id","in":"path","description":"User ID","required":true,"schema":{"type":"string"},"example":"user-uuid"},{"name":"roleName","in":"path","description":"Role name","required":true,"schema":{"type":"string","enum":["ADMIN","PRODUCTION_MANAGER","PRODUCTION_WORKER","QUALITY_MANAGER","QUALITY_INSPECTOR","PROCUREMENT_MANAGER","WAREHOUSE_WORKER","SALES_MANAGER","SALES_STAFF"]},"example":"MANAGER"}],"responses":{"404":{"description":"User or role not found"},"403":{"description":"Missing USER_MANAGEMENT permission"},"204":{"description":"Role removed successfully"},"401":{"description":"Authentication required"}},"security":[{"Bearer Authentication":[]}]}},"/api/customers/{id}/delivery-addresses/{label}":{"delete":{"tags":["Customers"],"operationId":"removeDeliveryAddress","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"label","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}},"security":[{"Bearer Authentication":[]}]}},"/api/articles/{id}/suppliers/{supplierId}":{"delete":{"tags":["Articles"],"operationId":"removeSupplier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"supplierId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}},"security":[{"Bearer Authentication":[]}]}},"/api/articles/{id}/sales-units/{suId}":{"delete":{"tags":["Articles"],"operationId":"removeSalesUnit","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"suId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}},"security":[{"Bearer Authentication":[]}]}}},"components":{"schemas":{"UpdateUserRequest":{"type":"object","properties":{"email":{"type":"string","description":"New email address","example":"newemail@example.com"},"branchId":{"type":"string","description":"New branch ID","example":"BRANCH-002"}},"description":"Request to update user details"},"RoleDTO":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","enum":["ADMIN","PRODUCTION_MANAGER","PRODUCTION_WORKER","QUALITY_MANAGER","QUALITY_INSPECTOR","PROCUREMENT_MANAGER","WAREHOUSE_WORKER","SALES_MANAGER","SALES_STAFF"]},"permissions":{"uniqueItems":true,"type":"array","items":{"type":"string","enum":["RECIPE_READ","RECIPE_WRITE","RECIPE_DELETE","BATCH_READ","BATCH_WRITE","BATCH_COMPLETE","BATCH_DELETE","PRODUCTION_ORDER_READ","PRODUCTION_ORDER_WRITE","PRODUCTION_ORDER_DELETE","HACCP_READ","HACCP_WRITE","TEMPERATURE_LOG_READ","TEMPERATURE_LOG_WRITE","CLEANING_RECORD_READ","CLEANING_RECORD_WRITE","GOODS_INSPECTION_READ","GOODS_INSPECTION_WRITE","STOCK_READ","STOCK_WRITE","STOCK_MOVEMENT_READ","STOCK_MOVEMENT_WRITE","INVENTORY_COUNT_READ","INVENTORY_COUNT_WRITE","PURCHASE_ORDER_READ","PURCHASE_ORDER_WRITE","PURCHASE_ORDER_DELETE","GOODS_RECEIPT_READ","GOODS_RECEIPT_WRITE","SUPPLIER_READ","SUPPLIER_WRITE","SUPPLIER_DELETE","ORDER_READ","ORDER_WRITE","ORDER_DELETE","INVOICE_READ","INVOICE_WRITE","INVOICE_DELETE","CUSTOMER_READ","CUSTOMER_WRITE","CUSTOMER_DELETE","LABEL_READ","LABEL_WRITE","LABEL_PRINT","BRANCH_READ","BRANCH_WRITE","BRANCH_DELETE","USER_READ","USER_WRITE","USER_DELETE","USER_LOCK","USER_UNLOCK","ROLE_READ","ROLE_WRITE","ROLE_ASSIGN","ROLE_REMOVE","REPORT_READ","REPORT_GENERATE","NOTIFICATION_READ","NOTIFICATION_SEND","AUDIT_LOG_READ","SYSTEM_SETTINGS_READ","SYSTEM_SETTINGS_WRITE"]}},"description":{"type":"string"}}},"UserDTO":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"email":{"type":"string"},"roles":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/RoleDTO"}},"branchId":{"type":"string"},"status":{"type":"string","enum":["ACTIVE","INACTIVE","LOCKED"]},"createdAt":{"type":"string","format":"date-time"},"lastLogin":{"type":"string","format":"date-time"}}},"ChangePasswordRequest":{"required":["currentPassword","newPassword"],"type":"object","properties":{"currentPassword":{"type":"string","description":"Current password","example":"OldPass123"},"newPassword":{"maxLength":2147483647,"minLength":8,"type":"string","description":"New password (min 8 characters)","example":"NewSecurePass456"}},"description":"Request to change user password"},"UpdateSupplierRequest":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"contactPerson":{"type":"string"},"street":{"type":"string"},"houseNumber":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"paymentDueDays":{"type":"integer","format":"int32"},"paymentDescription":{"type":"string"}}},"Supplier":{"type":"object"},"UpdateCustomerRequest":{"type":"object","properties":{"name":{"type":"string"},"street":{"type":"string"},"houseNumber":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"contactPerson":{"type":"string"},"paymentDueDays":{"type":"integer","format":"int32"},"paymentDescription":{"type":"string"}}},"Customer":{"type":"object","properties":{"frameContract":{"$ref":"#/components/schemas/ResultCustomerErrorVoid"},"preferences":{"uniqueItems":true,"type":"array","writeOnly":true,"items":{"type":"string","enum":["BIO","REGIONAL","TIERWOHL","HALAL","KOSHER","GLUTENFREI","LAKTOSEFREI"]}}}},"ResultCustomerErrorVoid":{"type":"object","properties":{"failure":{"type":"boolean"},"success":{"type":"boolean"}}},"SetPreferencesRequest":{"required":["preferences"],"type":"object","properties":{"preferences":{"uniqueItems":true,"type":"array","items":{"type":"string","enum":["BIO","REGIONAL","TIERWOHL","HALAL","KOSHER","GLUTENFREI","LAKTOSEFREI"]}}}},"LineItem":{"required":["agreedPrice","articleId"],"type":"object","properties":{"articleId":{"type":"string"},"agreedPrice":{"type":"number"},"agreedQuantity":{"type":"number"},"unit":{"type":"string","enum":["PIECE_FIXED","KG","HUNDRED_GRAM","PIECE_VARIABLE"]}}},"SetFrameContractRequest":{"required":["lineItems","rhythm"],"type":"object","properties":{"validFrom":{"type":"string","format":"date"},"validUntil":{"type":"string","format":"date"},"rhythm":{"type":"string","enum":["DAILY","WEEKLY","BIWEEKLY","MONTHLY","ON_DEMAND"]},"lineItems":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}}}},"UpdateProductCategoryRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"}}},"ProductCategory":{"type":"object"},"UpdateArticleRequest":{"type":"object","properties":{"name":{"type":"string"},"categoryId":{"type":"string"}}},"Article":{"type":"object"},"UpdateSalesUnitPriceRequest":{"required":["price"],"type":"object","properties":{"price":{"type":"number"}}},"CreateUserRequest":{"required":["email","password","roleNames","username"],"type":"object","properties":{"username":{"maxLength":50,"minLength":3,"type":"string","description":"Username (unique)","example":"john.doe"},"email":{"type":"string","description":"Email address (unique)","example":"john.doe@example.com"},"password":{"maxLength":2147483647,"minLength":8,"type":"string","description":"Password (min 8 characters)","example":"SecurePass123"},"roleNames":{"uniqueItems":true,"type":"array","description":"Role names to assign","example":["USER","MANAGER"],"items":{"type":"string","description":"Role names to assign","example":"[\"USER\",\"MANAGER\"]","enum":["ADMIN","PRODUCTION_MANAGER","PRODUCTION_WORKER","QUALITY_MANAGER","QUALITY_INSPECTOR","PROCUREMENT_MANAGER","WAREHOUSE_WORKER","SALES_MANAGER","SALES_STAFF"]}},"branchId":{"type":"string","description":"Branch ID (optional)","example":"BRANCH-001"}},"description":"Request to create a new user"},"AssignRoleRequest":{"required":["roleName"],"type":"object","properties":{"roleName":{"type":"string","description":"Role name to assign","example":"MANAGER","enum":["ADMIN","PRODUCTION_MANAGER","PRODUCTION_WORKER","QUALITY_MANAGER","QUALITY_INSPECTOR","PROCUREMENT_MANAGER","WAREHOUSE_WORKER","SALES_MANAGER","SALES_STAFF"]}},"description":"Request to assign a role to a user"},"CreateSupplierRequest":{"required":["name","phone"],"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"contactPerson":{"type":"string"},"street":{"type":"string"},"houseNumber":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"paymentDueDays":{"type":"integer","format":"int32"},"paymentDescription":{"type":"string"}}},"RateSupplierRequest":{"type":"object","properties":{"qualityScore":{"maximum":5,"minimum":1,"type":"integer","format":"int32"},"deliveryScore":{"maximum":5,"minimum":1,"type":"integer","format":"int32"},"priceScore":{"maximum":5,"minimum":1,"type":"integer","format":"int32"}}},"AddCertificateRequest":{"required":["certificateType"],"type":"object","properties":{"certificateType":{"type":"string"},"issuer":{"type":"string"},"validFrom":{"type":"string","format":"date"},"validUntil":{"type":"string","format":"date"}}},"CreateCustomerRequest":{"required":["city","country","name","phone","postalCode","street","type"],"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["B2C","B2B"]},"street":{"type":"string"},"houseNumber":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"contactPerson":{"type":"string"},"paymentDueDays":{"type":"integer","format":"int32"},"paymentDescription":{"type":"string"}}},"AddDeliveryAddressRequest":{"required":["city","country","postalCode","street"],"type":"object","properties":{"label":{"type":"string"},"street":{"type":"string"},"houseNumber":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"contactPerson":{"type":"string"},"deliveryNotes":{"type":"string"}}},"CreateProductCategoryRequest":{"required":["name"],"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"}}},"RefreshTokenRequest":{"required":["refreshToken"],"type":"object","properties":{"refreshToken":{"type":"string","description":"Refresh token"}},"description":"Refresh token request"},"LoginResponse":{"type":"object","properties":{"accessToken":{"type":"string","description":"JWT access token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"tokenType":{"type":"string","description":"Token type","example":"Bearer"},"expiresIn":{"type":"integer","description":"Token expiration time in seconds","format":"int64","example":3600},"expiresAt":{"type":"string","description":"Token expiration timestamp","format":"date-time"},"refreshToken":{"type":"string","description":"Refresh token for obtaining new access token"}},"description":"Login response with JWT tokens"},"LoginRequest":{"required":["password","username"],"type":"object","properties":{"username":{"type":"string","description":"Username","example":"admin"},"password":{"type":"string","description":"Password","example":"admin123"}},"description":"Login request with username and password"},"CreateArticleRequest":{"required":["articleNumber","categoryId","name","price","priceModel","unit"],"type":"object","properties":{"name":{"type":"string"},"articleNumber":{"type":"string"},"categoryId":{"type":"string"},"unit":{"type":"string","enum":["PIECE_FIXED","KG","HUNDRED_GRAM","PIECE_VARIABLE"]},"priceModel":{"type":"string","enum":["FIXED","WEIGHT_BASED"]},"price":{"type":"number"}}},"AssignSupplierRequest":{"required":["supplierId"],"type":"object","properties":{"supplierId":{"type":"string"}}},"AddSalesUnitRequest":{"required":["price","priceModel","unit"],"type":"object","properties":{"unit":{"type":"string","enum":["PIECE_FIXED","KG","HUNDRED_GRAM","PIECE_VARIABLE"]},"priceModel":{"type":"string","enum":["FIXED","WEIGHT_BASED"]},"price":{"type":"number"}}},"RemoveCertificateRequest":{"required":["certificateType"],"type":"object","properties":{"certificateType":{"type":"string"},"issuer":{"type":"string"},"validFrom":{"type":"string","format":"date"}}}},"securitySchemes":{"Bearer Authentication":{"type":"http","description":"JWT authentication token obtained from POST /api/auth/login.\n\nFormat: Bearer \n\nExample:\nBearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\n","scheme":"bearer","bearerFormat":"JWT"}}}} \ No newline at end of file diff --git a/frontend/packages/api-client/package.json b/frontend/packages/api-client/package.json index dac2988..34ebdb8 100644 --- a/frontend/packages/api-client/package.json +++ b/frontend/packages/api-client/package.json @@ -3,12 +3,22 @@ "version": "0.1.0", "description": "HTTP client for the Effigenix ERP API", "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./src/index.ts", + "types": "./src/index.ts", "exports": { ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "publishConfig": { + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } } }, "scripts": { diff --git a/frontend/packages/config/package.json b/frontend/packages/config/package.json index a133220..310e64d 100644 --- a/frontend/packages/config/package.json +++ b/frontend/packages/config/package.json @@ -3,12 +3,22 @@ "version": "0.1.0", "description": "Shared configuration constants for Effigenix ERP", "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./src/index.ts", + "types": "./src/index.ts", "exports": { ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "publishConfig": { + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } } }, "scripts": { diff --git a/frontend/packages/types/package.json b/frontend/packages/types/package.json index 3286bda..ab735bb 100644 --- a/frontend/packages/types/package.json +++ b/frontend/packages/types/package.json @@ -3,17 +3,28 @@ "version": "0.1.0", "description": "TypeScript types for Effigenix ERP (auto-generated from OpenAPI)", "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./src/index.ts", + "types": "./src/index.ts", "exports": { ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "publishConfig": { + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } } }, "scripts": { - "generate:types": "openapi-typescript http://localhost:8080/api-docs -o src/generated/api.ts", - "build": "pnpm run generate:types && tsup", + "generate:types": "openapi-typescript ../../openapi.json -o src/generated/api.ts", + "generate:spec": "curl -sf http://localhost:8080/api-docs -o ../../openapi.json", + "build": "tsup", "dev": "tsup --watch", "typecheck": "tsc --noEmit", "clean": "rm -rf dist .turbo" diff --git a/frontend/packages/types/src/auth.ts b/frontend/packages/types/src/auth.ts index 3dea270..86dae09 100644 --- a/frontend/packages/types/src/auth.ts +++ b/frontend/packages/types/src/auth.ts @@ -12,9 +12,6 @@ export type LoginResponse = components['schemas']['LoginResponse']; // Token Refresh export type RefreshTokenRequest = components['schemas']['RefreshTokenRequest']; -// Session Token -export type SessionToken = components['schemas']['SessionToken']; - /** * Custom types not in OpenAPI spec */ diff --git a/frontend/packages/types/src/common.ts b/frontend/packages/types/src/common.ts index b8199f4..73f98e4 100644 --- a/frontend/packages/types/src/common.ts +++ b/frontend/packages/types/src/common.ts @@ -3,15 +3,17 @@ * Re-exports types from the auto-generated OpenAPI schema */ -import type { components } from './generated/api'; - -// Error handling -export type ErrorResponse = components['schemas']['ErrorResponse']; - /** * Custom common types */ +export interface ErrorResponse { + message: string; + status?: number; + timestamp?: string; + path?: string; +} + export interface ValidationError { field: string; message: string; diff --git a/frontend/packages/types/src/generated/api.ts b/frontend/packages/types/src/generated/api.ts index 2484244..c37b877 100644 --- a/frontend/packages/types/src/generated/api.ts +++ b/frontend/packages/types/src/generated/api.ts @@ -1,22 +1,2345 @@ -// This file is AUTO-GENERATED by openapi-typescript -// DO NOT EDIT manually - run 'pnpm run generate:types' to regenerate -// -// To generate types, start the backend first: -// cd backend && mvn spring-boot:run -// Then run: -// pnpm run generate:types - /** - * This file will contain the OpenAPI-generated types from the backend. - * After running the generate command, it will export: - * - components.schemas (all DTOs) - * - paths (all API endpoints) + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. */ -export interface components { - schemas: Record; -} - export interface paths { - [key: string]: unknown; + "/api/users/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get user by ID + * @description Retrieve a single user by their ID. Requires authentication. + */ + get: operations["getUserById"]; + /** + * Update user + * @description Update user details (email, branchId). Only provided fields will be updated. + */ + put: operations["updateUser"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/{id}/password": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * Change password + * @description Change user password. Requires current password for verification. + */ + put: operations["changePassword"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/suppliers/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getSupplier"]; + put: operations["updateSupplier"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/customers/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getCustomer"]; + put: operations["updateCustomer"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/customers/{id}/preferences": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put: operations["setPreferences"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/customers/{id}/frame-contract": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put: operations["setFrameContract"]; + post?: never; + delete: operations["removeFrameContract"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/categories/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put: operations["updateCategory"]; + post?: never; + delete: operations["deleteCategory"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getArticle"]; + put: operations["updateArticle"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles/{id}/sales-units/{suId}/price": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put: operations["updateSalesUnitPrice"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all users + * @description Get a list of all users in the system. Requires authentication. + */ + get: operations["listUsers"]; + put?: never; + /** + * Create user (ADMIN only) + * @description Create a new user account with specified roles. Requires USER_MANAGEMENT permission. + */ + post: operations["createUser"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/{id}/unlock": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Unlock user (ADMIN only) + * @description Unlock a user account (allows login). Requires USER_MANAGEMENT permission. + */ + post: operations["unlockUser"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/{id}/roles": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Assign role (ADMIN only) + * @description Assign a role to a user. Requires USER_MANAGEMENT permission. + */ + post: operations["assignRole"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/{id}/lock": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Lock user (ADMIN only) + * @description Lock a user account (prevents login). Requires USER_MANAGEMENT permission. + */ + post: operations["lockUser"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/suppliers": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["listSuppliers"]; + put?: never; + post: operations["createSupplier"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/suppliers/{id}/rating": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["rateSupplier"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/suppliers/{id}/deactivate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["deactivate"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/suppliers/{id}/certificates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["addCertificate"]; + delete: operations["removeCertificate"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/suppliers/{id}/activate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["activate"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/customers": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["listCustomers"]; + put?: never; + post: operations["createCustomer"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/customers/{id}/delivery-addresses": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["addDeliveryAddress"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/customers/{id}/deactivate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["deactivate_1"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/customers/{id}/activate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["activate_1"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/categories": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["listCategories"]; + put?: never; + post: operations["createCategory"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/refresh": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Refresh access token + * @description Refresh an expired access token using a valid refresh token. Returns new access token and refresh token. + */ + post: operations["refresh"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * User logout + * @description Invalidate current JWT token. Requires authentication. + */ + post: operations["logout"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/login": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * User login + * @description Authenticate user with username and password. Returns JWT access token and refresh token. + */ + post: operations["login"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["listArticles"]; + put?: never; + post: operations["createArticle"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles/{id}/suppliers": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["assignSupplier"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles/{id}/sales-units": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["addSalesUnit"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles/{id}/deactivate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["deactivate_2"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles/{id}/activate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["activate_2"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/roles": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all roles (ADMIN only) + * @description Get a list of all available roles in the system. Requires USER_MANAGEMENT permission. + */ + get: operations["listRoles"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/{id}/roles/{roleName}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** + * Remove role (ADMIN only) + * @description Remove a role from a user. Requires USER_MANAGEMENT permission. + */ + delete: operations["removeRole"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/customers/{id}/delivery-addresses/{label}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["removeDeliveryAddress"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles/{id}/suppliers/{supplierId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["removeSupplier"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/articles/{id}/sales-units/{suId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["removeSalesUnit"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + /** @description Request to update user details */ + UpdateUserRequest: { + /** + * @description New email address + * @example newemail@example.com + */ + email?: string; + /** + * @description New branch ID + * @example BRANCH-002 + */ + branchId?: string; + }; + RoleDTO: { + id?: string; + /** @enum {string} */ + name?: "ADMIN" | "PRODUCTION_MANAGER" | "PRODUCTION_WORKER" | "QUALITY_MANAGER" | "QUALITY_INSPECTOR" | "PROCUREMENT_MANAGER" | "WAREHOUSE_WORKER" | "SALES_MANAGER" | "SALES_STAFF"; + permissions?: ("RECIPE_READ" | "RECIPE_WRITE" | "RECIPE_DELETE" | "BATCH_READ" | "BATCH_WRITE" | "BATCH_COMPLETE" | "BATCH_DELETE" | "PRODUCTION_ORDER_READ" | "PRODUCTION_ORDER_WRITE" | "PRODUCTION_ORDER_DELETE" | "HACCP_READ" | "HACCP_WRITE" | "TEMPERATURE_LOG_READ" | "TEMPERATURE_LOG_WRITE" | "CLEANING_RECORD_READ" | "CLEANING_RECORD_WRITE" | "GOODS_INSPECTION_READ" | "GOODS_INSPECTION_WRITE" | "STOCK_READ" | "STOCK_WRITE" | "STOCK_MOVEMENT_READ" | "STOCK_MOVEMENT_WRITE" | "INVENTORY_COUNT_READ" | "INVENTORY_COUNT_WRITE" | "PURCHASE_ORDER_READ" | "PURCHASE_ORDER_WRITE" | "PURCHASE_ORDER_DELETE" | "GOODS_RECEIPT_READ" | "GOODS_RECEIPT_WRITE" | "SUPPLIER_READ" | "SUPPLIER_WRITE" | "SUPPLIER_DELETE" | "ORDER_READ" | "ORDER_WRITE" | "ORDER_DELETE" | "INVOICE_READ" | "INVOICE_WRITE" | "INVOICE_DELETE" | "CUSTOMER_READ" | "CUSTOMER_WRITE" | "CUSTOMER_DELETE" | "LABEL_READ" | "LABEL_WRITE" | "LABEL_PRINT" | "BRANCH_READ" | "BRANCH_WRITE" | "BRANCH_DELETE" | "USER_READ" | "USER_WRITE" | "USER_DELETE" | "USER_LOCK" | "USER_UNLOCK" | "ROLE_READ" | "ROLE_WRITE" | "ROLE_ASSIGN" | "ROLE_REMOVE" | "REPORT_READ" | "REPORT_GENERATE" | "NOTIFICATION_READ" | "NOTIFICATION_SEND" | "AUDIT_LOG_READ" | "SYSTEM_SETTINGS_READ" | "SYSTEM_SETTINGS_WRITE")[]; + description?: string; + }; + UserDTO: { + id?: string; + username?: string; + email?: string; + roles?: components["schemas"]["RoleDTO"][]; + branchId?: string; + /** @enum {string} */ + status?: "ACTIVE" | "INACTIVE" | "LOCKED"; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + lastLogin?: string; + }; + /** @description Request to change user password */ + ChangePasswordRequest: { + /** + * @description Current password + * @example OldPass123 + */ + currentPassword: string; + /** + * @description New password (min 8 characters) + * @example NewSecurePass456 + */ + newPassword: string; + }; + UpdateSupplierRequest: { + name?: string; + phone?: string; + email?: string; + contactPerson?: string; + street?: string; + houseNumber?: string; + postalCode?: string; + city?: string; + country?: string; + /** Format: int32 */ + paymentDueDays?: number; + paymentDescription?: string; + }; + Supplier: Record; + UpdateCustomerRequest: { + name?: string; + street?: string; + houseNumber?: string; + postalCode?: string; + city?: string; + country?: string; + phone?: string; + email?: string; + contactPerson?: string; + /** Format: int32 */ + paymentDueDays?: number; + paymentDescription?: string; + }; + Customer: { + frameContract?: components["schemas"]["ResultCustomerErrorVoid"]; + preferences?: ("BIO" | "REGIONAL" | "TIERWOHL" | "HALAL" | "KOSHER" | "GLUTENFREI" | "LAKTOSEFREI")[]; + }; + ResultCustomerErrorVoid: { + failure?: boolean; + success?: boolean; + }; + SetPreferencesRequest: { + preferences: ("BIO" | "REGIONAL" | "TIERWOHL" | "HALAL" | "KOSHER" | "GLUTENFREI" | "LAKTOSEFREI")[]; + }; + LineItem: { + articleId: string; + agreedPrice: number; + agreedQuantity?: number; + /** @enum {string} */ + unit?: "PIECE_FIXED" | "KG" | "HUNDRED_GRAM" | "PIECE_VARIABLE"; + }; + SetFrameContractRequest: { + /** Format: date */ + validFrom?: string; + /** Format: date */ + validUntil?: string; + /** @enum {string} */ + rhythm: "DAILY" | "WEEKLY" | "BIWEEKLY" | "MONTHLY" | "ON_DEMAND"; + lineItems: components["schemas"]["LineItem"][]; + }; + UpdateProductCategoryRequest: { + name?: string; + description?: string; + }; + ProductCategory: Record; + UpdateArticleRequest: { + name?: string; + categoryId?: string; + }; + Article: Record; + UpdateSalesUnitPriceRequest: { + price: number; + }; + /** @description Request to create a new user */ + CreateUserRequest: { + /** + * @description Username (unique) + * @example john.doe + */ + username: string; + /** + * @description Email address (unique) + * @example john.doe@example.com + */ + email: string; + /** + * @description Password (min 8 characters) + * @example SecurePass123 + */ + password: string; + /** + * @description Role names to assign + * @example [ + * "USER", + * "MANAGER" + * ] + */ + roleNames: ("ADMIN" | "PRODUCTION_MANAGER" | "PRODUCTION_WORKER" | "QUALITY_MANAGER" | "QUALITY_INSPECTOR" | "PROCUREMENT_MANAGER" | "WAREHOUSE_WORKER" | "SALES_MANAGER" | "SALES_STAFF")[]; + /** + * @description Branch ID (optional) + * @example BRANCH-001 + */ + branchId?: string; + }; + /** @description Request to assign a role to a user */ + AssignRoleRequest: { + /** + * @description Role name to assign + * @example MANAGER + * @enum {string} + */ + roleName: "ADMIN" | "PRODUCTION_MANAGER" | "PRODUCTION_WORKER" | "QUALITY_MANAGER" | "QUALITY_INSPECTOR" | "PROCUREMENT_MANAGER" | "WAREHOUSE_WORKER" | "SALES_MANAGER" | "SALES_STAFF"; + }; + CreateSupplierRequest: { + name: string; + phone: string; + email?: string; + contactPerson?: string; + street?: string; + houseNumber?: string; + postalCode?: string; + city?: string; + country?: string; + /** Format: int32 */ + paymentDueDays?: number; + paymentDescription?: string; + }; + RateSupplierRequest: { + /** Format: int32 */ + qualityScore?: number; + /** Format: int32 */ + deliveryScore?: number; + /** Format: int32 */ + priceScore?: number; + }; + AddCertificateRequest: { + certificateType: string; + issuer?: string; + /** Format: date */ + validFrom?: string; + /** Format: date */ + validUntil?: string; + }; + CreateCustomerRequest: { + name: string; + /** @enum {string} */ + type: "B2C" | "B2B"; + street: string; + houseNumber?: string; + postalCode: string; + city: string; + country: string; + phone: string; + email?: string; + contactPerson?: string; + /** Format: int32 */ + paymentDueDays?: number; + paymentDescription?: string; + }; + AddDeliveryAddressRequest: { + label?: string; + street: string; + houseNumber?: string; + postalCode: string; + city: string; + country: string; + contactPerson?: string; + deliveryNotes?: string; + }; + CreateProductCategoryRequest: { + name: string; + description?: string; + }; + /** @description Refresh token request */ + RefreshTokenRequest: { + /** @description Refresh token */ + refreshToken: string; + }; + /** @description Login response with JWT tokens */ + LoginResponse: { + /** + * @description JWT access token + * @example eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... + */ + accessToken?: string; + /** + * @description Token type + * @example Bearer + */ + tokenType?: string; + /** + * Format: int64 + * @description Token expiration time in seconds + * @example 3600 + */ + expiresIn?: number; + /** + * Format: date-time + * @description Token expiration timestamp + */ + expiresAt?: string; + /** @description Refresh token for obtaining new access token */ + refreshToken?: string; + }; + /** @description Login request with username and password */ + LoginRequest: { + /** + * @description Username + * @example admin + */ + username: string; + /** + * @description Password + * @example admin123 + */ + password: string; + }; + CreateArticleRequest: { + name: string; + articleNumber: string; + categoryId: string; + /** @enum {string} */ + unit: "PIECE_FIXED" | "KG" | "HUNDRED_GRAM" | "PIECE_VARIABLE"; + /** @enum {string} */ + priceModel: "FIXED" | "WEIGHT_BASED"; + price: number; + }; + AssignSupplierRequest: { + supplierId: string; + }; + AddSalesUnitRequest: { + /** @enum {string} */ + unit: "PIECE_FIXED" | "KG" | "HUNDRED_GRAM" | "PIECE_VARIABLE"; + /** @enum {string} */ + priceModel: "FIXED" | "WEIGHT_BASED"; + price: number; + }; + RemoveCertificateRequest: { + certificateType: string; + issuer?: string; + /** Format: date */ + validFrom?: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + getUserById: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description User ID + * @example user-uuid + */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description User retrieved successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description User not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + }; + }; + updateUser: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description User ID + * @example user-uuid + */ + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateUserRequest"]; + }; + }; + responses: { + /** @description User updated successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description User not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Email already exists */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + }; + }; + changePassword: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description User ID + * @example user-uuid + */ + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ChangePasswordRequest"]; + }; + }; + responses: { + /** @description Password changed successfully */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Invalid password */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Invalid current password or authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description User not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getSupplier: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Supplier"]; + }; + }; + }; + }; + updateSupplier: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateSupplierRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Supplier"]; + }; + }; + }; + }; + getCustomer: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"]; + }; + }; + }; + }; + updateCustomer: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateCustomerRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"]; + }; + }; + }; + }; + setPreferences: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetPreferencesRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"]; + }; + }; + }; + }; + setFrameContract: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetFrameContractRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"]; + }; + }; + }; + }; + removeFrameContract: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + updateCategory: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateProductCategoryRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ProductCategory"]; + }; + }; + }; + }; + deleteCategory: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getArticle: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"]; + }; + }; + }; + }; + updateArticle: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateArticleRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"]; + }; + }; + }; + }; + updateSalesUnitPrice: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + suId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateSalesUnitPriceRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"]; + }; + }; + }; + }; + listUsers: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Users retrieved successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"][]; + }; + }; + }; + }; + createUser: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateUserRequest"]; + }; + }; + responses: { + /** @description User created successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Validation error or invalid password */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Missing USER_MANAGEMENT permission */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Username or email already exists */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + }; + }; + unlockUser: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description User ID + * @example user-uuid + */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description User unlocked successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Missing USER_MANAGEMENT permission */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description User not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + }; + }; + assignRole: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description User ID + * @example user-uuid + */ + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssignRoleRequest"]; + }; + }; + responses: { + /** @description Role assigned successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Missing USER_MANAGEMENT permission */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description User or role not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + }; + }; + lockUser: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description User ID + * @example user-uuid + */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description User locked successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description Missing USER_MANAGEMENT permission */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + /** @description User not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["UserDTO"]; + }; + }; + }; + }; + listSuppliers: { + parameters: { + query?: { + status?: "ACTIVE" | "INACTIVE"; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Supplier"][]; + }; + }; + }; + }; + createSupplier: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateSupplierRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Supplier"]; + }; + }; + }; + }; + rateSupplier: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RateSupplierRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Supplier"]; + }; + }; + }; + }; + deactivate: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Supplier"]; + }; + }; + }; + }; + addCertificate: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AddCertificateRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Supplier"]; + }; + }; + }; + }; + removeCertificate: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RemoveCertificateRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + activate: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Supplier"]; + }; + }; + }; + }; + listCustomers: { + parameters: { + query?: { + type?: "B2C" | "B2B"; + status?: "ACTIVE" | "INACTIVE"; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"][]; + }; + }; + }; + }; + createCustomer: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateCustomerRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"]; + }; + }; + }; + }; + addDeliveryAddress: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AddDeliveryAddressRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"]; + }; + }; + }; + }; + deactivate_1: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"]; + }; + }; + }; + }; + activate_1: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Customer"]; + }; + }; + }; + }; + listCategories: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ProductCategory"][]; + }; + }; + }; + }; + createCategory: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateProductCategoryRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ProductCategory"]; + }; + }; + }; + }; + refresh: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RefreshTokenRequest"]; + }; + }; + responses: { + /** @description Token refresh successful */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["LoginResponse"]; + }; + }; + /** @description Validation error (missing refresh token) */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["LoginResponse"]; + }; + }; + /** @description Invalid or expired refresh token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["LoginResponse"]; + }; + }; + }; + }; + logout: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Logout successful */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Invalid or missing authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + login: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["LoginRequest"]; + }; + }; + responses: { + /** @description Login successful */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["LoginResponse"]; + }; + }; + /** @description Validation error (missing username or password) */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["LoginResponse"]; + }; + }; + /** @description Invalid credentials, user locked, or user inactive */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["LoginResponse"]; + }; + }; + }; + }; + listArticles: { + parameters: { + query?: { + categoryId?: string; + status?: "ACTIVE" | "INACTIVE"; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"][]; + }; + }; + }; + }; + createArticle: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateArticleRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"]; + }; + }; + }; + }; + assignSupplier: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssignSupplierRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"]; + }; + }; + }; + }; + addSalesUnit: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AddSalesUnitRequest"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"]; + }; + }; + }; + }; + deactivate_2: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"]; + }; + }; + }; + }; + activate_2: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["Article"]; + }; + }; + }; + }; + listRoles: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Roles retrieved successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["RoleDTO"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["RoleDTO"][]; + }; + }; + /** @description Missing USER_MANAGEMENT permission */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["RoleDTO"][]; + }; + }; + }; + }; + removeRole: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description User ID + * @example user-uuid + */ + id: string; + /** + * @description Role name + * @example MANAGER + */ + roleName: "ADMIN" | "PRODUCTION_MANAGER" | "PRODUCTION_WORKER" | "QUALITY_MANAGER" | "QUALITY_INSPECTOR" | "PROCUREMENT_MANAGER" | "WAREHOUSE_WORKER" | "SALES_MANAGER" | "SALES_STAFF"; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Role removed successfully */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Missing USER_MANAGEMENT permission */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description User or role not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + removeDeliveryAddress: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + label: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + removeSupplier: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + supplierId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + removeSalesUnit: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + suId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; } diff --git a/frontend/packages/types/src/role.ts b/frontend/packages/types/src/role.ts index b9fff54..5817f9b 100644 --- a/frontend/packages/types/src/role.ts +++ b/frontend/packages/types/src/role.ts @@ -7,8 +7,8 @@ import type { components } from './generated/api'; // Role DTOs export type RoleDTO = components['schemas']['RoleDTO']; -export type RoleName = components['schemas']['RoleName']; -export type Permission = components['schemas']['Permission']; +export type RoleName = NonNullable; +export type Permission = NonNullable[number]; /** * Custom types for UI diff --git a/frontend/packages/validation/package.json b/frontend/packages/validation/package.json index decee84..a514509 100644 --- a/frontend/packages/validation/package.json +++ b/frontend/packages/validation/package.json @@ -3,12 +3,22 @@ "version": "0.1.0", "description": "Zod validation schemas for Effigenix ERP", "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./src/index.ts", + "types": "./src/index.ts", "exports": { ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "publishConfig": { + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } } }, "scripts": { diff --git a/makefile b/makefile new file mode 100644 index 0000000..6e18f23 --- /dev/null +++ b/makefile @@ -0,0 +1,7 @@ + + +backend/run: + cd backend && mvn spring-boot:run + +generate/openapi: + ./scripts/generate-openapi.sh diff --git a/scripts/generate-openapi.sh b/scripts/generate-openapi.sh new file mode 100755 index 0000000..aaf44c6 --- /dev/null +++ b/scripts/generate-openapi.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -euo pipefail + +BACKEND_DIR="$(cd "$(dirname "$0")/../backend" && pwd)" +FRONTEND_DIR="$(cd "$(dirname "$0")/../frontend" && pwd)" +API_DOCS_URL="http://localhost:8080/api-docs" +TIMEOUT=60 +BACKEND_PID="" + +cleanup() { + if [[ -n "$BACKEND_PID" ]]; then + echo "→ Backend wird gestoppt (PID $BACKEND_PID)..." + kill "$BACKEND_PID" 2>/dev/null || true + fi +} +trap cleanup EXIT + +wait_for_backend() { + echo "→ Warte auf Backend ($TIMEOUT s)..." + local elapsed=0 + until curl -sf "$API_DOCS_URL" -o /dev/null; do + if (( elapsed >= TIMEOUT )); then + echo "✗ Backend nicht erreichbar nach ${TIMEOUT}s" >&2 + exit 1 + fi + sleep 2 + (( elapsed += 2 )) + done + echo "✓ Backend bereit" +} + +# Backend starten falls nicht erreichbar +if curl -sf "$API_DOCS_URL" -o /dev/null 2>/dev/null; then + echo "✓ Backend läuft bereits" +else + echo "→ Backend wird gestartet..." + mvn -f "$BACKEND_DIR/pom.xml" spring-boot:run -q & + BACKEND_PID=$! + wait_for_backend +fi + +echo "→ OpenAPI-Spec wird generiert..." +curl -sf "$API_DOCS_URL" -o "$FRONTEND_DIR/openapi.json" +echo "✓ openapi.json aktualisiert" + +echo "→ TypeScript-Typen werden generiert..." +pnpm --filter @effigenix/types --prefix "$FRONTEND_DIR" generate:types +echo "✓ src/generated/api.ts aktualisiert" + +echo "" +echo "Fertig. Bitte committen:" +echo " git add frontend/openapi.json frontend/packages/types/src/generated/api.ts"