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
package/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const inquirer = require("inquirer");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs-extra");
|
|
6
|
+
const chalk = require("chalk");
|
|
7
|
+
const ora = require("ora");
|
|
8
|
+
|
|
9
|
+
const templates = {
|
|
10
|
+
"EPMS - Employee Payroll Management System": "epms-app",
|
|
11
|
+
"IMS - Inventory Management System": "lms-app",
|
|
12
|
+
"SCMS - Supply Chain Management System": "scms-app",
|
|
13
|
+
"SFMS - School Fees Management System": "sfms-app",
|
|
14
|
+
"SIMS - Stock Inventory Management System": "sims-app",
|
|
15
|
+
"SmartShop": "smartshop-app",
|
|
16
|
+
"SRMS - Sales Records Management System": "srms-app",
|
|
17
|
+
"StockHub SMS": "stockhub-sms-app",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
async function run() {
|
|
21
|
+
const answers = await inquirer.prompt([
|
|
22
|
+
{
|
|
23
|
+
type: "list",
|
|
24
|
+
name: "project",
|
|
25
|
+
message: "Select project to create:",
|
|
26
|
+
choices: Object.keys(templates),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: "input",
|
|
30
|
+
name: "name",
|
|
31
|
+
message: "Enter project folder name:",
|
|
32
|
+
default: "my-app",
|
|
33
|
+
},
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const spinner = ora("Creating project...").start();
|
|
37
|
+
|
|
38
|
+
const templateFolder = templates[answers.project];
|
|
39
|
+
const source = path.join(__dirname, "templates", templateFolder);
|
|
40
|
+
const target = path.join(process.cwd(), answers.name);
|
|
41
|
+
|
|
42
|
+
if (fs.existsSync(target)) {
|
|
43
|
+
spinner.fail("Folder already exists!");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
fs.copySync(source, target);
|
|
49
|
+
spinner.succeed("Project created successfully!");
|
|
50
|
+
|
|
51
|
+
console.log(
|
|
52
|
+
chalk.green("\nNext steps:\n"),
|
|
53
|
+
` cd ${answers.name}\n`,
|
|
54
|
+
" npm install\n",
|
|
55
|
+
" npm run dev"
|
|
56
|
+
);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
spinner.fail("Failed to create project: " + err.message);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
run();
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-ishvexa-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI scaffolding tool for ishvexa apps",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-ishvexa-app": "./index.js"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"chalk": "^4.1.2",
|
|
10
|
+
"fs-extra": "^11.1.1",
|
|
11
|
+
"inquirer": "^8.2.5",
|
|
12
|
+
"ora": "^5.4.1"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Employee Payroll Management System (EPMS)
|
|
2
|
+
|
|
3
|
+
National Practical Exam template — Software Development (TSS).
|
|
4
|
+
|
|
5
|
+
## ERD
|
|
6
|
+
|
|
7
|
+
| Entity | Primary Key | Attributes |
|
|
8
|
+
|--------|-------------|------------|
|
|
9
|
+
| **Department** | `departmentCode` | departmentName |
|
|
10
|
+
| **Employee** | `employeeNumber` | firstName, lastName, address, position, telephone, gender, hiredDate, departmentCode (FK) |
|
|
11
|
+
| **Salary** | `salary_id` | grossSalary, totalDeduction, netSalary, monthOfPayment, employeeNumber (FK) |
|
|
12
|
+
|
|
13
|
+
Relationships:
|
|
14
|
+
- Department (1) — (M) Employee
|
|
15
|
+
- Employee (1) — (M) Salary
|
|
16
|
+
|
|
17
|
+
## Exam rules implemented
|
|
18
|
+
|
|
19
|
+
| Form | Insert | Update / Delete / List |
|
|
20
|
+
|------|--------|-------------------------|
|
|
21
|
+
| Employee | Yes | List only |
|
|
22
|
+
| Department | Yes | List only |
|
|
23
|
+
| Salary | Yes | Full CRUD |
|
|
24
|
+
|
|
25
|
+
- Menu: **Employee**, **Department**, **Salary**, **Reports**, **Logout**
|
|
26
|
+
- Auth: username + password (JWT)
|
|
27
|
+
- Reports: daily (date picker), weekly (start/end date), monthly (month picker)
|
|
28
|
+
- Stack: React + Tailwind + Axios + Express + MySQL or MongoDB
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd backend-mysql && npm install
|
|
34
|
+
cd ../backend-mongodb && npm install
|
|
35
|
+
cd ../frontend && npm install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Database setup (MySQL)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
cd backend-mysql
|
|
42
|
+
cp .env.example .env
|
|
43
|
+
npm run db:init
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Database name: **EPMS**
|
|
47
|
+
|
|
48
|
+
## Run development server
|
|
49
|
+
|
|
50
|
+
MySQL API (port 5555):
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd backend-mysql && npm run dev
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
MongoDB API (port 5555 — run one backend at a time):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
cd backend-mongodb && npm run dev
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Frontend (port 5173):
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cd frontend && npm run dev
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Default login: `admin` / `admin123`
|
|
69
|
+
|
|
70
|
+
## Environment variables
|
|
71
|
+
|
|
72
|
+
### backend-mysql
|
|
73
|
+
|
|
74
|
+
| Variable | Description |
|
|
75
|
+
|----------|-------------|
|
|
76
|
+
| PORT | API port (5555) |
|
|
77
|
+
| JWT_SECRET | JWT secret |
|
|
78
|
+
| DB_HOST | MySQL host |
|
|
79
|
+
| DB_USER | MySQL user |
|
|
80
|
+
| DB_PASSWORD | MySQL password |
|
|
81
|
+
| DB_NAME | EPMS |
|
|
82
|
+
| DB_PORT | MySQL port |
|
|
83
|
+
|
|
84
|
+
### backend-mongodb
|
|
85
|
+
|
|
86
|
+
| Variable | Description |
|
|
87
|
+
|----------|-------------|
|
|
88
|
+
| PORT | API port (5555) |
|
|
89
|
+
| JWT_SECRET | JWT secret |
|
|
90
|
+
| MONGO_URI | MongoDB URI (database: EPMS) |
|
|
91
|
+
|
|
92
|
+
## API endpoints
|
|
93
|
+
|
|
94
|
+
- POST /api/auth/register
|
|
95
|
+
- POST /api/auth/login
|
|
96
|
+
- GET/POST /api/departments
|
|
97
|
+
- GET/POST /api/employees
|
|
98
|
+
- GET/POST/PUT/DELETE /api/salaries
|
|
99
|
+
- GET /api/reports?period=daily&date=YYYY-MM-DD
|
|
100
|
+
- GET /api/reports?period=weekly&startDate=YYYY-MM-DD&endDate=YYYY-MM-DD
|
|
101
|
+
- GET /api/reports?period=monthly&month=YYYY-MM
|
|
102
|
+
|
|
103
|
+
## Folder structure
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
epms/
|
|
107
|
+
├── README.md
|
|
108
|
+
├── frontend/
|
|
109
|
+
├── backend-mysql/
|
|
110
|
+
└── backend-mongodb/
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Save your exam folder as: `FirstName_LastName_National_Practical_Exam_2026`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
import dotenv from "dotenv";
|
|
3
|
+
import User from "../models/User.js";
|
|
4
|
+
|
|
5
|
+
dotenv.config();
|
|
6
|
+
|
|
7
|
+
const ADMIN_HASH = "$2b$10$aULsUjp9bb9lf5CZZyY.7./KhwsocVO0duyPlqu0Qnte75xHBdG5C";
|
|
8
|
+
|
|
9
|
+
export const connectDatabase = async () => {
|
|
10
|
+
try {
|
|
11
|
+
await mongoose.connect(process.env.MONGO_URI || "mongodb://localhost:27017/EPMS");
|
|
12
|
+
console.log("Database Connected Successfully");
|
|
13
|
+
const count = await User.countDocuments();
|
|
14
|
+
if (count === 0) {
|
|
15
|
+
await User.create({
|
|
16
|
+
username: "admin",
|
|
17
|
+
email: "admin@exam.local",
|
|
18
|
+
password: ADMIN_HASH,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.log("Database Connection Failed");
|
|
24
|
+
console.error(error.message);
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default mongoose;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import bcrypt from "bcryptjs";
|
|
2
|
+
import jwt from "jsonwebtoken";
|
|
3
|
+
import User from "../models/User.js";
|
|
4
|
+
|
|
5
|
+
const signToken = (user) =>
|
|
6
|
+
jwt.sign(
|
|
7
|
+
{ id: user._id, username: user.username },
|
|
8
|
+
process.env.JWT_SECRET || "exam_secret",
|
|
9
|
+
{ expiresIn: "8h" }
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
const normalizeEmail = (email) => String(email || "").trim().toLowerCase();
|
|
13
|
+
|
|
14
|
+
export const register = async (req, res) => {
|
|
15
|
+
try {
|
|
16
|
+
const { username, email, password } = req.body;
|
|
17
|
+
if (!username || !email || !password) {
|
|
18
|
+
return res.status(400).json({ message: "Username, email and password are required." });
|
|
19
|
+
}
|
|
20
|
+
const emailNorm = normalizeEmail(email);
|
|
21
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailNorm)) {
|
|
22
|
+
return res.status(400).json({ message: "Enter a valid email address." });
|
|
23
|
+
}
|
|
24
|
+
const existingUser = await User.findOne({ username: username.trim() });
|
|
25
|
+
if (existingUser) {
|
|
26
|
+
return res.status(409).json({ message: "Username already exists." });
|
|
27
|
+
}
|
|
28
|
+
const existingEmail = await User.findOne({ email: emailNorm });
|
|
29
|
+
if (existingEmail) {
|
|
30
|
+
return res.status(409).json({ message: "Email already registered." });
|
|
31
|
+
}
|
|
32
|
+
const hash = await bcrypt.hash(password, 10);
|
|
33
|
+
await User.create({ username: username.trim(), email: emailNorm, password: hash });
|
|
34
|
+
return res.status(201).json({ message: "Account created successfully." });
|
|
35
|
+
} catch {
|
|
36
|
+
return res.status(500).json({ message: "Server error during registration." });
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const login = async (req, res) => {
|
|
41
|
+
try {
|
|
42
|
+
const { username, password } = req.body;
|
|
43
|
+
if (!username || !password) {
|
|
44
|
+
return res.status(400).json({ message: "Username and password are required." });
|
|
45
|
+
}
|
|
46
|
+
const user = await User.findOne({ username: username.trim() });
|
|
47
|
+
if (!user) {
|
|
48
|
+
return res.status(401).json({ message: "Invalid credentials." });
|
|
49
|
+
}
|
|
50
|
+
const match = await bcrypt.compare(password, user.password);
|
|
51
|
+
if (!match) {
|
|
52
|
+
return res.status(401).json({ message: "Invalid credentials." });
|
|
53
|
+
}
|
|
54
|
+
return res.json({
|
|
55
|
+
message: "Login successful.",
|
|
56
|
+
token: signToken(user),
|
|
57
|
+
user: { id: user._id, username: user.username, email: user.email },
|
|
58
|
+
});
|
|
59
|
+
} catch {
|
|
60
|
+
return res.status(500).json({ message: "Server error during login." });
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const forgotPassword = async (req, res) => {
|
|
65
|
+
try {
|
|
66
|
+
const { email, newPassword, confirmPassword } = req.body;
|
|
67
|
+
if (!email) {
|
|
68
|
+
return res.status(400).json({ success: false, message: "Email is required." });
|
|
69
|
+
}
|
|
70
|
+
if (!newPassword) {
|
|
71
|
+
return res.status(400).json({ success: false, message: "New password is required." });
|
|
72
|
+
}
|
|
73
|
+
if (!confirmPassword) {
|
|
74
|
+
return res.status(400).json({ success: false, message: "Confirm password is required." });
|
|
75
|
+
}
|
|
76
|
+
if (newPassword !== confirmPassword) {
|
|
77
|
+
return res.status(400).json({
|
|
78
|
+
success: false,
|
|
79
|
+
message: "New password and confirm password must match.",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const emailNorm = normalizeEmail(email);
|
|
83
|
+
const user = await User.findOne({ email: emailNorm });
|
|
84
|
+
if (!user) {
|
|
85
|
+
return res.status(404).json({ success: false, message: "User not found" });
|
|
86
|
+
}
|
|
87
|
+
user.password = await bcrypt.hash(newPassword, 10);
|
|
88
|
+
await user.save();
|
|
89
|
+
return res.json({ success: true, message: "Password reset successfully" });
|
|
90
|
+
} catch {
|
|
91
|
+
return res.status(500).json({ success: false, message: "Server error." });
|
|
92
|
+
}
|
|
93
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Department from "../models/Department.js";
|
|
2
|
+
|
|
3
|
+
export const create = async (req, res) => {
|
|
4
|
+
try {
|
|
5
|
+
if (req.body.departmentCode === undefined || req.body.departmentCode === "") return res.status(400).json({ message: "Department Code is required." });
|
|
6
|
+
if (req.body.departmentName === undefined || req.body.departmentName === "") return res.status(400).json({ message: "Department Name is required." });
|
|
7
|
+
await Department.create({ department_code: req.body.departmentCode, department_name: req.body.departmentName });
|
|
8
|
+
return res.status(201).json({ message: "Department added successfully." });
|
|
9
|
+
} catch (error) {
|
|
10
|
+
if (error.code === 11000) {
|
|
11
|
+
return res.status(409).json({ message: "Department already exists." });
|
|
12
|
+
}
|
|
13
|
+
return res.status(500).json({ message: "Failed to add department." });
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const getAll = async (_req, res) => {
|
|
18
|
+
try {
|
|
19
|
+
const rows = await Department.find().sort({ department_code: -1 }).lean();
|
|
20
|
+
return res.json(rows.map((r) => { const { _id, __v, ...rest } = r; return rest; }));
|
|
21
|
+
} catch {
|
|
22
|
+
return res.status(500).json({ message: "Failed to fetch department records." });
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import Employee from "../models/Employee.js";
|
|
2
|
+
import Department from "../models/Department.js";
|
|
3
|
+
|
|
4
|
+
const ALLOWED_GENDERS = ["Male", "Female"];
|
|
5
|
+
|
|
6
|
+
export const create = async (req, res) => {
|
|
7
|
+
try {
|
|
8
|
+
if (req.body.employeeNumber === undefined || req.body.employeeNumber === "") return res.status(400).json({ message: "Employee Number is required." });
|
|
9
|
+
if (req.body.firstName === undefined || req.body.firstName === "") return res.status(400).json({ message: "First Name is required." });
|
|
10
|
+
if (req.body.lastName === undefined || req.body.lastName === "") return res.status(400).json({ message: "Last Name is required." });
|
|
11
|
+
if (req.body.address === undefined || req.body.address === "") return res.status(400).json({ message: "Address is required." });
|
|
12
|
+
if (req.body.position === undefined || req.body.position === "") return res.status(400).json({ message: "Position is required." });
|
|
13
|
+
if (req.body.telephone === undefined || req.body.telephone === "") return res.status(400).json({ message: "Telephone is required." });
|
|
14
|
+
if (req.body.gender === undefined || req.body.gender === "") return res.status(400).json({ message: "Gender is required." });
|
|
15
|
+
if (!ALLOWED_GENDERS.includes(req.body.gender)) {
|
|
16
|
+
return res.status(400).json({ message: "Select a valid gender (Male or Female)." });
|
|
17
|
+
}
|
|
18
|
+
if (req.body.hiredDate === undefined || req.body.hiredDate === "") return res.status(400).json({ message: "Hired Date is required." });
|
|
19
|
+
if (req.body.departmentCode === undefined || req.body.departmentCode === "") return res.status(400).json({ message: "Select a department from the list." });
|
|
20
|
+
const dept = await Department.findOne({ department_code: req.body.departmentCode });
|
|
21
|
+
if (!dept) return res.status(400).json({ message: "Selected department does not exist." });
|
|
22
|
+
await Employee.create({ employee_number: req.body.employeeNumber, first_name: req.body.firstName, last_name: req.body.lastName, address: req.body.address, position: req.body.position, telephone: req.body.telephone, gender: req.body.gender, hired_date: req.body.hiredDate, department_code: req.body.departmentCode });
|
|
23
|
+
return res.status(201).json({ message: "Employee added successfully." });
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error.code === 11000) {
|
|
26
|
+
return res.status(409).json({ message: "Employee already exists." });
|
|
27
|
+
}
|
|
28
|
+
return res.status(500).json({ message: "Failed to add employee." });
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const getAll = async (_req, res) => {
|
|
33
|
+
try {
|
|
34
|
+
const rows = await Employee.find().sort({ employee_number: -1 }).lean();
|
|
35
|
+
return res.json(rows.map((r) => { const { _id, __v, ...rest } = r; return rest; }));
|
|
36
|
+
} catch {
|
|
37
|
+
return res.status(500).json({ message: "Failed to fetch employee records." });
|
|
38
|
+
}
|
|
39
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import Department from "../models/Department.js";
|
|
2
|
+
import Employee from "../models/Employee.js";
|
|
3
|
+
import Salary from "../models/Salary.js";
|
|
4
|
+
|
|
5
|
+
const clean = (rows) => rows.map((r) => {
|
|
6
|
+
const copy = { ...r };
|
|
7
|
+
delete copy._id;
|
|
8
|
+
delete copy.__v;
|
|
9
|
+
return copy;
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const monthBounds = (month) => {
|
|
13
|
+
const start = new Date(`${month}-01T00:00:00`);
|
|
14
|
+
const end = new Date(start.getFullYear(), start.getMonth() + 1, 0, 23, 59, 59, 999);
|
|
15
|
+
return { start, end };
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const getReports = async (req, res) => {
|
|
19
|
+
try {
|
|
20
|
+
const period = req.query.period || "daily";
|
|
21
|
+
const date = req.query.date || new Date().toISOString().slice(0, 10);
|
|
22
|
+
const startDate = req.query.startDate;
|
|
23
|
+
const endDate = req.query.endDate;
|
|
24
|
+
const month = req.query.month || date.slice(0, 7);
|
|
25
|
+
|
|
26
|
+
let employees;
|
|
27
|
+
let salaries;
|
|
28
|
+
|
|
29
|
+
if (period === "daily") {
|
|
30
|
+
const start = new Date(`${date}T00:00:00`);
|
|
31
|
+
const end = new Date(`${date}T23:59:59`);
|
|
32
|
+
employees = clean(await Employee.find({ hired_date: { $gte: start, $lte: end } }).lean());
|
|
33
|
+
salaries = clean(await Salary.find({ month_of_payment: month }).lean());
|
|
34
|
+
} else if (period === "weekly") {
|
|
35
|
+
if (!startDate || !endDate) {
|
|
36
|
+
return res.status(400).json({ message: "Start date and end date are required for weekly reports." });
|
|
37
|
+
}
|
|
38
|
+
const start = new Date(`${startDate}T00:00:00`);
|
|
39
|
+
const end = new Date(`${endDate}T23:59:59`);
|
|
40
|
+
employees = clean(await Employee.find({ hired_date: { $gte: start, $lte: end } }).lean());
|
|
41
|
+
salaries = clean(
|
|
42
|
+
await Salary.find({
|
|
43
|
+
month_of_payment: { $gte: startDate.slice(0, 7), $lte: endDate.slice(0, 7) },
|
|
44
|
+
}).lean()
|
|
45
|
+
);
|
|
46
|
+
} else {
|
|
47
|
+
const { start, end } = monthBounds(month);
|
|
48
|
+
employees = clean(await Employee.find({ hired_date: { $gte: start, $lte: end } }).lean());
|
|
49
|
+
salaries = clean(await Salary.find({ month_of_payment: month }).lean());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const departments = clean(await Department.find().lean());
|
|
53
|
+
return res.json({ period, reports: { employees, departments, salaries } });
|
|
54
|
+
} catch {
|
|
55
|
+
return res.status(500).json({ message: "Failed to generate reports." });
|
|
56
|
+
}
|
|
57
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import Salary from "../models/Salary.js";
|
|
2
|
+
|
|
3
|
+
const calcNet = (gross, deduction) => {
|
|
4
|
+
const g = Number(gross);
|
|
5
|
+
const d = Number(deduction);
|
|
6
|
+
if (Number.isNaN(g) || Number.isNaN(d)) return null;
|
|
7
|
+
return Math.round((g - d) * 100) / 100;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const create = async (req, res) => {
|
|
11
|
+
try {
|
|
12
|
+
if (req.body.grossSalary === undefined || req.body.grossSalary === "") {
|
|
13
|
+
return res.status(400).json({ message: "Gross Salary is required." });
|
|
14
|
+
}
|
|
15
|
+
if (req.body.totalDeduction === undefined || req.body.totalDeduction === "") {
|
|
16
|
+
return res.status(400).json({ message: "Total Deduction is required." });
|
|
17
|
+
}
|
|
18
|
+
if (!req.body.monthOfPayment) {
|
|
19
|
+
return res.status(400).json({ message: "Month of Payment is required." });
|
|
20
|
+
}
|
|
21
|
+
if (!req.body.employeeNumber) {
|
|
22
|
+
return res.status(400).json({ message: "Employee is required." });
|
|
23
|
+
}
|
|
24
|
+
const netSalary = calcNet(req.body.grossSalary, req.body.totalDeduction);
|
|
25
|
+
if (netSalary === null) {
|
|
26
|
+
return res.status(400).json({ message: "Invalid salary amounts." });
|
|
27
|
+
}
|
|
28
|
+
await Salary.create({
|
|
29
|
+
gross_salary: req.body.grossSalary,
|
|
30
|
+
total_deduction: req.body.totalDeduction,
|
|
31
|
+
net_salary: netSalary,
|
|
32
|
+
month_of_payment: req.body.monthOfPayment,
|
|
33
|
+
employee_number: req.body.employeeNumber,
|
|
34
|
+
});
|
|
35
|
+
return res.status(201).json({ message: "Salary added successfully." });
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error.code === 11000) {
|
|
38
|
+
return res.status(409).json({ message: "Salary already exists." });
|
|
39
|
+
}
|
|
40
|
+
return res.status(500).json({ message: "Failed to add salary." });
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const getAll = async (_req, res) => {
|
|
45
|
+
try {
|
|
46
|
+
const rows = await Salary.find().sort({ salary_id: -1 }).lean();
|
|
47
|
+
return res.json(rows.map((r) => { const { _id, __v, ...rest } = r; return rest; }));
|
|
48
|
+
} catch {
|
|
49
|
+
return res.status(500).json({ message: "Failed to fetch salary records." });
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const update = async (req, res) => {
|
|
54
|
+
try {
|
|
55
|
+
if (req.body.grossSalary === undefined || req.body.grossSalary === "") {
|
|
56
|
+
return res.status(400).json({ message: "Gross Salary is required." });
|
|
57
|
+
}
|
|
58
|
+
if (req.body.totalDeduction === undefined || req.body.totalDeduction === "") {
|
|
59
|
+
return res.status(400).json({ message: "Total Deduction is required." });
|
|
60
|
+
}
|
|
61
|
+
if (!req.body.monthOfPayment) {
|
|
62
|
+
return res.status(400).json({ message: "Month of Payment is required." });
|
|
63
|
+
}
|
|
64
|
+
if (!req.body.employeeNumber) {
|
|
65
|
+
return res.status(400).json({ message: "Employee is required." });
|
|
66
|
+
}
|
|
67
|
+
const netSalary = calcNet(req.body.grossSalary, req.body.totalDeduction);
|
|
68
|
+
if (netSalary === null) {
|
|
69
|
+
return res.status(400).json({ message: "Invalid salary amounts." });
|
|
70
|
+
}
|
|
71
|
+
const updated = await Salary.findOneAndUpdate(
|
|
72
|
+
{ salary_id: Number(req.params.id) },
|
|
73
|
+
{
|
|
74
|
+
gross_salary: req.body.grossSalary,
|
|
75
|
+
total_deduction: req.body.totalDeduction,
|
|
76
|
+
net_salary: netSalary,
|
|
77
|
+
month_of_payment: req.body.monthOfPayment,
|
|
78
|
+
employee_number: req.body.employeeNumber,
|
|
79
|
+
},
|
|
80
|
+
{ new: true }
|
|
81
|
+
);
|
|
82
|
+
if (!updated) {
|
|
83
|
+
return res.status(404).json({ message: "Salary not found." });
|
|
84
|
+
}
|
|
85
|
+
return res.json({ message: "Salary updated successfully." });
|
|
86
|
+
} catch {
|
|
87
|
+
return res.status(500).json({ message: "Failed to update salary." });
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const remove = async (req, res) => {
|
|
92
|
+
try {
|
|
93
|
+
const deleted = await Salary.findOneAndDelete({ salary_id: Number(req.params.id) });
|
|
94
|
+
if (!deleted) {
|
|
95
|
+
return res.status(404).json({ message: "Salary not found." });
|
|
96
|
+
}
|
|
97
|
+
return res.json({ message: "Salary deleted successfully." });
|
|
98
|
+
} catch {
|
|
99
|
+
return res.status(500).json({ message: "Failed to delete salary." });
|
|
100
|
+
}
|
|
101
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import jwt from "jsonwebtoken";
|
|
2
|
+
|
|
3
|
+
const auth = (req, res, next) => {
|
|
4
|
+
const header = req.headers.authorization;
|
|
5
|
+
if (!header || !header.startsWith("Bearer ")) {
|
|
6
|
+
return res.status(401).json({ message: "Authentication required." });
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
req.user = jwt.verify(header.split(" ")[1], process.env.JWT_SECRET || "exam_secret");
|
|
10
|
+
next();
|
|
11
|
+
} catch {
|
|
12
|
+
return res.status(401).json({ message: "Invalid or expired token." });
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default auth;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
|
|
3
|
+
const counterSchema = new mongoose.Schema({
|
|
4
|
+
_id: { type: String, required: true },
|
|
5
|
+
seq: { type: Number, default: 0 },
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
counterSchema.statics.getNext = async function (name) {
|
|
9
|
+
const doc = await this.findByIdAndUpdate(name, { $inc: { seq: 1 } }, { new: true, upsert: true });
|
|
10
|
+
return doc.seq;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default mongoose.model("Counter", counterSchema);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const schema = new mongoose.Schema({
|
|
5
|
+
department_code: { type: String, required: true, unique: true },
|
|
6
|
+
department_name: { type: String, required: true }
|
|
7
|
+
}, { collection: "departments" });
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export default mongoose.model("Department", schema);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const schema = new mongoose.Schema({
|
|
5
|
+
employee_number: { type: String, required: true, unique: true },
|
|
6
|
+
first_name: { type: String, required: true },
|
|
7
|
+
last_name: { type: String, required: true },
|
|
8
|
+
address: { type: String, required: true },
|
|
9
|
+
position: { type: String, required: true },
|
|
10
|
+
telephone: { type: String, required: true },
|
|
11
|
+
gender: { type: String, required: true },
|
|
12
|
+
hired_date: { type: Date, required: true },
|
|
13
|
+
department_code: { type: String, required: true }
|
|
14
|
+
}, { collection: "employees" });
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export default mongoose.model("Employee", schema);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
import Counter from "./Counter.js";
|
|
3
|
+
|
|
4
|
+
const schema = new mongoose.Schema({
|
|
5
|
+
salary_id: { type: Number, unique: true },
|
|
6
|
+
gross_salary: { type: Number, required: true },
|
|
7
|
+
total_deduction: { type: Number, required: true },
|
|
8
|
+
net_salary: { type: Number, required: true },
|
|
9
|
+
month_of_payment: { type: String, required: true },
|
|
10
|
+
employee_number: { type: String, required: true }
|
|
11
|
+
}, { collection: "salaries" });
|
|
12
|
+
|
|
13
|
+
schema.pre("save", async function () {
|
|
14
|
+
if (this.isNew && (this.salary_id === undefined || this.salary_id === null)) {
|
|
15
|
+
this.salary_id = await Counter.getNext("salary_id");
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export default mongoose.model("Salary", schema);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
|
|
3
|
+
const userSchema = new mongoose.Schema({
|
|
4
|
+
username: { type: String, required: true, unique: true, trim: true },
|
|
5
|
+
email: { type: String, required: true, unique: true, lowercase: true, trim: true },
|
|
6
|
+
password: { type: String, required: true },
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export default mongoose.model("User", userSchema);
|