diff --git a/.adonisjs/client/data.d.ts b/.adonisjs/client/data.d.ts
index 3568d52..ee014a4 100644
--- a/.adonisjs/client/data.d.ts
+++ b/.adonisjs/client/data.d.ts
@@ -1,3 +1,8 @@
+/**
+ * This file is automatically generated.
+ * DO NOT EDIT manually
+ */
+
///
import type { InferData, InferVariants } from '@adonisjs/core/types/transformers'
import type UserTransformer from '#transformers/user_transformer'
diff --git a/.adonisjs/client/manifest.d.ts b/.adonisjs/client/manifest.d.ts
index 5845626..158e306 100644
--- a/.adonisjs/client/manifest.d.ts
+++ b/.adonisjs/client/manifest.d.ts
@@ -1,4 +1,10 @@
+/**
+ * This file is automatically generated.
+ * DO NOT EDIT manually
+ */
+
///
///
///
+///
///
diff --git a/.adonisjs/server/controllers.ts b/.adonisjs/server/controllers.ts
index f7f61b6..9abefc8 100644
--- a/.adonisjs/server/controllers.ts
+++ b/.adonisjs/server/controllers.ts
@@ -1,5 +1,23 @@
+/**
+ * This file is automatically generated.
+ * DO NOT EDIT manually
+ */
+
export const controllers = {
AccessToken: () => import('#controllers/access_token_controller'),
+ Categories: () => import('#controllers/categories_controller'),
+ FastPasses: () => import('#controllers/fast_passes_controller'),
+ Furnitures: () => import('#controllers/furnitures_controller'),
+ Goods: () => import('#controllers/goods_controller'),
+ Logs: () => import('#controllers/logs_controller'),
+ Members: () => import('#controllers/members_controller'),
NewAccount: () => import('#controllers/new_account_controller'),
+ Permissions: () => import('#controllers/permissions_controller'),
+ Products: () => import('#controllers/products_controller'),
Profile: () => import('#controllers/profile_controller'),
+ Restocks: () => import('#controllers/restocks_controller'),
+ Roles: () => import('#controllers/roles_controller'),
+ StockBatches: () => import('#controllers/stock_batches_controller'),
+ StockMovements: () => import('#controllers/stock_movements_controller'),
+ Suppliers: () => import('#controllers/suppliers_controller'),
}
diff --git a/.adonisjs/server/events.ts b/.adonisjs/server/events.ts
index a7ab473..a74e59b 100644
--- a/.adonisjs/server/events.ts
+++ b/.adonisjs/server/events.ts
@@ -1 +1,6 @@
+/**
+ * This file is automatically generated.
+ * DO NOT EDIT manually
+ */
+
export const events = {}
diff --git a/.adonisjs/server/listeners.ts b/.adonisjs/server/listeners.ts
index 28cbf66..05f35f8 100644
--- a/.adonisjs/server/listeners.ts
+++ b/.adonisjs/server/listeners.ts
@@ -1 +1,6 @@
+/**
+ * This file is automatically generated.
+ * DO NOT EDIT manually
+ */
+
export const listeners = {}
diff --git a/app/controllers/categories_controller.ts b/app/controllers/categories_controller.ts
new file mode 100644
index 0000000..dd94e08
--- /dev/null
+++ b/app/controllers/categories_controller.ts
@@ -0,0 +1,44 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Category from '#models/category'
+
+export default class CategoriesController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ return Category.all()
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const data = request.all()
+ return Category.create(data)
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ return Category.findOrFail(params.id)
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const category = await Category.findOrFail(params.id)
+ const data = request.all()
+ category.merge(data)
+ return category.save()
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const category = await Category.findOrFail(params.id)
+ return category.delete()
+ }
+}
diff --git a/app/controllers/fast_passes_controller.ts b/app/controllers/fast_passes_controller.ts
new file mode 100644
index 0000000..9ec8b47
--- /dev/null
+++ b/app/controllers/fast_passes_controller.ts
@@ -0,0 +1,54 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import FastPass from '#models/fast_pass'
+
+export default class FastPassesController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ return FastPass.query()
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { price, duration, description, label } = request.all()
+ const fastPass = new FastPass()
+ fastPass.price = price
+ fastPass.duration = duration
+ fastPass.description = description
+ fastPass.label = label
+ await fastPass.save()
+ return fastPass
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ return FastPass.query().where('id', params.id).firstOrFail()
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const fastPass = await FastPass.query().where('id', params.id).firstOrFail() // We get our fast pass by id
+ const { price, duration, description, label } = request.all() // We transfer the new data from the request to constants
+ fastPass.price = price // Assigning the data
+ fastPass.duration = duration
+ fastPass.description = description
+ fastPass.label = label
+ await fastPass.save() // We save the fast pass to the database
+ return fastPass
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const fastPass = await FastPass.query().where('id', params.id).firstOrFail()
+ await fastPass.delete()
+ }
+}
diff --git a/app/controllers/furnitures_controller.ts b/app/controllers/furnitures_controller.ts
new file mode 100644
index 0000000..76a68c6
--- /dev/null
+++ b/app/controllers/furnitures_controller.ts
@@ -0,0 +1,44 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Furniture from '#models/furniture'
+
+export default class FurnituresController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ return Furniture.all()
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { name, quantity, price } = request.all()
+ return Furniture.create({ name, quantity, price })
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ return Furniture.findOrFail(params.id)
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const furniture = await Furniture.findOrFail(params.id)
+ const { name, quantity, price } = request.all()
+ furniture.merge({ name, quantity, price })
+ return furniture.save()
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const furniture = await Furniture.findOrFail(params.id)
+ return furniture.delete()
+ }
+}
diff --git a/app/controllers/goods_controller.ts b/app/controllers/goods_controller.ts
new file mode 100644
index 0000000..e8cff66
--- /dev/null
+++ b/app/controllers/goods_controller.ts
@@ -0,0 +1,69 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Good from '#models/good'
+
+export default class GoodsController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ return Good.query().preload('products').preload('category').preload('suppliers')
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { name, unit, brand, categoryId } = request.all()
+ const good = new Good()
+ good.name = name
+ good.unit = unit
+ good.brand = brand
+ good.categoryId = categoryId
+ await good.save()
+ return good
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ return await Good.query()
+ .preload('products')
+ .preload('category')
+ .preload('suppliers')
+ .where('id', params.id)
+ .firstOrFail()
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const good = await Good.query()
+ .preload('products')
+ .preload('category')
+ .preload('suppliers')
+ .where('id', params.id)
+ .firstOrFail() // We get our good by id
+ const { name, unit, brand, categoryId } = request.all()
+ good.name = name
+ good.unit = unit
+ good.brand = brand
+ good.categoryId = categoryId
+ await good.save()
+ return good
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const good = await Good.query()
+ .preload('products')
+ .preload('category')
+ .preload('suppliers')
+ .where('id', params.id)
+ .firstOrFail()
+ await good.delete()
+ }
+}
diff --git a/app/controllers/logs_controller.ts b/app/controllers/logs_controller.ts
new file mode 100644
index 0000000..232e372
--- /dev/null
+++ b/app/controllers/logs_controller.ts
@@ -0,0 +1,62 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Log from '#models/log'
+
+export default class LogsController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ const logs = await Log.query().preload('user')
+ return logs
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { level, message, method, url, ip, meta, userId } = request.all()
+ const log = await Log.create({
+ level,
+ message,
+ method,
+ url,
+ ip,
+ meta,
+ userId,
+ })
+ return log
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ const log = await Log.query().where('id', params.id).preload('user').firstOrFail()
+ return log
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const log = await Log.query().where('id', params.id).firstOrFail()
+ const { level, message, method, url, ip, meta, userId } = request.all()
+ log.level = level
+ log.message = message
+ log.method = method
+ log.url = url
+ log.ip = ip
+ log.meta = meta
+ log.userId = userId
+ await log.save()
+ return log
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const log = await Log.query().where('id', params.id).preload('user').firstOrFail()
+ await log.delete()
+ }
+}
diff --git a/app/controllers/members_controller.ts b/app/controllers/members_controller.ts
new file mode 100644
index 0000000..246b0bd
--- /dev/null
+++ b/app/controllers/members_controller.ts
@@ -0,0 +1,61 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Member from '#models/member'
+
+export default class MembersController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ const members = await Member.query().preload('role')
+ return members
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { firstName, lastName } = request.all()
+ const member = new Member()
+ member.firstName = firstName
+ member.lastName = lastName
+ await member.save()
+ return member
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ const member = await Member.query().preload('role').where('id', params.id).first()
+ if (!member) {
+ throw new Error('Member not found')
+ }
+ return member
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const member = await Member.query().preload('role').where('id', params.id).first()
+ if (!member) {
+ throw new Error('Member not found')
+ }
+ const { firstName, lastName } = request.all()
+ member.firstName = firstName
+ member.lastName = lastName
+ await member.save()
+ return member
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const member = await Member.query().preload('role').where('id', params.id).first()
+ if (!member) {
+ throw new Error('Member not found')
+ }
+ await member.delete()
+ }
+}
diff --git a/app/controllers/permissions_controller.ts b/app/controllers/permissions_controller.ts
new file mode 100644
index 0000000..6dc1aad
--- /dev/null
+++ b/app/controllers/permissions_controller.ts
@@ -0,0 +1,49 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Permission from '#models/permission'
+
+export default class PermissionsController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ const permissions = await Permission.all()
+ return permissions
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { permission } = request.all()
+ const newPermission = await Permission.create({ permission })
+ return newPermission
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ const permission = await Permission.findOrFail(params.id)
+ return permission
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const permission = await Permission.findOrFail(params.id)
+ const { permission: newPermission } = request.all()
+ permission.permission = newPermission
+ await permission.save()
+ return permission
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const permission = await Permission.findOrFail(params.id)
+ await permission.delete()
+ return { message: 'Permission deleted successfully' }
+ }
+}
diff --git a/app/controllers/products_controller.ts b/app/controllers/products_controller.ts
new file mode 100644
index 0000000..215c49e
--- /dev/null
+++ b/app/controllers/products_controller.ts
@@ -0,0 +1,66 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Product from '#models/product'
+
+export default class ProductsController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ return Product.query().preload('furnitures').preload('goods')
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { name, isVegetarian, description, recipe } = request.all()
+ const product = new Product()
+ product.name = name
+ product.isVegetarian = isVegetarian
+ product.description = description
+ product.recipe = recipe
+ await product.save()
+ return product
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ return await Product.query()
+ .preload('furnitures')
+ .preload('goods')
+ .where('id', params.id)
+ .firstOrFail()
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const product = await Product.query()
+ .preload('furnitures')
+ .preload('goods')
+ .where('id', params.id)
+ .firstOrFail() // We get our product by id
+ const { name, isVegetarian, description, recipe } = request.all() // We transfer the new data from the request to constants
+ product.name = name // Assigning the data
+ product.isVegetarian = isVegetarian // Assigning the data
+ product.description = description // Assigning the data
+ product.recipe = recipe // Assigning the data
+ await product.save() // We save the product to the database
+ return product
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const product = await Product.query()
+ .preload('furnitures')
+ .preload('goods')
+ .where('id', params.id)
+ .firstOrFail() // Get the product by id
+ await product.delete()
+ }
+}
diff --git a/app/controllers/restocks_controller.ts b/app/controllers/restocks_controller.ts
new file mode 100644
index 0000000..cc6c6f1
--- /dev/null
+++ b/app/controllers/restocks_controller.ts
@@ -0,0 +1,72 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Restock from '#models/restock'
+
+export default class RestocksController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ const restocks = await Restock.query()
+ .preload('member')
+ .preload('supplier')
+ .preload('stockBatches')
+ return restocks
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { memberId, supplierId, totalPrice } = request.all()
+ const restock = new Restock()
+ restock.memberId = memberId
+ restock.supplierId = supplierId
+ restock.totalPrice = totalPrice
+ await restock.save()
+ return restock
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ const restock = await Restock.query()
+ .preload('member')
+ .preload('supplier')
+ .preload('stockBatches')
+ .where('id', params.id)
+ .firstOrFail()
+ return restock
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const restock = await Restock.query()
+ .preload('member')
+ .preload('supplier')
+ .preload('stockBatches')
+ .where('id', params.id)
+ .firstOrFail()
+ const { memberId, supplierId, totalPrice } = request.all()
+ restock.memberId = memberId
+ restock.supplierId = supplierId
+ restock.totalPrice = totalPrice
+ await restock.save()
+ return restock
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const restock = await Restock.query()
+ .preload('member')
+ .preload('supplier')
+ .preload('stockBatches')
+ .where('id', params.id)
+ .firstOrFail()
+ await restock.delete()
+ }
+}
diff --git a/app/controllers/roles_controller.ts b/app/controllers/roles_controller.ts
new file mode 100644
index 0000000..a7c9659
--- /dev/null
+++ b/app/controllers/roles_controller.ts
@@ -0,0 +1,54 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Role from '#models/role'
+
+export default class RolesController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ const roles = await Role.query()
+ return roles
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { name } = request.all()
+ const role = await Role.create({ name })
+ return role
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ const role = await Role.findOrFail(params.id)
+ return role
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const { name } = request.body()
+ const role = await Role.find(params.id)
+ if (!role) {
+ throw new Error('Role not found')
+ }
+ role.name = name
+ await role.save()
+ return role
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const role = await Role.find(params.id)
+ if (!role) {
+ throw new Error('Role not found')
+ }
+ await role.delete()
+ }
+}
diff --git a/app/controllers/stock_batches_controller.ts b/app/controllers/stock_batches_controller.ts
new file mode 100644
index 0000000..1576bdb
--- /dev/null
+++ b/app/controllers/stock_batches_controller.ts
@@ -0,0 +1,73 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import StockBatch from '#models/stock_batch'
+
+export default class StockBatchesController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ const stockBatches = await StockBatch.query().preload('good').preload('restock')
+ return stockBatches
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { expirationDate, label, quantity, restockId, goodId } = request.all()
+ const stockBatch = await StockBatch.create({
+ expirationDate,
+ label,
+ quantity,
+ restockId,
+ goodId,
+ })
+ return stockBatch
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ const stockBatch = await StockBatch.query()
+ .where('id', params.id)
+ .preload('good')
+ .preload('restock')
+ .firstOrFail()
+ return stockBatch
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const stockBatch = await StockBatch.query()
+ .where('id', params.id)
+ .preload('good')
+ .preload('restock')
+ .firstOrFail()
+ const { expirationDate, label, quantity, restockId, goodId } = request.all()
+ await stockBatch
+ .merge({
+ expirationDate,
+ label,
+ quantity,
+ restockId,
+ goodId,
+ })
+ .save()
+ return stockBatch
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const stockBatch = await StockBatch.query()
+ .where('id', params.id)
+ .preload('good')
+ .preload('restock')
+ .firstOrFail()
+ await stockBatch.delete()
+ }
+}
diff --git a/app/controllers/stock_movements_controller.ts b/app/controllers/stock_movements_controller.ts
new file mode 100644
index 0000000..3683a2a
--- /dev/null
+++ b/app/controllers/stock_movements_controller.ts
@@ -0,0 +1,71 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import StockMovement from '#models/stock_movement'
+
+export default class StockMovementsController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ const stockMovements = await StockMovement.query().preload('good').preload('stockBatch')
+ return stockMovements
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { quantity, movementType, goodId, stockBatchId } = request.all()
+ const stockMovement = await StockMovement.create({
+ quantity,
+ movementType,
+ goodId,
+ stockBatchId,
+ })
+ return stockMovement
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ const stockMovement = await StockMovement.query()
+ .where('id', params.id)
+ .preload('good')
+ .preload('stockBatch')
+ .firstOrFail()
+
+ return stockMovement
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const stockMovement = await StockMovement.query()
+ .where('id', params.id)
+ .preload('good')
+ .preload('stockBatch')
+ .firstOrFail()
+ const { quantity, movementType, goodId, stockBatchId } = request.all()
+
+ stockMovement.quantity = quantity
+ stockMovement.movementType = movementType
+ stockMovement.goodId = goodId
+ stockMovement.stockBatchId = stockBatchId
+
+ await stockMovement.save()
+ return stockMovement
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const stockMovement = await StockMovement.query()
+ .where('id', params.id)
+ .preload('good')
+ .preload('stockBatch')
+ .firstOrFail()
+ await stockMovement.delete()
+ }
+}
diff --git a/app/controllers/suppliers_controller.ts b/app/controllers/suppliers_controller.ts
new file mode 100644
index 0000000..5b3f3e7
--- /dev/null
+++ b/app/controllers/suppliers_controller.ts
@@ -0,0 +1,60 @@
+import type { HttpContext } from '@adonisjs/core/http'
+import Supplier from '#models/supplier'
+
+export default class SuppliersController {
+ /**
+ * Display a list of resource
+ */
+ async index({}: HttpContext) {
+ return Supplier.query().preload('goods').preload('restocks')
+ }
+
+ /**
+ * Handle form submission for the create action
+ */
+ async store({ request }: HttpContext) {
+ const { name } = request.all()
+ const supplier = new Supplier()
+ supplier.name = name
+ await supplier.save()
+ return supplier
+ }
+
+ /**
+ * Show individual record
+ */
+ async show({ params }: HttpContext) {
+ return await Supplier.query()
+ .preload('goods')
+ .preload('restocks')
+ .where('id', params.id)
+ .firstOrFail()
+ }
+
+ /**
+ * Handle form submission for the edit action
+ */
+ async update({ params, request }: HttpContext) {
+ const supplier = await Supplier.query()
+ .preload('goods')
+ .preload('restocks')
+ .where('id', params.id)
+ .firstOrFail() // We get our supplier by id
+ const { name } = request.all() // We transfer the new data from the request to constants
+ supplier.name = name // Assigning the data
+ await supplier.save() // We save the supplier to the database
+ return supplier
+ }
+
+ /**
+ * Delete record
+ */
+ async destroy({ params }: HttpContext) {
+ const supplier = await Supplier.query()
+ .preload('goods')
+ .preload('restocks')
+ .where('id', params.id)
+ .firstOrFail() // Get the supplier by id
+ await supplier.delete()
+ }
+}
diff --git a/app/models/fast_pass.ts b/app/models/fast_pass.ts
index 96dc7ae..e30557d 100644
--- a/app/models/fast_pass.ts
+++ b/app/models/fast_pass.ts
@@ -1,9 +1,9 @@
import { FastPassSchema } from '#database/schema'
-import { belongsTo } from '@adonisjs/lucid/orm'
+import { manyToMany } from '@adonisjs/lucid/orm'
import User from '#models/user'
-import type { BelongsTo } from '@adonisjs/lucid/types/relations'
+import type { ManyToMany } from '@adonisjs/lucid/types/relations'
export default class FastPass extends FastPassSchema {
- @belongsTo(() => User)
- declare user: BelongsTo
+ @manyToMany(() => User)
+ declare user: ManyToMany
}
diff --git a/app/models/member.ts b/app/models/member.ts
index 61f5c9a..99c86d2 100644
--- a/app/models/member.ts
+++ b/app/models/member.ts
@@ -10,7 +10,9 @@ import Restock from '#models/restock'
import Role from '#models/role'
export default class Member extends MemberSchema {
- @belongsTo(() => User)
+ public static selfAssignPrimaryKey = true
+
+ @belongsTo(() => User, { foreignKey: 'id' })
declare user: BelongsTo
@hasMany(() => Order)
diff --git a/app/models/permission.ts b/app/models/permission.ts
index 5a8a820..a12f3bd 100644
--- a/app/models/permission.ts
+++ b/app/models/permission.ts
@@ -4,8 +4,19 @@ import Role from '#models/role'
import type { ManyToMany } from '@adonisjs/lucid/types/relations'
export default class Permission extends PermissionSchema {
+ public static primaryKey = 'permission'
+ public static selfAssignPrimaryKey = true
+
@manyToMany(() => Role, {
pivotTable: 'roles_permissions',
+ pivotForeignKey: 'permission_id',
+ pivotRelatedForeignKey: 'role_id',
+ localKey: 'permission',
+ relatedKey: 'id',
+ pivotTimestamps: {
+ createdAt: 'created_at',
+ updatedAt: false,
+ },
})
declare roles: ManyToMany
}
diff --git a/app/models/role.ts b/app/models/role.ts
index 72549b4..5541888 100644
--- a/app/models/role.ts
+++ b/app/models/role.ts
@@ -7,6 +7,14 @@ import Member from '#models/member'
export default class Role extends RoleSchema {
@manyToMany(() => Permission, {
pivotTable: 'roles_permissions',
+ pivotForeignKey: 'role_id',
+ pivotRelatedForeignKey: 'permission_id',
+ localKey: 'id',
+ relatedKey: 'permission',
+ pivotTimestamps: {
+ createdAt: 'created_at',
+ updatedAt: false,
+ },
})
declare permissions: ManyToMany
diff --git a/app/models/user.ts b/app/models/user.ts
index f47980f..65c55da 100644
--- a/app/models/user.ts
+++ b/app/models/user.ts
@@ -19,10 +19,14 @@ export default class User extends compose(UserSchema, withAuthFinder(hash)) {
@manyToMany(() => FastPass, {
pivotTable: 'subscriptions',
+ pivotForeignKey: 'user_id',
+ pivotRelatedForeignKey: 'fast_pass_id',
+ pivotColumns: ['subscribed_at'],
+ pivotTimestamps: true,
})
declare fastPasses: ManyToMany
- @hasOne(() => Member)
+ @hasOne(() => Member, { foreignKey: 'id', localKey: 'id' })
declare member: HasOne
@hasMany(() => PreOrder)
diff --git a/database/factories/category_factory.ts b/database/factories/category_factory.ts
new file mode 100644
index 0000000..e0f1e4d
--- /dev/null
+++ b/database/factories/category_factory.ts
@@ -0,0 +1,10 @@
+import factory from '@adonisjs/lucid/factories'
+import Category from '#models/category'
+
+export const CategoryFactory = factory
+ .define(Category, async ({ faker }) => {
+ return {
+ name: faker.commerce.department(),
+ }
+ })
+ .build()
diff --git a/database/factories/event_factory.ts b/database/factories/event_factory.ts
new file mode 100644
index 0000000..6e3f100
--- /dev/null
+++ b/database/factories/event_factory.ts
@@ -0,0 +1,14 @@
+import factory from '@adonisjs/lucid/factories'
+import Event from '#models/event'
+import { DateTime } from 'luxon'
+
+export const EventFactory = factory
+ .define(Event, async ({ faker }) => {
+ return {
+ name: faker.company.catchPhrase(),
+ description: faker.lorem.paragraph(),
+ date: DateTime.fromJSDate(faker.date.future()),
+ status: faker.helpers.arrayElement(['scheduled', 'ongoing', 'completed']),
+ }
+ })
+ .build()
diff --git a/database/factories/fast_pass_factory.ts b/database/factories/fast_pass_factory.ts
new file mode 100644
index 0000000..a81c624
--- /dev/null
+++ b/database/factories/fast_pass_factory.ts
@@ -0,0 +1,13 @@
+import factory from '@adonisjs/lucid/factories'
+import FastPass from '#models/fast_pass'
+
+export const FastPassFactory = factory
+ .define(FastPass, async ({ faker }) => {
+ return {
+ label: faker.helpers.arrayElement(['1 year', '2 year', '3 year']),
+ description: faker.lorem.sentence(),
+ price: faker.number.int({ min: 10, max: 100 }),
+ duration: faker.number.int({ min: 1, max: 12 }),
+ }
+ })
+ .build()
diff --git a/database/factories/furniture_factory.ts b/database/factories/furniture_factory.ts
new file mode 100644
index 0000000..7636c13
--- /dev/null
+++ b/database/factories/furniture_factory.ts
@@ -0,0 +1,12 @@
+import factory from '@adonisjs/lucid/factories'
+import Furniture from '#models/furniture'
+
+export const FurnitureFactory = factory
+ .define(Furniture, async ({ faker }) => {
+ return {
+ name: faker.commerce.productName(),
+ quantity: faker.number.int({ min: 1, max: 100 }),
+ price: faker.commerce.price(),
+ }
+ })
+ .build()
diff --git a/database/factories/good_factory.ts b/database/factories/good_factory.ts
new file mode 100644
index 0000000..c8ebcd0
--- /dev/null
+++ b/database/factories/good_factory.ts
@@ -0,0 +1,15 @@
+import factory from '@adonisjs/lucid/factories'
+import Good from '#models/good'
+import { CategoryFactory } from './category_factory.js'
+
+export const GoodFactory = factory
+ .define(Good, async ({ faker }) => {
+ return {
+ name: faker.commerce.productName(),
+ unit: faker.helpers.arrayElement(['pcs', 'kg', 'liter']),
+ brand: faker.company.name(),
+ categoryId: null, // Will be set by relation
+ }
+ })
+ .relation('category', () => CategoryFactory)
+ .build()
diff --git a/database/factories/job_factory.ts b/database/factories/job_factory.ts
new file mode 100644
index 0000000..30f82cb
--- /dev/null
+++ b/database/factories/job_factory.ts
@@ -0,0 +1,11 @@
+import factory from '@adonisjs/lucid/factories'
+import Job from '#models/job'
+
+export const JobFactory = factory
+ .define(Job, async ({ faker }) => {
+ return {
+ name: faker.person.jobTitle(),
+ description: faker.lorem.paragraph(),
+ }
+ })
+ .build()
diff --git a/database/factories/log_factory.ts b/database/factories/log_factory.ts
new file mode 100644
index 0000000..8a0d407
--- /dev/null
+++ b/database/factories/log_factory.ts
@@ -0,0 +1,21 @@
+import factory from '@adonisjs/lucid/factories'
+import Log from '#models/log'
+import { UserFactory } from './user_factory.ts'
+
+export const LogFactory = factory
+ .define(Log, async ({ faker }) => {
+ return {
+ level: faker.helpers.arrayElement(['info', 'warning', 'error']),
+ message: faker.lorem.sentence(),
+ method: faker.helpers.arrayElement(['GET', 'POST', 'PUT', 'DELETE']),
+ url: faker.internet.url(),
+ ip: faker.internet.ip(),
+ meta: {
+ userAgent: faker.internet.userAgent(),
+ referrer: faker.internet.url(),
+ },
+ userId: null, // Will be set by relation if needed
+ }
+ })
+ .relation('user', () => UserFactory)
+ .build()
diff --git a/database/factories/member_event_assigned_job_factory.ts b/database/factories/member_event_assigned_job_factory.ts
new file mode 100644
index 0000000..111892f
--- /dev/null
+++ b/database/factories/member_event_assigned_job_factory.ts
@@ -0,0 +1,14 @@
+import factory from '@adonisjs/lucid/factories'
+import MemberEventAssignedJob from '#models/member_event_assigned_job'
+import { MemberFactory } from '#database/factories/members_factory'
+import { EventFactory } from '#database/factories/event_factory'
+import { JobFactory } from '#database/factories/job_factory'
+
+export const MemberEventAssignedJobFactory = factory
+ .define(MemberEventAssignedJob, async () => {
+ return {}
+ })
+ .relation('member', () => MemberFactory)
+ .relation('event', () => EventFactory)
+ .relation('job', () => JobFactory)
+ .build()
diff --git a/database/factories/members_factory.ts b/database/factories/members_factory.ts
new file mode 100644
index 0000000..74d662e
--- /dev/null
+++ b/database/factories/members_factory.ts
@@ -0,0 +1,32 @@
+import factory from '@adonisjs/lucid/factories'
+import Member from '#models/member'
+import { UserFactory } from '#database/factories/user_factory'
+import { RoleFactory } from '#database/factories/role_factory'
+
+export const MemberFactory = factory
+ .define(Member, async ({ faker }) => {
+ return {
+ firstName: faker.person.firstName(),
+ lastName: faker.person.lastName(),
+ roleId: null,
+ }
+ })
+ .before('create', async (builder, member, ctx) => {
+ const requestedBelongsTo = (builder as any).withBelongsToRelations as
+ | undefined
+ | Array<{ name: string }>
+ const willCreateUserViaRelation = requestedBelongsTo?.some(
+ (relation) => relation.name === 'user'
+ )
+
+ if (willCreateUserViaRelation) {
+ return
+ }
+
+ const user = await UserFactory.useCtx(ctx).create()
+ member.id = user.id
+ member.$setRelated('user', user)
+ })
+ .relation('user', () => UserFactory)
+ .relation('role', () => RoleFactory)
+ .build()
diff --git a/database/factories/order_factory.ts b/database/factories/order_factory.ts
new file mode 100644
index 0000000..1cb7237
--- /dev/null
+++ b/database/factories/order_factory.ts
@@ -0,0 +1,16 @@
+import factory from '@adonisjs/lucid/factories'
+import Order from '#models/order'
+import { MemberFactory } from '#database/factories/members_factory'
+import { EventFactory } from '#database/factories/event_factory'
+import { TransactionFactory } from '#database/factories/transaction_factory'
+
+export const OrderFactory = factory
+ .define(Order, async ({ faker }) => {
+ return {
+ status: faker.helpers.arrayElement(['pending', 'completed', 'cancelled']),
+ }
+ })
+ .relation('takenBy', () => MemberFactory)
+ .relation('event', () => EventFactory)
+ .relation('transaction', () => TransactionFactory)
+ .build()
diff --git a/database/factories/permission_factory.ts b/database/factories/permission_factory.ts
new file mode 100644
index 0000000..0bf7611
--- /dev/null
+++ b/database/factories/permission_factory.ts
@@ -0,0 +1,37 @@
+import factory from '@adonisjs/lucid/factories'
+import Permission from '#models/permission'
+
+const permissions = [
+ 'presence:write',
+ 'presence:read',
+ 'stock:read',
+ 'stock:update',
+ 'stock:create',
+ 'stock:delete',
+ 'product:read',
+ 'product:update',
+ 'product:create',
+ 'product:delete',
+ 'supplier:read',
+ 'supplier:update',
+ 'supplier:create',
+ 'supplier:delete',
+ 'restock:read',
+ 'restock:update',
+ 'restock:create',
+ 'restock:delete',
+]
+
+let permissionIndex = 0
+
+export const PermissionFactory = factory
+ .define(Permission, async () => {
+ if (permissionIndex >= permissions.length) {
+ throw new Error('Plus de permissions disponibles (unicité garantie)')
+ }
+
+ return {
+ permission: permissions[permissionIndex++],
+ }
+ })
+ .build()
diff --git a/database/factories/pre_order_factory.ts b/database/factories/pre_order_factory.ts
new file mode 100644
index 0000000..4cf873a
--- /dev/null
+++ b/database/factories/pre_order_factory.ts
@@ -0,0 +1,14 @@
+import factory from '@adonisjs/lucid/factories'
+import PreOrder from '#models/pre_order'
+import { UserFactory } from '#database/factories/user_factory'
+import { EventFactory } from '#database/factories/event_factory'
+import { TransactionFactory } from '#database/factories/transaction_factory'
+
+export const PreOrderFactory = factory
+ .define(PreOrder, async () => {
+ return {}
+ })
+ .relation('user', () => UserFactory)
+ .relation('event', () => EventFactory)
+ .relation('transaction', () => TransactionFactory)
+ .build()
diff --git a/database/factories/product_factory.ts b/database/factories/product_factory.ts
new file mode 100644
index 0000000..248285b
--- /dev/null
+++ b/database/factories/product_factory.ts
@@ -0,0 +1,13 @@
+import factory from '@adonisjs/lucid/factories'
+import Product from '#models/product'
+
+export const ProductFactory = factory
+ .define(Product, async ({ faker }) => {
+ return {
+ name: faker.commerce.productName(),
+ isVegetarian: faker.datatype.boolean(),
+ description: faker.commerce.productDescription(),
+ recipe: faker.lorem.paragraph(),
+ }
+ })
+ .build()
diff --git a/database/factories/restock_factory.ts b/database/factories/restock_factory.ts
new file mode 100644
index 0000000..8e083e6
--- /dev/null
+++ b/database/factories/restock_factory.ts
@@ -0,0 +1,16 @@
+import factory from '@adonisjs/lucid/factories'
+import Restock from '#models/restock'
+import { SupplierFactory } from './supplier_factory.ts'
+import { MemberFactory } from './members_factory.ts'
+
+export const RestockFactory = factory
+ .define(Restock, async ({ faker }) => {
+ return {
+ totalPrice: faker.commerce.price(),
+ memberId: null, // Will be set by relation
+ supplierId: null, // Will be set by relation
+ }
+ })
+ .relation('member', () => MemberFactory)
+ .relation('supplier', () => SupplierFactory)
+ .build()
diff --git a/database/factories/role_factory.ts b/database/factories/role_factory.ts
new file mode 100644
index 0000000..0661138
--- /dev/null
+++ b/database/factories/role_factory.ts
@@ -0,0 +1,17 @@
+import factory from '@adonisjs/lucid/factories'
+import Role from '#models/role'
+
+export const RoleFactory = factory
+ .define(Role, async ({ faker }) => {
+ return {
+ name: faker.helpers.arrayElement([
+ 'President',
+ 'Service',
+ 'Assembly',
+ 'Logistics',
+ 'Finance',
+ 'HR',
+ ]),
+ }
+ })
+ .build()
diff --git a/database/factories/stock_batch_factory.ts b/database/factories/stock_batch_factory.ts
new file mode 100644
index 0000000..5adabb8
--- /dev/null
+++ b/database/factories/stock_batch_factory.ts
@@ -0,0 +1,19 @@
+import factory from '@adonisjs/lucid/factories'
+import StockBatch from '#models/stock_batch'
+import { RestockFactory } from './restock_factory.ts'
+import { GoodFactory } from './good_factory.ts'
+import { DateTime } from 'luxon'
+
+export const StockBatchFactory = factory
+ .define(StockBatch, async ({ faker }) => {
+ return {
+ expirationDate: DateTime.fromJSDate(faker.date.future()),
+ label: faker.commerce.productName(),
+ quantity: faker.number.int({ min: 1, max: 100 }).toString(),
+ restockId: null, // Will be set by relation
+ goodId: null, // Will be set by relation
+ }
+ })
+ .relation('restock', () => RestockFactory)
+ .relation('good', () => GoodFactory)
+ .build()
diff --git a/database/factories/stock_movement_factory.ts b/database/factories/stock_movement_factory.ts
new file mode 100644
index 0000000..c02af18
--- /dev/null
+++ b/database/factories/stock_movement_factory.ts
@@ -0,0 +1,17 @@
+import factory from '@adonisjs/lucid/factories'
+import StockMovement from '#models/stock_movement'
+import { GoodFactory } from './good_factory.ts'
+import { StockBatchFactory } from './stock_batch_factory.ts'
+
+export const StockMovementFactory = factory
+ .define(StockMovement, async ({ faker }) => {
+ return {
+ quantity: faker.number.int({ min: 1, max: 100 }).toString(),
+ movementType: faker.helpers.arrayElement(['in', 'out']),
+ goodId: undefined,
+ stockBatchId: undefined,
+ }
+ })
+ .relation('good', () => GoodFactory)
+ .relation('stockBatch', () => StockBatchFactory)
+ .build()
diff --git a/database/factories/supplier_factory.ts b/database/factories/supplier_factory.ts
new file mode 100644
index 0000000..258d390
--- /dev/null
+++ b/database/factories/supplier_factory.ts
@@ -0,0 +1,10 @@
+import factory from '@adonisjs/lucid/factories'
+import Supplier from '#models/supplier'
+
+export const SupplierFactory = factory
+ .define(Supplier, async ({ faker }) => {
+ return {
+ name: faker.company.name(),
+ }
+ })
+ .build()
diff --git a/database/factories/transaction_factory.ts b/database/factories/transaction_factory.ts
new file mode 100644
index 0000000..7e6e719
--- /dev/null
+++ b/database/factories/transaction_factory.ts
@@ -0,0 +1,11 @@
+import factory from '@adonisjs/lucid/factories'
+import Transaction from '#models/transaction'
+
+export const TransactionFactory = factory
+ .define(Transaction, async ({ faker }) => {
+ return {
+ amount: faker.finance.amount(),
+ type: faker.helpers.arrayElement(['credit', 'debit', 'refund']),
+ }
+ })
+ .build()
diff --git a/database/factories/user_factory.ts b/database/factories/user_factory.ts
new file mode 100644
index 0000000..862f56f
--- /dev/null
+++ b/database/factories/user_factory.ts
@@ -0,0 +1,12 @@
+import factory from '@adonisjs/lucid/factories'
+import User from '#models/user'
+
+export const UserFactory = factory
+ .define(User, async ({ faker }) => {
+ return {
+ email: faker.internet.email(),
+ password: faker.internet.password(),
+ casId: faker.string.uuid(),
+ }
+ })
+ .build()
diff --git a/database/migrations/1761885935168_create_users_table.ts b/database/migrations/1761885935168_create_users_table.ts
index 93770f5..2f8d0e0 100644
--- a/database/migrations/1761885935168_create_users_table.ts
+++ b/database/migrations/1761885935168_create_users_table.ts
@@ -5,7 +5,7 @@ export default class extends BaseSchema {
async up() {
this.schema.createTable(this.tableName, (table) => {
- table.increments('id').notNullable()
+ table.increments('id')
table.string('cas_id').unique().notNullable()
table.string('email', 254).notNullable().unique()
table.string('password').notNullable()
diff --git a/database/migrations/1773828511747_create_members_table.ts b/database/migrations/1773828511747_create_members_table.ts
index 10da26b..a3b5803 100644
--- a/database/migrations/1773828511747_create_members_table.ts
+++ b/database/migrations/1773828511747_create_members_table.ts
@@ -5,7 +5,13 @@ export default class extends BaseSchema {
async up() {
this.schema.createTable(this.tableName, (table) => {
- table.integer('id').references('id').inTable('users').onDelete('CASCADE').primary()
+ table
+ .integer('id')
+ .primary()
+ .notNullable()
+ .references('id')
+ .inTable('users')
+ .onDelete('CASCADE')
table.string('first_name').notNullable()
table.string('last_name').notNullable()
diff --git a/database/schema.ts b/database/schema.ts
index 688c00c..d0a5e46 100644
--- a/database/schema.ts
+++ b/database/schema.ts
@@ -160,13 +160,15 @@ export class FurnitureSchema extends BaseModel {
}
export class GoodSupplierSchema extends BaseModel {
- static $columns = ['createdAt', 'goodId', 'supplierId', 'updatedAt'] as const
+ static $columns = ['createdAt', 'goodId', 'price', 'supplierId', 'updatedAt'] as const
$columns = GoodSupplierSchema.$columns
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime | null
@column()
declare goodId: number
@column()
+ declare price: string
+ @column()
declare supplierId: number
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime | null
@@ -390,21 +392,33 @@ export class PreOrderSchema extends BaseModel {
}
export class ProductFurnitureSchema extends BaseModel {
- static $columns = ['furnitureId', 'productId'] as const
+ static $columns = ['createdAt', 'furnitureId', 'productId', 'quantity', 'updatedAt'] as const
$columns = ProductFurnitureSchema.$columns
+ @column.dateTime({ autoCreate: true })
+ declare createdAt: DateTime
@column()
declare furnitureId: number
@column({ isPrimary: true })
declare productId: number
+ @column()
+ declare quantity: number
+ @column.dateTime({ autoCreate: true, autoUpdate: true })
+ declare updatedAt: DateTime | null
}
export class ProductGoodSchema extends BaseModel {
- static $columns = ['goodId', 'productId'] as const
+ static $columns = ['createdAt', 'goodId', 'productId', 'quantity', 'updatedAt'] as const
$columns = ProductGoodSchema.$columns
+ @column.dateTime({ autoCreate: true })
+ declare createdAt: DateTime
@column()
declare goodId: number
@column({ isPrimary: true })
declare productId: number
+ @column()
+ declare quantity: number
+ @column.dateTime({ autoCreate: true, autoUpdate: true })
+ declare updatedAt: DateTime | null
}
export class ProductSchema extends BaseModel {
@@ -580,8 +594,10 @@ export class TransactionSchema extends BaseModel {
}
export class UserSchema extends BaseModel {
- static $columns = ['createdAt', 'email', 'id', 'password', 'updatedAt'] as const
+ static $columns = ['casId', 'createdAt', 'email', 'id', 'password', 'updatedAt'] as const
$columns = UserSchema.$columns
+ @column()
+ declare casId: string
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime
@column()
diff --git a/database/seeders/category_seeder.ts b/database/seeders/category_seeder.ts
new file mode 100644
index 0000000..9a33a46
--- /dev/null
+++ b/database/seeders/category_seeder.ts
@@ -0,0 +1,8 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { CategoryFactory } from '#database/factories/category_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ await CategoryFactory.createMany(10)
+ }
+}
diff --git a/database/seeders/event_seeder.ts b/database/seeders/event_seeder.ts
new file mode 100644
index 0000000..bac1669
--- /dev/null
+++ b/database/seeders/event_seeder.ts
@@ -0,0 +1,8 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { EventFactory } from '#database/factories/event_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ await EventFactory.createMany(10)
+ }
+}
diff --git a/database/seeders/fast_pass_seeder.ts b/database/seeders/fast_pass_seeder.ts
new file mode 100644
index 0000000..dd42730
--- /dev/null
+++ b/database/seeders/fast_pass_seeder.ts
@@ -0,0 +1,8 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { FastPassFactory } from '#database/factories/fast_pass_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ await FastPassFactory.createMany(5)
+ }
+}
diff --git a/database/seeders/furniture_seeder.ts b/database/seeders/furniture_seeder.ts
new file mode 100644
index 0000000..d5777a5
--- /dev/null
+++ b/database/seeders/furniture_seeder.ts
@@ -0,0 +1,9 @@
+import { FurnitureFactory } from '#database/factories/furniture_factory'
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Write your database queries inside the run method
+ await FurnitureFactory.createMany(10)
+ }
+}
diff --git a/database/seeders/good_seeder.ts b/database/seeders/good_seeder.ts
new file mode 100644
index 0000000..74ed770
--- /dev/null
+++ b/database/seeders/good_seeder.ts
@@ -0,0 +1,17 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { GoodFactory } from '#database/factories/good_factory'
+import { CategoryFactory } from '#database/factories/category_factory'
+
+export default class extends BaseSeeder {
+ public async run() {
+ // 1. Créer des catégories
+ const categories = await CategoryFactory.createMany(3)
+
+ // 2. Créer des goods liés aux catégories
+ await GoodFactory.merge(
+ Array.from({ length: 10 }, (_, index) => ({
+ categoryId: categories[index % categories.length].id,
+ }))
+ ).createMany(10)
+ }
+}
diff --git a/database/seeders/good_supplier_seeder.ts b/database/seeders/good_supplier_seeder.ts
new file mode 100644
index 0000000..0ab76a9
--- /dev/null
+++ b/database/seeders/good_supplier_seeder.ts
@@ -0,0 +1,40 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import Good from '#models/good'
+import Supplier from '#models/supplier'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Write your database queries inside the run method
+ const goods = await Good.all()
+ const suppliers = await Supplier.all()
+
+ console.log(`Found ${goods.length} goods and ${suppliers.length} suppliers`)
+
+ if (goods.length < 2) {
+ throw new Error('Not enough goods in database. Run good_seeder first!')
+ }
+
+ if (suppliers.length === 0) {
+ throw new Error('Not enough suppliers in database. Run supplier_seeder first!')
+ }
+
+ // Pour chaque supplier, attacher plusieurs goods avec des prices
+ for (const supplier of suppliers) {
+ // Sélectionner 2-3 goods aléatoires pour chaque supplier
+ const randomGoodsCount = Math.floor(Math.random() * 2) + 2 // 2 ou 3 goods
+ const selectedGoods = goods
+ .sort(() => 0.5 - Math.random()) // Mélanger
+ .slice(0, randomGoodsCount)
+
+ const pivotData: Record = {}
+
+ for (const good of selectedGoods) {
+ pivotData[good.id] = {
+ price: Math.floor(Math.random() * 1000) + 10, // prix entre 10 et 1000
+ }
+ }
+
+ await supplier.related('goods').sync(pivotData)
+ }
+ }
+}
diff --git a/database/seeders/job_seeder.ts b/database/seeders/job_seeder.ts
new file mode 100644
index 0000000..fc230ea
--- /dev/null
+++ b/database/seeders/job_seeder.ts
@@ -0,0 +1,8 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { JobFactory } from '#database/factories/job_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ await JobFactory.createMany(8)
+ }
+}
diff --git a/database/seeders/log_seeder.ts b/database/seeders/log_seeder.ts
new file mode 100644
index 0000000..68b53c2
--- /dev/null
+++ b/database/seeders/log_seeder.ts
@@ -0,0 +1,21 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import User from '#models/user'
+import { LogFactory } from '#database/factories/log_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ const users = await User.query().select('id')
+
+ if (users.length === 0) {
+ throw new Error('LogSeeder: no users found. Run UserSeeder first.')
+ }
+
+ const pickUserId = () => users[Math.floor(Math.random() * users.length)].id
+
+ await LogFactory.merge(
+ Array.from({ length: 50 }, () => ({
+ userId: pickUserId(),
+ }))
+ ).createMany(50)
+ }
+}
diff --git a/database/seeders/main_seeder.ts b/database/seeders/main_seeder.ts
new file mode 100644
index 0000000..8f4fd3d
--- /dev/null
+++ b/database/seeders/main_seeder.ts
@@ -0,0 +1,60 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import GoodSeeder from './good_seeder.js'
+import FurnitureSeeder from './furniture_seeder.js'
+import ProductSeeder from './product_seeder.js'
+import ProductGoodSeeder from './product_good_seeder.js'
+import ProductFurnitureSeeder from './product_furniture_seeder.js'
+import SupplierSeeder from './supplier_seeder.js'
+import GoodSupplierSeeder from './good_supplier_seeder.js'
+import MemberSeeder from './member_seeder.js'
+import RestockSeeder from './restock_seeder.js'
+import StockBatchSeeder from './stock_batch_seeder.js'
+import StockMovementSeeder from './stock_movement_seeder.js'
+import LogSeeder from './log_seeder.js'
+import RoleSeeder from './role_seeder.js'
+import PermissionSeeder from './permission_seeder.js'
+import RolePermissionSeeder from './role_permission_seeder.js'
+import EventSeeder from './event_seeder.js'
+import JobSeeder from './job_seeder.js'
+import TransactionSeeder from './transaction_seeder.js'
+import FastPassSeeder from './fast_pass_seeder.js'
+import SubscriptionSeeder from './subscription_seeder.js'
+
+export default class extends BaseSeeder {
+ private async runSeeder(Seeder: typeof BaseSeeder) {
+ await new Seeder(this.client).run()
+ }
+
+ public async run() {
+ // 1. Seeders seuls (no dependencies)
+ await this.runSeeder(RoleSeeder)
+ await this.runSeeder(PermissionSeeder)
+ await this.runSeeder(JobSeeder)
+ await this.runSeeder(TransactionSeeder)
+
+ // 2. Seeders dépendants (depends on step 1)
+ await this.runSeeder(RolePermissionSeeder)
+ await this.runSeeder(MemberSeeder)
+ await this.runSeeder(GoodSeeder)
+ await this.runSeeder(FurnitureSeeder)
+ await this.runSeeder(SupplierSeeder)
+ await this.runSeeder(EventSeeder)
+ await this.runSeeder(FastPassSeeder)
+
+ // 3. Seeders dépendants des seeders précédents
+ await this.runSeeder(ProductSeeder)
+ await this.runSeeder(RestockSeeder)
+ await this.runSeeder(LogSeeder)
+ await this.runSeeder(FastPassSeeder)
+
+ // 4. Seeders dépendants des seeders précédents
+ await this.runSeeder(SubscriptionSeeder)
+ await this.runSeeder(ProductGoodSeeder)
+ await this.runSeeder(ProductFurnitureSeeder)
+ await this.runSeeder(GoodSupplierSeeder)
+ await this.runSeeder(StockBatchSeeder)
+
+ // 5. Seeders dépendants des seeders précédents
+ await this.runSeeder(StockMovementSeeder)
+ }
+}
diff --git a/database/seeders/member_seeder.ts b/database/seeders/member_seeder.ts
new file mode 100644
index 0000000..02adfcf
--- /dev/null
+++ b/database/seeders/member_seeder.ts
@@ -0,0 +1,23 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { MemberFactory } from '#database/factories/members_factory'
+import Role from '#models/role'
+
+export default class MemberSeeder extends BaseSeeder {
+ async run() {
+ const roles = await Role.query().select('id')
+
+ if (roles.length === 0) {
+ throw new Error('MemberSeeder: no roles found. Run RoleSeeder first.')
+ }
+
+ const pickRoleId = () => roles[Math.floor(Math.random() * roles.length)].id
+
+ await MemberFactory.with('user')
+ .merge(
+ Array.from({ length: 10 }, () => ({
+ roleId: pickRoleId(),
+ }))
+ )
+ .createMany(10)
+ }
+}
diff --git a/database/seeders/permission_seeder.ts b/database/seeders/permission_seeder.ts
new file mode 100644
index 0000000..f3e2a57
--- /dev/null
+++ b/database/seeders/permission_seeder.ts
@@ -0,0 +1,32 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import Permission from '#models/permission'
+
+const permissions = [
+ 'presence:write',
+ 'presence:read',
+ 'stock:read',
+ 'stock:update',
+ 'stock:create',
+ 'stock:delete',
+ 'product:read',
+ 'product:update',
+ 'product:create',
+ 'product:delete',
+ 'supplier:read',
+ 'supplier:update',
+ 'supplier:create',
+ 'supplier:delete',
+ 'restock:read',
+ 'restock:update',
+ 'restock:create',
+ 'restock:delete',
+]
+
+export default class extends BaseSeeder {
+ async run() {
+ await Permission.fetchOrCreateMany(
+ 'permission',
+ permissions.map((permission) => ({ permission }))
+ )
+ }
+}
diff --git a/database/seeders/product_furniture_seeder.ts b/database/seeders/product_furniture_seeder.ts
new file mode 100644
index 0000000..33d0de3
--- /dev/null
+++ b/database/seeders/product_furniture_seeder.ts
@@ -0,0 +1,18 @@
+import Furniture from '#models/furniture'
+import Product from '#models/product'
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Write your database queries inside the run method.
+ const products = await Product.all()
+ const funrnitures = await Furniture.all()
+
+ for (const product of products) {
+ await product.related('furnitures').sync({
+ [funrnitures[0].id]: { quantity: 2 },
+ [funrnitures[1].id]: { quantity: 5 },
+ })
+ }
+ }
+}
diff --git a/database/seeders/product_good_seeder.ts b/database/seeders/product_good_seeder.ts
new file mode 100644
index 0000000..cfb66c6
--- /dev/null
+++ b/database/seeders/product_good_seeder.ts
@@ -0,0 +1,39 @@
+import Good from '#models/good'
+import Product from '#models/product'
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+
+export default class extends BaseSeeder {
+ async run() {
+ const goods = await Good.all()
+ const products = await Product.all()
+
+ console.log(`Found ${goods.length} goods and ${products.length} products`)
+
+ if (goods.length < 2) {
+ throw new Error('Not enough goods in database. Run good_seeder first!')
+ }
+
+ if (products.length === 0) {
+ throw new Error('Not enough products in database. Run product_seeder first!')
+ }
+
+ // Pour chaque product, attacher plusieurs goods avec des quantités
+ for (const product of products) {
+ // Sélectionner 2-3 goods aléatoires pour chaque product
+ const randomGoodsCount = Math.floor(Math.random() * 2) + 2 // 2 ou 3 goods
+ const selectedGoods = goods
+ .sort(() => 0.5 - Math.random()) // Mélanger
+ .slice(0, randomGoodsCount)
+
+ const pivotData: Record = {}
+
+ for (const good of selectedGoods) {
+ pivotData[good.id] = {
+ quantity: Math.floor(Math.random() * 10) + 1, // quantité entre 1 et 10
+ }
+ }
+
+ await product.related('goods').sync(pivotData)
+ }
+ }
+}
diff --git a/database/seeders/product_seeder.ts b/database/seeders/product_seeder.ts
new file mode 100644
index 0000000..f823e45
--- /dev/null
+++ b/database/seeders/product_seeder.ts
@@ -0,0 +1,9 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { ProductFactory } from '#database/factories/product_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Write your database queries inside the run method
+ await ProductFactory.createMany(10)
+ }
+}
diff --git a/database/seeders/restock_seeder.ts b/database/seeders/restock_seeder.ts
new file mode 100644
index 0000000..c2bd7ea
--- /dev/null
+++ b/database/seeders/restock_seeder.ts
@@ -0,0 +1,19 @@
+import { SupplierFactory } from '#database/factories/supplier_factory'
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { RestockFactory } from '#database/factories/restock_factory'
+import { MemberFactory } from '#database/factories/members_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Write your database queries inside the run method
+ const suppliers = await SupplierFactory.createMany(5)
+ const members = await MemberFactory.createMany(5)
+
+ await RestockFactory.merge(
+ Array.from({ length: 10 }, (_, index) => ({
+ supplierId: suppliers[index % suppliers.length].id,
+ memberId: members[index % members.length].id,
+ }))
+ ).createMany(10)
+ }
+}
diff --git a/database/seeders/role_permission_seeder.ts b/database/seeders/role_permission_seeder.ts
new file mode 100644
index 0000000..7640f57
--- /dev/null
+++ b/database/seeders/role_permission_seeder.ts
@@ -0,0 +1,73 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import Role from '#models/role'
+import Permission from '#models/permission'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Fetch all roles and permissions
+ const roles = await Role.all()
+ const permissions = await Permission.all()
+
+ // Define permission mapping for different roles
+ const rolePermissionMap: Record = {
+ President: [
+ 'presence:write',
+ 'presence:read',
+ 'stock:read',
+ 'stock:update',
+ 'stock:create',
+ 'stock:delete',
+ 'product:read',
+ 'product:update',
+ 'product:create',
+ 'product:delete',
+ 'supplier:read',
+ 'supplier:update',
+ 'supplier:create',
+ 'supplier:delete',
+ 'restock:read',
+ 'restock:update',
+ 'restock:create',
+ 'restock:delete',
+ ],
+ Service: [
+ 'presence:read',
+ 'stock:read',
+ 'product:read',
+ 'supplier:read',
+ 'restock:read',
+ 'restock:create',
+ ],
+ Assembly: ['presence:read', 'stock:read', 'product:read'],
+ Logistics: [
+ 'stock:read',
+ 'stock:update',
+ 'stock:create',
+ 'product:read',
+ 'supplier:read',
+ 'supplier:update',
+ 'restock:read',
+ 'restock:update',
+ 'restock:create',
+ ],
+ Finance: [
+ 'supplier:read',
+ 'supplier:update',
+ 'restock:read',
+ 'restock:update',
+ 'product:read',
+ ],
+ HR: ['presence:write', 'presence:read'],
+ }
+
+ // Assign permissions to roles
+ for (const role of roles) {
+ const permissionNames = rolePermissionMap[role.name] || []
+ const rolePermissions = permissions.filter((p) => permissionNames.includes(p.permission))
+
+ if (rolePermissions.length > 0) {
+ await role.related('permissions').attach(rolePermissions.map((p) => p.permission))
+ }
+ }
+ }
+}
diff --git a/database/seeders/role_seeder.ts b/database/seeders/role_seeder.ts
new file mode 100644
index 0000000..b582eee
--- /dev/null
+++ b/database/seeders/role_seeder.ts
@@ -0,0 +1,9 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { RoleFactory } from '#database/factories/role_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Write your database queries inside the run method
+ await RoleFactory.createMany(5)
+ }
+}
diff --git a/database/seeders/stock_batch_seeder.ts b/database/seeders/stock_batch_seeder.ts
new file mode 100644
index 0000000..b249dab
--- /dev/null
+++ b/database/seeders/stock_batch_seeder.ts
@@ -0,0 +1,26 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { StockBatchFactory } from '#database/factories/stock_batch_factory'
+import Good from '#models/good'
+import Restock from '#models/restock'
+
+export default class extends BaseSeeder {
+ async run() {
+ const goods = await Good.query().select('id')
+ const restocks = await Restock.query().select('id')
+
+ if (goods.length === 0) {
+ throw new Error('StockBatchSeeder: no goods found. Run GoodSeeder first.')
+ }
+
+ if (restocks.length === 0) {
+ throw new Error('StockBatchSeeder: no restocks found. Run RestockSeeder first.')
+ }
+
+ await StockBatchFactory.merge(
+ Array.from({ length: 10 }, (_, index) => ({
+ goodId: goods[index % goods.length].id,
+ restockId: restocks[index % restocks.length].id,
+ }))
+ ).createMany(10)
+ }
+}
diff --git a/database/seeders/stock_movement_seeder.ts b/database/seeders/stock_movement_seeder.ts
new file mode 100644
index 0000000..706cc54
--- /dev/null
+++ b/database/seeders/stock_movement_seeder.ts
@@ -0,0 +1,44 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import Good from '#models/good'
+import StockBatch from '#models/stock_batch'
+import { StockMovementFactory } from '#database/factories/stock_movement_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Write your database queries inside the run method
+ const goods = await Good.query().select('id')
+ const stockBatches = await StockBatch.query().select('id')
+
+ if (goods.length === 0) {
+ throw new Error('StockMovementSeeder: no goods found. Run GoodSeeder first.')
+ }
+
+ if (stockBatches.length === 0) {
+ throw new Error('StockMovementSeeder: no stock batches found. Run StockBatchSeeder first.')
+ }
+
+ console.log(
+ `Seeding stock movements with ${goods.length} goods and ${stockBatches.length} stock batches...`
+ )
+
+ const pickId = (rows: Array<{ id: number }>) => rows[Math.floor(Math.random() * rows.length)].id
+
+ await StockMovementFactory.merge(
+ Array.from({ length: 20 }, () => {
+ const goodId = pickId(goods)
+
+ let stockBatchId = pickId(stockBatches)
+ if (stockBatches.length > 1) {
+ while (stockBatchId === goodId) {
+ stockBatchId = pickId(stockBatches)
+ }
+ }
+
+ return {
+ goodId,
+ stockBatchId,
+ }
+ })
+ ).createMany(20)
+ }
+}
diff --git a/database/seeders/subscription_seeder.ts b/database/seeders/subscription_seeder.ts
new file mode 100644
index 0000000..0e3d5e3
--- /dev/null
+++ b/database/seeders/subscription_seeder.ts
@@ -0,0 +1,22 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import User from '#models/user'
+import FastPass from '#models/fast_pass'
+import { DateTime } from 'luxon'
+
+export default class extends BaseSeeder {
+ async run() {
+ const users = await User.all()
+ const fastPasses = await FastPass.all()
+
+ if (users.length === 0 || fastPasses.length < 2) {
+ return
+ }
+
+ for (const user of users) {
+ await user.related('fastPasses').sync({
+ [fastPasses[0].id]: { subscribed_at: DateTime.now() },
+ [fastPasses[1].id]: { subscribed_at: DateTime.now() },
+ })
+ }
+ }
+}
diff --git a/database/seeders/supplier_seeder.ts b/database/seeders/supplier_seeder.ts
new file mode 100644
index 0000000..c73ff64
--- /dev/null
+++ b/database/seeders/supplier_seeder.ts
@@ -0,0 +1,9 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { SupplierFactory } from '#database/factories/supplier_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ // Write your database queries inside the run method
+ await SupplierFactory.createMany(10)
+ }
+}
diff --git a/database/seeders/transaction_seeder.ts b/database/seeders/transaction_seeder.ts
new file mode 100644
index 0000000..fcfeb86
--- /dev/null
+++ b/database/seeders/transaction_seeder.ts
@@ -0,0 +1,8 @@
+import { BaseSeeder } from '@adonisjs/lucid/seeders'
+import { TransactionFactory } from '#database/factories/transaction_factory'
+
+export default class extends BaseSeeder {
+ async run() {
+ await TransactionFactory.createMany(15)
+ }
+}
diff --git a/start/routes.ts b/start/routes.ts
index 720a100..b1b8c4c 100644
--- a/start/routes.ts
+++ b/start/routes.ts
@@ -14,3 +14,28 @@ router.get('/', () => {
})
router.group(() => {}).prefix('/v1')
+
+router
+ .group(() => {
+ router.resource('members', () => import('#controllers/members_controller')).apiOnly()
+ router.resource('categories', () => import('#controllers/categories_controller')).apiOnly()
+ router.resource('furnitures', () => import('#controllers/furnitures_controller')).apiOnly()
+ router.resource('products', () => import('#controllers/products_controller')).apiOnly()
+ router.resource('goods', () => import('#controllers/goods_controller')).apiOnly()
+ router.resource('suppliers', () => import('#controllers/suppliers_controller')).apiOnly()
+ router.resource('restocks', () => import('#controllers/restocks_controller')).apiOnly()
+ router
+ .resource('stock-batches', () => import('#controllers/stock_batches_controller'))
+ .apiOnly()
+ router
+ .resource('stock-movements', () => import('#controllers/stock_movements_controller'))
+ .apiOnly()
+ router.resource('logs', () => import('#controllers/logs_controller')).apiOnly()
+ router.resource('roles', () => import('#controllers/roles_controller')).apiOnly()
+ router.resource('permissions', () => import('#controllers/permissions_controller')).apiOnly()
+ })
+ .prefix('/v1')
+
+router.get('/test', async () => {
+ return { message: 'ok' }
+})