create-ishvexa-app 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +62 -0
- package/package.json +14 -0
- package/templates/epms-app/.env +7 -0
- package/templates/epms-app/README.md +113 -0
- package/templates/epms-app/backend-mongodb/.env +3 -0
- package/templates/epms-app/backend-mongodb/.env.example +3 -0
- package/templates/epms-app/backend-mongodb/config/db.js +29 -0
- package/templates/epms-app/backend-mongodb/controllers/authController.js +93 -0
- package/templates/epms-app/backend-mongodb/controllers/departmentController.js +24 -0
- package/templates/epms-app/backend-mongodb/controllers/employeeController.js +39 -0
- package/templates/epms-app/backend-mongodb/controllers/reportController.js +57 -0
- package/templates/epms-app/backend-mongodb/controllers/salaryController.js +101 -0
- package/templates/epms-app/backend-mongodb/middleware/auth.js +16 -0
- package/templates/epms-app/backend-mongodb/models/Counter.js +13 -0
- package/templates/epms-app/backend-mongodb/models/Department.js +11 -0
- package/templates/epms-app/backend-mongodb/models/Employee.js +18 -0
- package/templates/epms-app/backend-mongodb/models/Salary.js +19 -0
- package/templates/epms-app/backend-mongodb/models/User.js +9 -0
- package/templates/epms-app/backend-mongodb/package-lock.json +1571 -0
- package/templates/epms-app/backend-mongodb/package.json +22 -0
- package/templates/epms-app/backend-mongodb/routes/authRoutes.js +8 -0
- package/templates/epms-app/backend-mongodb/routes/departmentRoutes.js +6 -0
- package/templates/epms-app/backend-mongodb/routes/employeeRoutes.js +6 -0
- package/templates/epms-app/backend-mongodb/routes/reportRoutes.js +5 -0
- package/templates/epms-app/backend-mongodb/routes/salaryRoutes.js +8 -0
- package/templates/epms-app/backend-mongodb/server.js +39 -0
- package/templates/epms-app/backend-mysql/.env +7 -0
- package/templates/epms-app/backend-mysql/.env.example +7 -0
- package/templates/epms-app/backend-mysql/config/db.js +33 -0
- package/templates/epms-app/backend-mysql/controllers/authController.js +98 -0
- package/templates/epms-app/backend-mysql/controllers/departmentController.js +25 -0
- package/templates/epms-app/backend-mysql/controllers/employeeController.js +39 -0
- package/templates/epms-app/backend-mysql/controllers/reportController.js +41 -0
- package/templates/epms-app/backend-mysql/controllers/salaryController.js +93 -0
- package/templates/epms-app/backend-mysql/database/schema.sql +7 -0
- package/templates/epms-app/backend-mysql/middleware/auth.js +16 -0
- package/templates/epms-app/backend-mysql/package-lock.json +1486 -0
- package/templates/epms-app/backend-mysql/package.json +23 -0
- package/templates/epms-app/backend-mysql/routes/authRoutes.js +8 -0
- package/templates/epms-app/backend-mysql/routes/departmentRoutes.js +6 -0
- package/templates/epms-app/backend-mysql/routes/employeeRoutes.js +6 -0
- package/templates/epms-app/backend-mysql/routes/reportRoutes.js +5 -0
- package/templates/epms-app/backend-mysql/routes/salaryRoutes.js +8 -0
- package/templates/epms-app/backend-mysql/server.js +39 -0
- package/templates/epms-app/frontend/README.md +16 -0
- package/templates/epms-app/frontend/eslint.config.js +21 -0
- package/templates/epms-app/frontend/index.html +12 -0
- package/templates/epms-app/frontend/package-lock.json +3033 -0
- package/templates/epms-app/frontend/package.json +23 -0
- package/templates/epms-app/frontend/public/favicon.svg +1 -0
- package/templates/epms-app/frontend/public/icons.svg +24 -0
- package/templates/epms-app/frontend/src/App.css +184 -0
- package/templates/epms-app/frontend/src/App.jsx +31 -0
- package/templates/epms-app/frontend/src/api/authApi.js +7 -0
- package/templates/epms-app/frontend/src/api/client.js +11 -0
- package/templates/epms-app/frontend/src/api/departmentApi.js +5 -0
- package/templates/epms-app/frontend/src/api/employeeApi.js +4 -0
- package/templates/epms-app/frontend/src/api/reportApi.js +4 -0
- package/templates/epms-app/frontend/src/api/salaryApi.js +6 -0
- package/templates/epms-app/frontend/src/api/sparePartsApi.js +3 -0
- package/templates/epms-app/frontend/src/api/usersApi.js +4 -0
- package/templates/epms-app/frontend/src/assets/hero.png +0 -0
- package/templates/epms-app/frontend/src/assets/react.svg +1 -0
- package/templates/epms-app/frontend/src/assets/vite.svg +1 -0
- package/templates/epms-app/frontend/src/components/AppLayout.jsx +49 -0
- package/templates/epms-app/frontend/src/context/AuthContext.jsx +41 -0
- package/templates/epms-app/frontend/src/hooks/.gitkeep +0 -0
- package/templates/epms-app/frontend/src/index.css +2 -0
- package/templates/epms-app/frontend/src/main.jsx +16 -0
- package/templates/epms-app/frontend/src/pages/DepartmentPage.jsx +165 -0
- package/templates/epms-app/frontend/src/pages/DepartmentsPage.jsx +119 -0
- package/templates/epms-app/frontend/src/pages/EmployeePage.jsx +212 -0
- package/templates/epms-app/frontend/src/pages/EmployeesPage.jsx +217 -0
- package/templates/epms-app/frontend/src/pages/ForgotPassword.jsx +103 -0
- package/templates/epms-app/frontend/src/pages/LoginPage.jsx +105 -0
- package/templates/epms-app/frontend/src/pages/RegisterPage.jsx +84 -0
- package/templates/epms-app/frontend/src/pages/ReportsPage.jsx +192 -0
- package/templates/epms-app/frontend/src/pages/ResetPasswordPage.jsx +83 -0
- package/templates/epms-app/frontend/src/pages/SalariesPage.jsx +274 -0
- package/templates/epms-app/frontend/src/pages/SalaryPage.jsx +254 -0
- package/templates/epms-app/frontend/vite.config.js +8 -0
- package/templates/lms-app/.env +9 -0
- package/templates/lms-app/README.md +89 -0
- package/templates/lms-app/backend-mongodb/.env +5 -0
- package/templates/lms-app/backend-mongodb/.env.example +5 -0
- package/templates/lms-app/backend-mongodb/package-lock.json +1583 -0
- package/templates/lms-app/backend-mongodb/package.json +26 -0
- package/templates/lms-app/backend-mongodb/src/config/db.js +10 -0
- package/templates/lms-app/backend-mongodb/src/config/env.js +28 -0
- package/templates/lms-app/backend-mongodb/src/controllers/authController.js +86 -0
- package/templates/lms-app/backend-mongodb/src/controllers/bookController.js +101 -0
- package/templates/lms-app/backend-mongodb/src/controllers/borrowController.js +106 -0
- package/templates/lms-app/backend-mongodb/src/controllers/dashboardController.js +40 -0
- package/templates/lms-app/backend-mongodb/src/controllers/reportController.js +47 -0
- package/templates/lms-app/backend-mongodb/src/controllers/studentController.js +92 -0
- package/templates/lms-app/backend-mongodb/src/ensureSeedData.js +72 -0
- package/templates/lms-app/backend-mongodb/src/middleware/auth.js +29 -0
- package/templates/lms-app/backend-mongodb/src/models/Book.js +14 -0
- package/templates/lms-app/backend-mongodb/src/models/Borrow.js +16 -0
- package/templates/lms-app/backend-mongodb/src/models/Student.js +14 -0
- package/templates/lms-app/backend-mongodb/src/models/User.js +13 -0
- package/templates/lms-app/backend-mongodb/src/routes/authRoutes.js +12 -0
- package/templates/lms-app/backend-mongodb/src/routes/bookRoutes.js +13 -0
- package/templates/lms-app/backend-mongodb/src/routes/borrowRoutes.js +11 -0
- package/templates/lms-app/backend-mongodb/src/routes/dashboardRoutes.js +9 -0
- package/templates/lms-app/backend-mongodb/src/routes/reportRoutes.js +12 -0
- package/templates/lms-app/backend-mongodb/src/routes/studentRoutes.js +13 -0
- package/templates/lms-app/backend-mongodb/src/seed.js +16 -0
- package/templates/lms-app/backend-mongodb/src/server.js +66 -0
- package/templates/lms-app/backend-mysql/.env +9 -0
- package/templates/lms-app/backend-mysql/.env.example +9 -0
- package/templates/lms-app/backend-mysql/database/schema.sql +45 -0
- package/templates/lms-app/backend-mysql/package-lock.json +1462 -0
- package/templates/lms-app/backend-mysql/package.json +23 -0
- package/templates/lms-app/backend-mysql/src/config/db.js +33 -0
- package/templates/lms-app/backend-mysql/src/config/env.js +21 -0
- package/templates/lms-app/backend-mysql/src/controllers/authController.js +87 -0
- package/templates/lms-app/backend-mysql/src/controllers/bookController.js +106 -0
- package/templates/lms-app/backend-mysql/src/controllers/borrowController.js +113 -0
- package/templates/lms-app/backend-mysql/src/controllers/dashboardController.js +33 -0
- package/templates/lms-app/backend-mysql/src/controllers/reportController.js +40 -0
- package/templates/lms-app/backend-mysql/src/controllers/studentController.js +95 -0
- package/templates/lms-app/backend-mysql/src/ensureSeedData.js +54 -0
- package/templates/lms-app/backend-mysql/src/middleware/auth.js +28 -0
- package/templates/lms-app/backend-mysql/src/routes/authRoutes.js +12 -0
- package/templates/lms-app/backend-mysql/src/routes/bookRoutes.js +13 -0
- package/templates/lms-app/backend-mysql/src/routes/borrowRoutes.js +11 -0
- package/templates/lms-app/backend-mysql/src/routes/dashboardRoutes.js +9 -0
- package/templates/lms-app/backend-mysql/src/routes/reportRoutes.js +12 -0
- package/templates/lms-app/backend-mysql/src/routes/studentRoutes.js +13 -0
- package/templates/lms-app/backend-mysql/src/server.js +69 -0
- package/templates/lms-app/backend-mysql/src/utils/mappers.js +73 -0
- package/templates/lms-app/frontend/.env.example +5 -0
- package/templates/lms-app/frontend/index.html +13 -0
- package/templates/lms-app/frontend/package-lock.json +1592 -0
- package/templates/lms-app/frontend/package.json +23 -0
- package/templates/lms-app/frontend/public/favicon.svg +4 -0
- package/templates/lms-app/frontend/src/App.jsx +107 -0
- package/templates/lms-app/frontend/src/api/authApi.js +5 -0
- package/templates/lms-app/frontend/src/api/booksApi.js +6 -0
- package/templates/lms-app/frontend/src/api/borrowsApi.js +5 -0
- package/templates/lms-app/frontend/src/api/client.js +8 -0
- package/templates/lms-app/frontend/src/api/dashboardApi.js +3 -0
- package/templates/lms-app/frontend/src/api/reportsApi.js +6 -0
- package/templates/lms-app/frontend/src/api/studentsApi.js +6 -0
- package/templates/lms-app/frontend/src/components/AppLayout.jsx +63 -0
- package/templates/lms-app/frontend/src/index.css +34 -0
- package/templates/lms-app/frontend/src/main.jsx +13 -0
- package/templates/lms-app/frontend/src/pages/BooksPage.jsx +206 -0
- package/templates/lms-app/frontend/src/pages/BorrowPage.jsx +134 -0
- package/templates/lms-app/frontend/src/pages/DashboardPage.jsx +42 -0
- package/templates/lms-app/frontend/src/pages/ForgotPassword.jsx +112 -0
- package/templates/lms-app/frontend/src/pages/LoginPage.jsx +71 -0
- package/templates/lms-app/frontend/src/pages/ReportsPage.jsx +176 -0
- package/templates/lms-app/frontend/src/pages/ReturnPage.jsx +75 -0
- package/templates/lms-app/frontend/src/pages/SearchPage.jsx +156 -0
- package/templates/lms-app/frontend/src/pages/StudentsPage.jsx +204 -0
- package/templates/lms-app/frontend/vite.config.js +26 -0
- package/templates/scms-app/.env +7 -0
- package/templates/scms-app/README.md +80 -0
- package/templates/scms-app/backend-mongodb/.env +3 -0
- package/templates/scms-app/backend-mongodb/.env.example +3 -0
- package/templates/scms-app/backend-mongodb/config/db.js +29 -0
- package/templates/scms-app/backend-mongodb/controllers/authController.js +93 -0
- package/templates/scms-app/backend-mongodb/controllers/deliveryController.js +65 -0
- package/templates/scms-app/backend-mongodb/controllers/reportController.js +51 -0
- package/templates/scms-app/backend-mongodb/controllers/shipmentController.js +65 -0
- package/templates/scms-app/backend-mongodb/controllers/supplierController.js +27 -0
- package/templates/scms-app/backend-mongodb/middleware/auth.js +16 -0
- package/templates/scms-app/backend-mongodb/models/Delivery.js +14 -0
- package/templates/scms-app/backend-mongodb/models/Shipment.js +14 -0
- package/templates/scms-app/backend-mongodb/models/Supplier.js +14 -0
- package/templates/scms-app/backend-mongodb/models/User.js +9 -0
- package/templates/scms-app/backend-mongodb/package-lock.json +1571 -0
- package/templates/scms-app/backend-mongodb/package.json +22 -0
- package/templates/scms-app/backend-mongodb/routes/authRoutes.js +8 -0
- package/templates/scms-app/backend-mongodb/routes/deliveryRoutes.js +8 -0
- package/templates/scms-app/backend-mongodb/routes/reportRoutes.js +5 -0
- package/templates/scms-app/backend-mongodb/routes/shipmentRoutes.js +8 -0
- package/templates/scms-app/backend-mongodb/routes/supplierRoutes.js +6 -0
- package/templates/scms-app/backend-mongodb/server.js +39 -0
- package/templates/scms-app/backend-mysql/.env +7 -0
- package/templates/scms-app/backend-mysql/.env.example +7 -0
- package/templates/scms-app/backend-mysql/config/db.js +33 -0
- package/templates/scms-app/backend-mysql/controllers/authController.js +98 -0
- package/templates/scms-app/backend-mysql/controllers/deliveryController.js +62 -0
- package/templates/scms-app/backend-mysql/controllers/reportController.js +39 -0
- package/templates/scms-app/backend-mysql/controllers/shipmentController.js +62 -0
- package/templates/scms-app/backend-mysql/controllers/supplierController.js +28 -0
- package/templates/scms-app/backend-mysql/database/schema.sql +7 -0
- package/templates/scms-app/backend-mysql/middleware/auth.js +16 -0
- package/templates/scms-app/backend-mysql/package-lock.json +1486 -0
- package/templates/scms-app/backend-mysql/package.json +23 -0
- package/templates/scms-app/backend-mysql/routes/authRoutes.js +8 -0
- package/templates/scms-app/backend-mysql/routes/deliveryRoutes.js +8 -0
- package/templates/scms-app/backend-mysql/routes/reportRoutes.js +5 -0
- package/templates/scms-app/backend-mysql/routes/shipmentRoutes.js +8 -0
- package/templates/scms-app/backend-mysql/routes/supplierRoutes.js +6 -0
- package/templates/scms-app/backend-mysql/server.js +39 -0
- package/templates/scms-app/frontend/index.html +12 -0
- package/templates/scms-app/frontend/package-lock.json +1634 -0
- package/templates/scms-app/frontend/package.json +23 -0
- package/templates/scms-app/frontend/src/App.jsx +31 -0
- package/templates/scms-app/frontend/src/api/client.js +11 -0
- package/templates/scms-app/frontend/src/components/AppLayout.jsx +49 -0
- package/templates/scms-app/frontend/src/context/AuthContext.jsx +41 -0
- package/templates/scms-app/frontend/src/hooks/.gitkeep +0 -0
- package/templates/scms-app/frontend/src/index.css +2 -0
- package/templates/scms-app/frontend/src/main.jsx +16 -0
- package/templates/scms-app/frontend/src/pages/DeliveriesPage.jsx +265 -0
- package/templates/scms-app/frontend/src/pages/ForgotPassword.jsx +103 -0
- package/templates/scms-app/frontend/src/pages/LoginPage.jsx +105 -0
- package/templates/scms-app/frontend/src/pages/ReportsPage.jsx +192 -0
- package/templates/scms-app/frontend/src/pages/ShipmentsPage.jsx +259 -0
- package/templates/scms-app/frontend/src/pages/SuppliersPage.jsx +168 -0
- package/templates/scms-app/frontend/vite.config.js +8 -0
- package/templates/sfms-app/.env +7 -0
- package/templates/sfms-app/README.md +72 -0
- package/templates/sfms-app/backend-mongodb/.env +3 -0
- package/templates/sfms-app/backend-mongodb/.env.example +3 -0
- package/templates/sfms-app/backend-mongodb/package-lock.json +1580 -0
- package/templates/sfms-app/backend-mongodb/package.json +23 -0
- package/templates/sfms-app/backend-mongodb/src/config/database.js +7 -0
- package/templates/sfms-app/backend-mongodb/src/config/env.js +35 -0
- package/templates/sfms-app/backend-mongodb/src/middleware/authMiddleware.js +32 -0
- package/templates/sfms-app/backend-mongodb/src/models/Payment.js +12 -0
- package/templates/sfms-app/backend-mongodb/src/models/Student.js +12 -0
- package/templates/sfms-app/backend-mongodb/src/models/User.js +14 -0
- package/templates/sfms-app/backend-mongodb/src/routes/authRoutes.js +140 -0
- package/templates/sfms-app/backend-mongodb/src/routes/paymentRoutes.js +117 -0
- package/templates/sfms-app/backend-mongodb/src/routes/reportRoutes.js +59 -0
- package/templates/sfms-app/backend-mongodb/src/routes/studentRoutes.js +79 -0
- package/templates/sfms-app/backend-mongodb/src/server.js +34 -0
- package/templates/sfms-app/backend-mysql/.env +7 -0
- package/templates/sfms-app/backend-mysql/.env.example +7 -0
- package/templates/sfms-app/backend-mysql/database/schema.sql +29 -0
- package/templates/sfms-app/backend-mysql/package-lock.json +1467 -0
- package/templates/sfms-app/backend-mysql/package.json +24 -0
- package/templates/sfms-app/backend-mysql/src/config/.gitkeep +0 -0
- package/templates/sfms-app/backend-mysql/src/config/db.js +31 -0
- package/templates/sfms-app/backend-mysql/src/config/env.js +20 -0
- package/templates/sfms-app/backend-mysql/src/middleware/.gitkeep +0 -0
- package/templates/sfms-app/backend-mysql/src/middleware/authMiddleware.js +26 -0
- package/templates/sfms-app/backend-mysql/src/models/.gitkeep +0 -0
- package/templates/sfms-app/backend-mysql/src/routes/.gitkeep +0 -0
- package/templates/sfms-app/backend-mysql/src/routes/authRoutes.js +131 -0
- package/templates/sfms-app/backend-mysql/src/routes/paymentRoutes.js +92 -0
- package/templates/sfms-app/backend-mysql/src/routes/reportRoutes.js +41 -0
- package/templates/sfms-app/backend-mysql/src/routes/studentRoutes.js +75 -0
- package/templates/sfms-app/backend-mysql/src/server.js +39 -0
- package/templates/sfms-app/backend-mysql/src/utils/mappers.js +43 -0
- package/templates/sfms-app/frontend/.env.example +9 -0
- package/templates/sfms-app/frontend/index.html +19 -0
- package/templates/sfms-app/frontend/package-lock.json +2667 -0
- package/templates/sfms-app/frontend/package.json +23 -0
- package/templates/sfms-app/frontend/postcss.config.js +6 -0
- package/templates/sfms-app/frontend/public/favicon.svg +4 -0
- package/templates/sfms-app/frontend/src/App.jsx +38 -0
- package/templates/sfms-app/frontend/src/api/apiClient.js +54 -0
- package/templates/sfms-app/frontend/src/components/AppLayout.jsx +61 -0
- package/templates/sfms-app/frontend/src/context/AuthContext.jsx +87 -0
- package/templates/sfms-app/frontend/src/index.css +7 -0
- package/templates/sfms-app/frontend/src/main.jsx +16 -0
- package/templates/sfms-app/frontend/src/pages/DashboardPage.jsx +78 -0
- package/templates/sfms-app/frontend/src/pages/ForgotPassword.jsx +114 -0
- package/templates/sfms-app/frontend/src/pages/LoginPage.jsx +141 -0
- package/templates/sfms-app/frontend/src/pages/PaymentsPage.jsx +309 -0
- package/templates/sfms-app/frontend/src/pages/ReportsPage.jsx +123 -0
- package/templates/sfms-app/frontend/src/pages/StudentsPage.jsx +281 -0
- package/templates/sfms-app/frontend/tailwind.config.js +21 -0
- package/templates/sfms-app/frontend/vite.config.js +61 -0
- package/templates/sims-app/README.md +138 -0
- package/templates/sims-app/backend/.env +4 -0
- package/templates/sims-app/backend/.env.example +4 -0
- package/templates/sims-app/backend/package.json +22 -0
- package/templates/sims-app/backend/src/config/db.js +9 -0
- package/templates/sims-app/backend/src/controllers/authController.js +115 -0
- package/templates/sims-app/backend/src/controllers/simsReportController.js +94 -0
- package/templates/sims-app/backend/src/controllers/sparePartController.js +41 -0
- package/templates/sims-app/backend/src/controllers/stockInController.js +45 -0
- package/templates/sims-app/backend/src/controllers/stockOutController.js +123 -0
- package/templates/sims-app/backend/src/middleware/auth.js +8 -0
- package/templates/sims-app/backend/src/models/SparePart.js +17 -0
- package/templates/sims-app/backend/src/models/StockIn.js +16 -0
- package/templates/sims-app/backend/src/models/StockOut.js +18 -0
- package/templates/sims-app/backend/src/models/User.js +12 -0
- package/templates/sims-app/backend/src/routes/authRoutes.js +12 -0
- package/templates/sims-app/backend/src/routes/simsReportRoutes.js +8 -0
- package/templates/sims-app/backend/src/routes/sparePartRoutes.js +8 -0
- package/templates/sims-app/backend/src/routes/stockInRoutes.js +8 -0
- package/templates/sims-app/backend/src/routes/stockOutRoutes.js +10 -0
- package/templates/sims-app/backend/src/server.js +62 -0
- package/templates/sims-app/backend/src/utils/passwordPolicy.js +10 -0
- package/templates/sims-app/backend/src/utils/sparePartHelpers.js +5 -0
- package/templates/sims-app/frontend/index.html +13 -0
- package/templates/sims-app/frontend/package.json +31 -0
- package/templates/sims-app/frontend/src/App.jsx +110 -0
- package/templates/sims-app/frontend/src/api/authApi.js +7 -0
- package/templates/sims-app/frontend/src/api/client.js +8 -0
- package/templates/sims-app/frontend/src/api/simsReportApi.js +5 -0
- package/templates/sims-app/frontend/src/api/sparePartsApi.js +4 -0
- package/templates/sims-app/frontend/src/api/stockInApi.js +4 -0
- package/templates/sims-app/frontend/src/api/stockOutApi.js +6 -0
- package/templates/sims-app/frontend/src/api/usersApi.js +3 -0
- package/templates/sims-app/frontend/src/components/AppLayout.jsx +47 -0
- package/templates/sims-app/frontend/src/index.css +7 -0
- package/templates/sims-app/frontend/src/main.jsx +13 -0
- package/templates/sims-app/frontend/src/pages/ForgotPassword.jsx +111 -0
- package/templates/sims-app/frontend/src/pages/LoginPage.jsx +71 -0
- package/templates/sims-app/frontend/src/pages/RegisterPage.jsx +99 -0
- package/templates/sims-app/frontend/src/pages/ReportsPage.jsx +120 -0
- package/templates/sims-app/frontend/src/pages/SparePartPage.jsx +148 -0
- package/templates/sims-app/frontend/src/pages/StockInPage.jsx +122 -0
- package/templates/sims-app/frontend/src/pages/StockOutPage.jsx +252 -0
- package/templates/sims-app/frontend/src/utils/passwordPolicy.js +8 -0
- package/templates/sims-app/frontend/vite.config.js +8 -0
- package/templates/smartshop-app/README.md +61 -0
- package/templates/smartshop-app/backend/.env +7 -0
- package/templates/smartshop-app/backend/.env.example +7 -0
- package/templates/smartshop-app/backend/database/schema.sql +46 -0
- package/templates/smartshop-app/backend/package-lock.json +1487 -0
- package/templates/smartshop-app/backend/package.json +26 -0
- package/templates/smartshop-app/backend/src/app.js +57 -0
- package/templates/smartshop-app/backend/src/config/db.js +52 -0
- package/templates/smartshop-app/backend/src/controllers/authController.js +98 -0
- package/templates/smartshop-app/backend/src/controllers/customerController.js +26 -0
- package/templates/smartshop-app/backend/src/controllers/productController.js +21 -0
- package/templates/smartshop-app/backend/src/controllers/reportController.js +29 -0
- package/templates/smartshop-app/backend/src/controllers/saleController.js +11 -0
- package/templates/smartshop-app/backend/src/middleware/authMiddleware.js +22 -0
- package/templates/smartshop-app/backend/src/models/authModel.js +24 -0
- package/templates/smartshop-app/backend/src/models/customerModel.js +43 -0
- package/templates/smartshop-app/backend/src/models/productModel.js +37 -0
- package/templates/smartshop-app/backend/src/models/reportModel.js +56 -0
- package/templates/smartshop-app/backend/src/models/saleModel.js +54 -0
- package/templates/smartshop-app/backend/src/routes/authRoutes.js +10 -0
- package/templates/smartshop-app/backend/src/routes/customerRoutes.js +16 -0
- package/templates/smartshop-app/backend/src/routes/productRoutes.js +16 -0
- package/templates/smartshop-app/backend/src/routes/reportRoutes.js +18 -0
- package/templates/smartshop-app/backend/src/routes/saleRoutes.js +9 -0
- package/templates/smartshop-app/backend/src/server.js +19 -0
- package/templates/smartshop-app/frontend/README.md +18 -0
- package/templates/smartshop-app/frontend/eslint.config.js +21 -0
- package/templates/smartshop-app/frontend/index.html +13 -0
- package/templates/smartshop-app/frontend/package-lock.json +3415 -0
- package/templates/smartshop-app/frontend/package.json +34 -0
- package/templates/smartshop-app/frontend/public/favicon.svg +1 -0
- package/templates/smartshop-app/frontend/public/icons.svg +24 -0
- package/templates/smartshop-app/frontend/src/App.css +184 -0
- package/templates/smartshop-app/frontend/src/App.jsx +41 -0
- package/templates/smartshop-app/frontend/src/assets/hero.png +0 -0
- package/templates/smartshop-app/frontend/src/assets/react.svg +1 -0
- package/templates/smartshop-app/frontend/src/assets/vite.svg +1 -0
- package/templates/smartshop-app/frontend/src/components/AppLayout.jsx +71 -0
- package/templates/smartshop-app/frontend/src/components/FormCard.jsx +12 -0
- package/templates/smartshop-app/frontend/src/components/StatCard.jsx +10 -0
- package/templates/smartshop-app/frontend/src/index.css +28 -0
- package/templates/smartshop-app/frontend/src/main.jsx +13 -0
- package/templates/smartshop-app/frontend/src/pages/CustomersPage.jsx +175 -0
- package/templates/smartshop-app/frontend/src/pages/DashboardPage.jsx +30 -0
- package/templates/smartshop-app/frontend/src/pages/ForgotPassword.jsx +102 -0
- package/templates/smartshop-app/frontend/src/pages/LoginPage.jsx +142 -0
- package/templates/smartshop-app/frontend/src/pages/ProductsPage.jsx +165 -0
- package/templates/smartshop-app/frontend/src/pages/ReportsPage.jsx +204 -0
- package/templates/smartshop-app/frontend/src/pages/SalesPage.jsx +153 -0
- package/templates/smartshop-app/frontend/src/services/api.js +15 -0
- package/templates/smartshop-app/frontend/vite.config.js +13 -0
- package/templates/srms-app/.env +7 -0
- package/templates/srms-app/README.md +82 -0
- package/templates/srms-app/backend-mongodb/.env +3 -0
- package/templates/srms-app/backend-mongodb/.env.example +3 -0
- package/templates/srms-app/backend-mongodb/config/db.js +29 -0
- package/templates/srms-app/backend-mongodb/controllers/authController.js +93 -0
- package/templates/srms-app/backend-mongodb/controllers/customerController.js +27 -0
- package/templates/srms-app/backend-mongodb/controllers/productController.js +26 -0
- package/templates/srms-app/backend-mongodb/controllers/reportController.js +44 -0
- package/templates/srms-app/backend-mongodb/controllers/saleController.js +72 -0
- package/templates/srms-app/backend-mongodb/middleware/auth.js +16 -0
- package/templates/srms-app/backend-mongodb/models/Customer.js +14 -0
- package/templates/srms-app/backend-mongodb/models/Product.js +13 -0
- package/templates/srms-app/backend-mongodb/models/Sale.js +15 -0
- package/templates/srms-app/backend-mongodb/models/User.js +9 -0
- package/templates/srms-app/backend-mongodb/package-lock.json +1571 -0
- package/templates/srms-app/backend-mongodb/package.json +22 -0
- package/templates/srms-app/backend-mongodb/routes/authRoutes.js +8 -0
- package/templates/srms-app/backend-mongodb/routes/customerRoutes.js +6 -0
- package/templates/srms-app/backend-mongodb/routes/productRoutes.js +6 -0
- package/templates/srms-app/backend-mongodb/routes/reportRoutes.js +5 -0
- package/templates/srms-app/backend-mongodb/routes/saleRoutes.js +8 -0
- package/templates/srms-app/backend-mongodb/server.js +39 -0
- package/templates/srms-app/backend-mysql/.env +7 -0
- package/templates/srms-app/backend-mysql/.env.example +7 -0
- package/templates/srms-app/backend-mysql/config/db.js +33 -0
- package/templates/srms-app/backend-mysql/controllers/authController.js +98 -0
- package/templates/srms-app/backend-mysql/controllers/customerController.js +28 -0
- package/templates/srms-app/backend-mysql/controllers/productController.js +27 -0
- package/templates/srms-app/backend-mysql/controllers/reportController.js +29 -0
- package/templates/srms-app/backend-mysql/controllers/saleController.js +68 -0
- package/templates/srms-app/backend-mysql/database/schema.sql +7 -0
- package/templates/srms-app/backend-mysql/middleware/auth.js +16 -0
- package/templates/srms-app/backend-mysql/package-lock.json +1486 -0
- package/templates/srms-app/backend-mysql/package.json +23 -0
- package/templates/srms-app/backend-mysql/routes/authRoutes.js +8 -0
- package/templates/srms-app/backend-mysql/routes/customerRoutes.js +6 -0
- package/templates/srms-app/backend-mysql/routes/productRoutes.js +6 -0
- package/templates/srms-app/backend-mysql/routes/reportRoutes.js +5 -0
- package/templates/srms-app/backend-mysql/routes/saleRoutes.js +8 -0
- package/templates/srms-app/backend-mysql/server.js +39 -0
- package/templates/srms-app/frontend/index.html +12 -0
- package/templates/srms-app/frontend/package-lock.json +1634 -0
- package/templates/srms-app/frontend/package.json +23 -0
- package/templates/srms-app/frontend/src/App.jsx +31 -0
- package/templates/srms-app/frontend/src/api/client.js +11 -0
- package/templates/srms-app/frontend/src/components/AppLayout.jsx +40 -0
- package/templates/srms-app/frontend/src/context/AuthContext.jsx +41 -0
- package/templates/srms-app/frontend/src/hooks/.gitkeep +0 -0
- package/templates/srms-app/frontend/src/index.css +2 -0
- package/templates/srms-app/frontend/src/main.jsx +16 -0
- package/templates/srms-app/frontend/src/pages/CustomersPage.jsx +160 -0
- package/templates/srms-app/frontend/src/pages/ForgotPassword.jsx +103 -0
- package/templates/srms-app/frontend/src/pages/LoginPage.jsx +105 -0
- package/templates/srms-app/frontend/src/pages/ProductsPage.jsx +158 -0
- package/templates/srms-app/frontend/src/pages/ReportsPage.jsx +192 -0
- package/templates/srms-app/frontend/src/pages/SalesPage.jsx +310 -0
- package/templates/srms-app/frontend/vite.config.js +8 -0
- package/templates/stockhub-sms-app/.env +7 -0
- package/templates/stockhub-sms-app/README.md +82 -0
- package/templates/stockhub-sms-app/backend-mongodb/.env +3 -0
- package/templates/stockhub-sms-app/backend-mongodb/.env.example +3 -0
- package/templates/stockhub-sms-app/backend-mongodb/config/db.js +29 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/authController.js +93 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/productController.js +29 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/reportController.js +53 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/transactionController.js +74 -0
- package/templates/stockhub-sms-app/backend-mongodb/controllers/warehouseController.js +25 -0
- package/templates/stockhub-sms-app/backend-mongodb/middleware/auth.js +16 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/Counter.js +13 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/Product.js +16 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/StockTransaction.js +19 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/User.js +9 -0
- package/templates/stockhub-sms-app/backend-mongodb/models/Warehouse.js +12 -0
- package/templates/stockhub-sms-app/backend-mongodb/package-lock.json +1571 -0
- package/templates/stockhub-sms-app/backend-mongodb/package.json +22 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/authRoutes.js +8 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/productRoutes.js +6 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/reportRoutes.js +5 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/transactionRoutes.js +8 -0
- package/templates/stockhub-sms-app/backend-mongodb/routes/warehouseRoutes.js +6 -0
- package/templates/stockhub-sms-app/backend-mongodb/server.js +39 -0
- package/templates/stockhub-sms-app/backend-mysql/.env +7 -0
- package/templates/stockhub-sms-app/backend-mysql/.env.example +7 -0
- package/templates/stockhub-sms-app/backend-mysql/config/db.js +33 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/authController.js +98 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/productController.js +30 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/reportController.js +53 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/transactionController.js +70 -0
- package/templates/stockhub-sms-app/backend-mysql/controllers/warehouseController.js +26 -0
- package/templates/stockhub-sms-app/backend-mysql/database/schema.sql +40 -0
- package/templates/stockhub-sms-app/backend-mysql/middleware/auth.js +16 -0
- package/templates/stockhub-sms-app/backend-mysql/package-lock.json +1486 -0
- package/templates/stockhub-sms-app/backend-mysql/package.json +23 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/authRoutes.js +8 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/productRoutes.js +6 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/reportRoutes.js +5 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/transactionRoutes.js +8 -0
- package/templates/stockhub-sms-app/backend-mysql/routes/warehouseRoutes.js +6 -0
- package/templates/stockhub-sms-app/backend-mysql/server.js +39 -0
- package/templates/stockhub-sms-app/frontend/index.html +12 -0
- package/templates/stockhub-sms-app/frontend/package-lock.json +1634 -0
- package/templates/stockhub-sms-app/frontend/package.json +23 -0
- package/templates/stockhub-sms-app/frontend/src/App.jsx +31 -0
- package/templates/stockhub-sms-app/frontend/src/api/client.js +11 -0
- package/templates/stockhub-sms-app/frontend/src/components/AppLayout.jsx +40 -0
- package/templates/stockhub-sms-app/frontend/src/context/AuthContext.jsx +41 -0
- package/templates/stockhub-sms-app/frontend/src/hooks/.gitkeep +0 -0
- package/templates/stockhub-sms-app/frontend/src/index.css +13 -0
- package/templates/stockhub-sms-app/frontend/src/main.jsx +16 -0
- package/templates/stockhub-sms-app/frontend/src/pages/ForgotPassword.jsx +103 -0
- package/templates/stockhub-sms-app/frontend/src/pages/LoginPage.jsx +105 -0
- package/templates/stockhub-sms-app/frontend/src/pages/ProductsPage.jsx +132 -0
- package/templates/stockhub-sms-app/frontend/src/pages/ReportsPage.jsx +177 -0
- package/templates/stockhub-sms-app/frontend/src/pages/TransactionsPage.jsx +270 -0
- package/templates/stockhub-sms-app/frontend/src/pages/WarehousesPage.jsx +116 -0
- package/templates/stockhub-sms-app/frontend/vite.config.js +8 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const SparePart = require("../models/SparePart");
|
|
2
|
+
const StockIn = require("../models/StockIn");
|
|
3
|
+
const StockOut = require("../models/StockOut");
|
|
4
|
+
|
|
5
|
+
const dayRange = (dateStr) => {
|
|
6
|
+
const d = new Date(String(dateStr));
|
|
7
|
+
if (Number.isNaN(d.getTime())) return null;
|
|
8
|
+
const start = new Date(d);
|
|
9
|
+
start.setHours(0, 0, 0, 0);
|
|
10
|
+
const end = new Date(start);
|
|
11
|
+
end.setDate(end.getDate() + 1);
|
|
12
|
+
return { start, end };
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const dailyStockStatus = async (req, res) => {
|
|
16
|
+
try {
|
|
17
|
+
const { date } = req.query;
|
|
18
|
+
if (!date) {
|
|
19
|
+
return res.status(400).json({ message: "date query (YYYY-MM-DD) is required" });
|
|
20
|
+
}
|
|
21
|
+
const range = dayRange(date);
|
|
22
|
+
if (!range) {
|
|
23
|
+
return res.status(400).json({ message: "Invalid date" });
|
|
24
|
+
}
|
|
25
|
+
const parts = await SparePart.find();
|
|
26
|
+
const rows = [];
|
|
27
|
+
for (const p of parts) {
|
|
28
|
+
const inSum = await StockIn.aggregate([
|
|
29
|
+
{
|
|
30
|
+
$match: {
|
|
31
|
+
sparePart: p._id,
|
|
32
|
+
stockInDate: { $gte: range.start, $lt: range.end },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{ $group: { _id: null, total: { $sum: "$stockInQuantity" } } },
|
|
36
|
+
]);
|
|
37
|
+
const outSum = await StockOut.aggregate([
|
|
38
|
+
{
|
|
39
|
+
$match: {
|
|
40
|
+
sparePart: p._id,
|
|
41
|
+
stockOutDate: { $gte: range.start, $lt: range.end },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{ $group: { _id: null, total: { $sum: "$stockOutQuantity" } } },
|
|
45
|
+
]);
|
|
46
|
+
const stockInDay = inSum[0]?.total || 0;
|
|
47
|
+
const stockOutDay = outSum[0]?.total || 0;
|
|
48
|
+
rows.push({
|
|
49
|
+
spareName: p.name,
|
|
50
|
+
category: p.category,
|
|
51
|
+
storedQuantity: p.quantity,
|
|
52
|
+
stockInQuantity: stockInDay,
|
|
53
|
+
stockOutQuantity: stockOutDay,
|
|
54
|
+
remainingQuantity: p.quantity,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return res.json(rows);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return res.status(500).json({ message: error.message });
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const dailyStockOut = async (req, res) => {
|
|
64
|
+
try {
|
|
65
|
+
const { date } = req.query;
|
|
66
|
+
if (!date) {
|
|
67
|
+
return res.status(400).json({ message: "date query (YYYY-MM-DD) is required" });
|
|
68
|
+
}
|
|
69
|
+
const range = dayRange(date);
|
|
70
|
+
if (!range) {
|
|
71
|
+
return res.status(400).json({ message: "Invalid date" });
|
|
72
|
+
}
|
|
73
|
+
const list = await StockOut.find({
|
|
74
|
+
stockOutDate: { $gte: range.start, $lt: range.end },
|
|
75
|
+
})
|
|
76
|
+
.populate("sparePart", "name category")
|
|
77
|
+
.sort({ stockOutDate: 1 });
|
|
78
|
+
return res.json(
|
|
79
|
+
list.map((r) => ({
|
|
80
|
+
id: r._id,
|
|
81
|
+
spareName: r.sparePart?.name || "",
|
|
82
|
+
category: r.sparePart?.category || "",
|
|
83
|
+
stockOutQuantity: r.stockOutQuantity,
|
|
84
|
+
stockOutUnitPrice: r.stockOutUnitPrice,
|
|
85
|
+
stockOutTotalPrice: r.stockOutTotalPrice,
|
|
86
|
+
stockOutDate: r.stockOutDate,
|
|
87
|
+
}))
|
|
88
|
+
);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return res.status(500).json({ message: error.message });
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
module.exports = { dailyStockStatus, dailyStockOut };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const SparePart = require("../models/SparePart");
|
|
2
|
+
const { recalcPartTotals } = require("../utils/sparePartHelpers");
|
|
3
|
+
|
|
4
|
+
const create = async (req, res) => {
|
|
5
|
+
try {
|
|
6
|
+
const { name, category, quantity, unitPrice } = req.body;
|
|
7
|
+
if (!name || !category || quantity === undefined || unitPrice === undefined) {
|
|
8
|
+
return res.status(400).json({ message: "Name, category, quantity, and unit price are required" });
|
|
9
|
+
}
|
|
10
|
+
const q = Number(quantity);
|
|
11
|
+
const u = Number(unitPrice);
|
|
12
|
+
if (Number.isNaN(q) || q < 0 || Number.isNaN(u) || u < 0) {
|
|
13
|
+
return res.status(400).json({ message: "Invalid quantity or unit price" });
|
|
14
|
+
}
|
|
15
|
+
const t = q * u;
|
|
16
|
+
const part = await SparePart.create({
|
|
17
|
+
name: String(name).trim(),
|
|
18
|
+
category: String(category).trim(),
|
|
19
|
+
quantity: q,
|
|
20
|
+
unitPrice: u,
|
|
21
|
+
totalPrice: t,
|
|
22
|
+
});
|
|
23
|
+
return res.status(201).json(part);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error.code === 11000) {
|
|
26
|
+
return res.status(409).json({ message: "A spare part with this name and category already exists" });
|
|
27
|
+
}
|
|
28
|
+
return res.status(500).json({ message: error.message });
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const list = async (_req, res) => {
|
|
33
|
+
try {
|
|
34
|
+
const items = await SparePart.find().sort({ name: 1 });
|
|
35
|
+
return res.json(items);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
return res.status(500).json({ message: error.message });
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
module.exports = { create, list };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const SparePart = require("../models/SparePart");
|
|
2
|
+
const StockIn = require("../models/StockIn");
|
|
3
|
+
const { recalcPartTotals } = require("../utils/sparePartHelpers");
|
|
4
|
+
|
|
5
|
+
const create = async (req, res) => {
|
|
6
|
+
try {
|
|
7
|
+
const { sparePartId, stockInQuantity, stockInDate } = req.body;
|
|
8
|
+
if (!sparePartId || stockInQuantity === undefined || !stockInDate) {
|
|
9
|
+
return res.status(400).json({ message: "Spare part, stock-in quantity, and date are required" });
|
|
10
|
+
}
|
|
11
|
+
const qty = Number(stockInQuantity);
|
|
12
|
+
if (Number.isNaN(qty) || qty < 1) {
|
|
13
|
+
return res.status(400).json({ message: "Stock-in quantity must be at least 1" });
|
|
14
|
+
}
|
|
15
|
+
const part = await SparePart.findById(sparePartId);
|
|
16
|
+
if (!part) {
|
|
17
|
+
return res.status(404).json({ message: "Spare part not found" });
|
|
18
|
+
}
|
|
19
|
+
part.quantity += qty;
|
|
20
|
+
recalcPartTotals(part);
|
|
21
|
+
await part.save();
|
|
22
|
+
|
|
23
|
+
const record = await StockIn.create({
|
|
24
|
+
sparePart: sparePartId,
|
|
25
|
+
stockInQuantity: qty,
|
|
26
|
+
stockInDate: new Date(stockInDate),
|
|
27
|
+
});
|
|
28
|
+
return res.status(201).json(record);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return res.status(500).json({ message: error.message });
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const list = async (_req, res) => {
|
|
35
|
+
try {
|
|
36
|
+
const list = await StockIn.find()
|
|
37
|
+
.populate("sparePart", "name category")
|
|
38
|
+
.sort({ stockInDate: -1 });
|
|
39
|
+
return res.json(list);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return res.status(500).json({ message: error.message });
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
module.exports = { create, list };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const SparePart = require("../models/SparePart");
|
|
2
|
+
const StockOut = require("../models/StockOut");
|
|
3
|
+
const { recalcPartTotals } = require("../utils/sparePartHelpers");
|
|
4
|
+
|
|
5
|
+
const create = async (req, res) => {
|
|
6
|
+
try {
|
|
7
|
+
const { sparePartId, stockOutQuantity, stockOutUnitPrice, stockOutDate } = req.body;
|
|
8
|
+
if (!sparePartId || stockOutQuantity === undefined || stockOutUnitPrice === undefined || !stockOutDate) {
|
|
9
|
+
return res
|
|
10
|
+
.status(400)
|
|
11
|
+
.json({ message: "Spare part, quantity, unit price, and date are required" });
|
|
12
|
+
}
|
|
13
|
+
const qty = Number(stockOutQuantity);
|
|
14
|
+
const unit = Number(stockOutUnitPrice);
|
|
15
|
+
if (Number.isNaN(qty) || qty < 1) {
|
|
16
|
+
return res.status(400).json({ message: "Invalid stock-out quantity" });
|
|
17
|
+
}
|
|
18
|
+
if (Number.isNaN(unit) || unit < 0) {
|
|
19
|
+
return res.status(400).json({ message: "Invalid unit price" });
|
|
20
|
+
}
|
|
21
|
+
const part = await SparePart.findById(sparePartId);
|
|
22
|
+
if (!part) {
|
|
23
|
+
return res.status(404).json({ message: "Spare part not found" });
|
|
24
|
+
}
|
|
25
|
+
if (part.quantity < qty) {
|
|
26
|
+
return res.status(400).json({ message: "Not enough quantity in stock" });
|
|
27
|
+
}
|
|
28
|
+
part.quantity -= qty;
|
|
29
|
+
recalcPartTotals(part);
|
|
30
|
+
await part.save();
|
|
31
|
+
const total = qty * unit;
|
|
32
|
+
const record = await StockOut.create({
|
|
33
|
+
sparePart: sparePartId,
|
|
34
|
+
stockOutQuantity: qty,
|
|
35
|
+
stockOutUnitPrice: unit,
|
|
36
|
+
stockOutTotalPrice: total,
|
|
37
|
+
stockOutDate: new Date(stockOutDate),
|
|
38
|
+
});
|
|
39
|
+
return res.status(201).json(record);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return res.status(500).json({ message: error.message });
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const list = async (_req, res) => {
|
|
46
|
+
try {
|
|
47
|
+
const list = await StockOut.find()
|
|
48
|
+
.populate("sparePart", "name category")
|
|
49
|
+
.sort({ stockOutDate: -1 });
|
|
50
|
+
return res.json(list);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return res.status(500).json({ message: error.message });
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const update = async (req, res) => {
|
|
57
|
+
try {
|
|
58
|
+
const current = await StockOut.findById(req.params.id);
|
|
59
|
+
if (!current) {
|
|
60
|
+
return res.status(404).json({ message: "Stock out not found" });
|
|
61
|
+
}
|
|
62
|
+
const part = await SparePart.findById(current.sparePart);
|
|
63
|
+
if (!part) {
|
|
64
|
+
return res.status(404).json({ message: "Spare part not found" });
|
|
65
|
+
}
|
|
66
|
+
part.quantity += current.stockOutQuantity;
|
|
67
|
+
recalcPartTotals(part);
|
|
68
|
+
|
|
69
|
+
const qty = Number(req.body.stockOutQuantity);
|
|
70
|
+
const unit = Number(req.body.stockOutUnitPrice);
|
|
71
|
+
const failRestore = async () => {
|
|
72
|
+
part.quantity -= current.stockOutQuantity;
|
|
73
|
+
recalcPartTotals(part);
|
|
74
|
+
await part.save();
|
|
75
|
+
};
|
|
76
|
+
if (Number.isNaN(qty) || qty < 1) {
|
|
77
|
+
await failRestore();
|
|
78
|
+
return res.status(400).json({ message: "Invalid stock-out quantity" });
|
|
79
|
+
}
|
|
80
|
+
if (Number.isNaN(unit) || unit < 0) {
|
|
81
|
+
await failRestore();
|
|
82
|
+
return res.status(400).json({ message: "Invalid unit price" });
|
|
83
|
+
}
|
|
84
|
+
if (part.quantity < qty) {
|
|
85
|
+
await failRestore();
|
|
86
|
+
return res.status(400).json({ message: "Not enough quantity in stock" });
|
|
87
|
+
}
|
|
88
|
+
part.quantity -= qty;
|
|
89
|
+
recalcPartTotals(part);
|
|
90
|
+
await part.save();
|
|
91
|
+
if (req.body.stockOutDate) {
|
|
92
|
+
current.stockOutDate = new Date(req.body.stockOutDate);
|
|
93
|
+
}
|
|
94
|
+
current.stockOutQuantity = qty;
|
|
95
|
+
current.stockOutUnitPrice = unit;
|
|
96
|
+
current.stockOutTotalPrice = qty * unit;
|
|
97
|
+
await current.save();
|
|
98
|
+
return res.json(current);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return res.status(500).json({ message: error.message });
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const remove = async (req, res) => {
|
|
105
|
+
try {
|
|
106
|
+
const current = await StockOut.findById(req.params.id);
|
|
107
|
+
if (!current) {
|
|
108
|
+
return res.status(404).json({ message: "Stock out not found" });
|
|
109
|
+
}
|
|
110
|
+
const part = await SparePart.findById(current.sparePart);
|
|
111
|
+
if (part) {
|
|
112
|
+
part.quantity += current.stockOutQuantity;
|
|
113
|
+
recalcPartTotals(part);
|
|
114
|
+
await part.save();
|
|
115
|
+
}
|
|
116
|
+
await StockOut.findByIdAndDelete(req.params.id);
|
|
117
|
+
return res.json({ message: "Stock out removed" });
|
|
118
|
+
} catch (error) {
|
|
119
|
+
return res.status(500).json({ message: error.message });
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
module.exports = { create, list, update, remove };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
const sparePartSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
name: { type: String, required: true, trim: true },
|
|
6
|
+
category: { type: String, required: true, trim: true },
|
|
7
|
+
quantity: { type: Number, required: true, min: 0, default: 0 },
|
|
8
|
+
unitPrice: { type: Number, required: true, min: 0 },
|
|
9
|
+
totalPrice: { type: Number, required: true, min: 0 },
|
|
10
|
+
},
|
|
11
|
+
{ timestamps: true }
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
// Helps satisfy “duplicate data entry is eliminated” (assessment checklist 2.12)
|
|
15
|
+
sparePartSchema.index({ name: 1, category: 1 }, { unique: true });
|
|
16
|
+
|
|
17
|
+
module.exports = mongoose.model("SparePart", sparePartSchema);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
const stockInSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
sparePart: {
|
|
6
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
7
|
+
ref: "SparePart",
|
|
8
|
+
required: true,
|
|
9
|
+
},
|
|
10
|
+
stockInQuantity: { type: Number, required: true, min: 1 },
|
|
11
|
+
stockInDate: { type: Date, required: true },
|
|
12
|
+
},
|
|
13
|
+
{ timestamps: true }
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
module.exports = mongoose.model("StockIn", stockInSchema);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
const stockOutSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
sparePart: {
|
|
6
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
7
|
+
ref: "SparePart",
|
|
8
|
+
required: true,
|
|
9
|
+
},
|
|
10
|
+
stockOutQuantity: { type: Number, required: true, min: 1 },
|
|
11
|
+
stockOutUnitPrice: { type: Number, required: true, min: 0 },
|
|
12
|
+
stockOutTotalPrice: { type: Number, required: true, min: 0 },
|
|
13
|
+
stockOutDate: { type: Date, required: true },
|
|
14
|
+
},
|
|
15
|
+
{ timestamps: true }
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
module.exports = mongoose.model("StockOut", stockOutSchema);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
const userSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
username: { type: String, required: true, unique: true, trim: true },
|
|
6
|
+
email: { type: String, required: true, unique: true, lowercase: true, trim: true },
|
|
7
|
+
passwordHash: { type: String, required: true },
|
|
8
|
+
},
|
|
9
|
+
{ timestamps: true }
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
module.exports = mongoose.model("User", userSchema);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const authController = require("../controllers/authController");
|
|
3
|
+
|
|
4
|
+
const router = express.Router();
|
|
5
|
+
|
|
6
|
+
router.post("/register", authController.register);
|
|
7
|
+
router.post("/login", authController.login);
|
|
8
|
+
router.get("/me", authController.currentUser);
|
|
9
|
+
router.post("/logout", authController.logout);
|
|
10
|
+
router.post("/forgot-password", authController.forgotPassword);
|
|
11
|
+
|
|
12
|
+
module.exports = router;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const simsReportController = require("../controllers/simsReportController");
|
|
3
|
+
const requireAuth = require("../middleware/auth");
|
|
4
|
+
|
|
5
|
+
const router = express.Router();
|
|
6
|
+
router.get("/daily-stock-status", requireAuth, simsReportController.dailyStockStatus);
|
|
7
|
+
router.get("/daily-stockout", requireAuth, simsReportController.dailyStockOut);
|
|
8
|
+
module.exports = router;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const sparePartController = require("../controllers/sparePartController");
|
|
3
|
+
const requireAuth = require("../middleware/auth");
|
|
4
|
+
|
|
5
|
+
const router = express.Router();
|
|
6
|
+
router.post("/", requireAuth, sparePartController.create);
|
|
7
|
+
router.get("/", requireAuth, sparePartController.list);
|
|
8
|
+
module.exports = router;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const stockInController = require("../controllers/stockInController");
|
|
3
|
+
const requireAuth = require("../middleware/auth");
|
|
4
|
+
|
|
5
|
+
const router = express.Router();
|
|
6
|
+
router.post("/", requireAuth, stockInController.create);
|
|
7
|
+
router.get("/", requireAuth, stockInController.list);
|
|
8
|
+
module.exports = router;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const stockOutController = require("../controllers/stockOutController");
|
|
3
|
+
const requireAuth = require("../middleware/auth");
|
|
4
|
+
|
|
5
|
+
const router = express.Router();
|
|
6
|
+
router.post("/", requireAuth, stockOutController.create);
|
|
7
|
+
router.get("/", requireAuth, stockOutController.list);
|
|
8
|
+
router.put("/:id", requireAuth, stockOutController.update);
|
|
9
|
+
router.delete("/:id", requireAuth, stockOutController.remove);
|
|
10
|
+
module.exports = router;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const cors = require("cors");
|
|
3
|
+
const session = require("express-session");
|
|
4
|
+
const connectMongo = require("connect-mongo");
|
|
5
|
+
const dotenv = require("dotenv");
|
|
6
|
+
const connectDatabase = require("./config/db");
|
|
7
|
+
const authRoutes = require("./routes/authRoutes");
|
|
8
|
+
const sparePartRoutes = require("./routes/sparePartRoutes");
|
|
9
|
+
const stockInRoutes = require("./routes/stockInRoutes");
|
|
10
|
+
const stockOutRoutes = require("./routes/stockOutRoutes");
|
|
11
|
+
const simsReportRoutes = require("./routes/simsReportRoutes");
|
|
12
|
+
|
|
13
|
+
dotenv.config();
|
|
14
|
+
|
|
15
|
+
const app = express();
|
|
16
|
+
const PORT = process.env.PORT || 5001;
|
|
17
|
+
const FRONTEND_URL = process.env.FRONTEND_URL || "http://localhost:5174";
|
|
18
|
+
const MongoStore = connectMongo.default || connectMongo.MongoStore || connectMongo;
|
|
19
|
+
const MONGO_URI = process.env.MONGO_URI || "mongodb://127.0.0.1:27017/sims";
|
|
20
|
+
|
|
21
|
+
app.use(
|
|
22
|
+
cors({
|
|
23
|
+
origin: FRONTEND_URL,
|
|
24
|
+
credentials: true,
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
app.use(express.json());
|
|
28
|
+
app.set("trust proxy", 1);
|
|
29
|
+
app.use(
|
|
30
|
+
session({
|
|
31
|
+
name: "sims.sid",
|
|
32
|
+
secret: process.env.SESSION_SECRET || "sims-exam-secret",
|
|
33
|
+
resave: false,
|
|
34
|
+
saveUninitialized: false,
|
|
35
|
+
store: MongoStore.create({ mongoUrl: MONGO_URI }),
|
|
36
|
+
cookie: {
|
|
37
|
+
httpOnly: true,
|
|
38
|
+
sameSite: "lax",
|
|
39
|
+
maxAge: 1000 * 60 * 60 * 8,
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
app.get("/api/health", (_req, res) => {
|
|
45
|
+
res.json({ message: "SIMS API is running" });
|
|
46
|
+
});
|
|
47
|
+
app.use("/api/auth", authRoutes);
|
|
48
|
+
app.use("/api/spare-parts", sparePartRoutes);
|
|
49
|
+
app.use("/api/stock-in", stockInRoutes);
|
|
50
|
+
app.use("/api/stock-out", stockOutRoutes);
|
|
51
|
+
app.use("/api/reports", simsReportRoutes);
|
|
52
|
+
|
|
53
|
+
connectDatabase()
|
|
54
|
+
.then(() => {
|
|
55
|
+
app.listen(PORT, () => {
|
|
56
|
+
console.log(`SIMS server running on port ${PORT}`);
|
|
57
|
+
});
|
|
58
|
+
})
|
|
59
|
+
.catch((error) => {
|
|
60
|
+
console.error("Failed to start server:", error.message);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const strongPasswordError = (password) => {
|
|
2
|
+
const p = String(password || "");
|
|
3
|
+
if (p.length < 8) return "Password must be at least 8 characters (strong password required)";
|
|
4
|
+
if (!/[A-Z]/.test(p)) return "Password must include an uppercase letter";
|
|
5
|
+
if (!/[a-z]/.test(p)) return "Password must include a lowercase letter";
|
|
6
|
+
if (!/[0-9]/.test(p)) return "Password must include a number";
|
|
7
|
+
return null;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
module.exports = { strongPasswordError };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>SIMS — Stock Inventory</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sims-frontend",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"lint": "eslint .",
|
|
10
|
+
"preview": "vite preview"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@tailwindcss/vite": "^4.2.4",
|
|
14
|
+
"axios": "^1.15.2",
|
|
15
|
+
"react": "^19.2.5",
|
|
16
|
+
"react-dom": "^19.2.5",
|
|
17
|
+
"react-router-dom": "^7.14.2",
|
|
18
|
+
"tailwindcss": "^4.2.4"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@eslint/js": "^10.0.1",
|
|
22
|
+
"@types/react": "^19.2.14",
|
|
23
|
+
"@types/react-dom": "^19.2.3",
|
|
24
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
25
|
+
"eslint": "^10.2.0",
|
|
26
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
27
|
+
"eslint-plugin-react-refresh": "^0.5.2",
|
|
28
|
+
"globals": "^17.5.0",
|
|
29
|
+
"vite": "^8.0.10"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { Navigate, Route, Routes } from "react-router-dom";
|
|
3
|
+
import AppLayout from "./components/AppLayout";
|
|
4
|
+
import LoginPage from "./pages/LoginPage";
|
|
5
|
+
import RegisterPage from "./pages/RegisterPage";
|
|
6
|
+
import ForgotPassword from "./pages/ForgotPassword";
|
|
7
|
+
import SparePartPage from "./pages/SparePartPage";
|
|
8
|
+
import StockInPage from "./pages/StockInPage";
|
|
9
|
+
import StockOutPage from "./pages/StockOutPage";
|
|
10
|
+
import ReportsPage from "./pages/ReportsPage";
|
|
11
|
+
import { fetchCurrentUser, logoutUser } from "./api/authApi";
|
|
12
|
+
|
|
13
|
+
function ProtectedLayout({ isAuthenticated, username, onLogout }) {
|
|
14
|
+
if (!isAuthenticated) {
|
|
15
|
+
return <Navigate to="/login" replace />;
|
|
16
|
+
}
|
|
17
|
+
return <AppLayout onLogout={onLogout} username={username} />;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function PublicRoute({ isAuthenticated, children }) {
|
|
21
|
+
if (isAuthenticated) {
|
|
22
|
+
return <Navigate to="/spare-part" replace />;
|
|
23
|
+
}
|
|
24
|
+
return children;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function App() {
|
|
28
|
+
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
29
|
+
const [username, setUsername] = useState("");
|
|
30
|
+
const [loading, setLoading] = useState(true);
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
(async () => {
|
|
34
|
+
try {
|
|
35
|
+
const r = await fetchCurrentUser();
|
|
36
|
+
setIsAuthenticated(true);
|
|
37
|
+
setUsername(r.data.username);
|
|
38
|
+
} catch {
|
|
39
|
+
setIsAuthenticated(false);
|
|
40
|
+
} finally {
|
|
41
|
+
setLoading(false);
|
|
42
|
+
}
|
|
43
|
+
})();
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const handleLogout = async () => {
|
|
47
|
+
await logoutUser();
|
|
48
|
+
setIsAuthenticated(false);
|
|
49
|
+
setUsername("");
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
if (loading) {
|
|
53
|
+
return <div className="p-8 text-center text-slate-600">Checking session…</div>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Routes>
|
|
58
|
+
<Route
|
|
59
|
+
path="/login"
|
|
60
|
+
element={
|
|
61
|
+
<PublicRoute isAuthenticated={isAuthenticated}>
|
|
62
|
+
<LoginPage
|
|
63
|
+
onLoginSuccess={(name) => {
|
|
64
|
+
setIsAuthenticated(true);
|
|
65
|
+
setUsername(name);
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
</PublicRoute>
|
|
69
|
+
}
|
|
70
|
+
/>
|
|
71
|
+
<Route
|
|
72
|
+
path="/register"
|
|
73
|
+
element={
|
|
74
|
+
<PublicRoute isAuthenticated={isAuthenticated}>
|
|
75
|
+
<RegisterPage />
|
|
76
|
+
</PublicRoute>
|
|
77
|
+
}
|
|
78
|
+
/>
|
|
79
|
+
<Route
|
|
80
|
+
path="/forgot-password"
|
|
81
|
+
element={
|
|
82
|
+
<PublicRoute isAuthenticated={isAuthenticated}>
|
|
83
|
+
<ForgotPassword />
|
|
84
|
+
</PublicRoute>
|
|
85
|
+
}
|
|
86
|
+
/>
|
|
87
|
+
<Route
|
|
88
|
+
element={
|
|
89
|
+
<ProtectedLayout
|
|
90
|
+
isAuthenticated={isAuthenticated}
|
|
91
|
+
username={username}
|
|
92
|
+
onLogout={handleLogout}
|
|
93
|
+
/>
|
|
94
|
+
}
|
|
95
|
+
>
|
|
96
|
+
<Route path="/spare-part" element={<SparePartPage />} />
|
|
97
|
+
<Route path="/stock-in" element={<StockInPage />} />
|
|
98
|
+
<Route path="/stock-out" element={<StockOutPage />} />
|
|
99
|
+
<Route path="/reports" element={<ReportsPage />} />
|
|
100
|
+
<Route path="/" element={<Navigate to="/spare-part" replace />} />
|
|
101
|
+
</Route>
|
|
102
|
+
<Route
|
|
103
|
+
path="*"
|
|
104
|
+
element={<Navigate to={isAuthenticated ? "/spare-part" : "/login"} replace />}
|
|
105
|
+
/>
|
|
106
|
+
</Routes>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export default App;
|