feat(mock): added mock-seeds scripts

This commit is contained in:
Matthieu Haineault 2025-08-12 12:09:57 -04:00
parent 22fb29b8fa
commit 4496c1e419
18 changed files with 1272 additions and 1 deletions

498
package-lock.json generated
View File

@ -55,6 +55,7 @@
"ts-loader": "^9.5.2", "ts-loader": "^9.5.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"tsx": "^4.20.4",
"typescript": "^5.7.3", "typescript": "^5.7.3",
"typescript-eslint": "^8.20.0" "typescript-eslint": "^8.20.0"
} }
@ -719,6 +720,422 @@
"@jridgewell/sourcemap-codec": "^1.4.10" "@jridgewell/sourcemap-codec": "^1.4.10"
} }
}, },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz",
"integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz",
"integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz",
"integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz",
"integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz",
"integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz",
"integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz",
"integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz",
"integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz",
"integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz",
"integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz",
"integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz",
"integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==",
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz",
"integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==",
"cpu": [
"mips64el"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz",
"integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz",
"integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==",
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz",
"integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==",
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz",
"integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz",
"integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz",
"integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz",
"integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz",
"integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz",
"integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz",
"integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz",
"integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz",
"integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz",
"integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@eslint-community/eslint-utils": { "node_modules/@eslint-community/eslint-utils": {
"version": "4.7.0", "version": "4.7.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
@ -5942,6 +6359,47 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/esbuild": {
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz",
"integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==",
"dev": true,
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.8",
"@esbuild/android-arm": "0.25.8",
"@esbuild/android-arm64": "0.25.8",
"@esbuild/android-x64": "0.25.8",
"@esbuild/darwin-arm64": "0.25.8",
"@esbuild/darwin-x64": "0.25.8",
"@esbuild/freebsd-arm64": "0.25.8",
"@esbuild/freebsd-x64": "0.25.8",
"@esbuild/linux-arm": "0.25.8",
"@esbuild/linux-arm64": "0.25.8",
"@esbuild/linux-ia32": "0.25.8",
"@esbuild/linux-loong64": "0.25.8",
"@esbuild/linux-mips64el": "0.25.8",
"@esbuild/linux-ppc64": "0.25.8",
"@esbuild/linux-riscv64": "0.25.8",
"@esbuild/linux-s390x": "0.25.8",
"@esbuild/linux-x64": "0.25.8",
"@esbuild/netbsd-arm64": "0.25.8",
"@esbuild/netbsd-x64": "0.25.8",
"@esbuild/openbsd-arm64": "0.25.8",
"@esbuild/openbsd-x64": "0.25.8",
"@esbuild/openharmony-arm64": "0.25.8",
"@esbuild/sunos-x64": "0.25.8",
"@esbuild/win32-arm64": "0.25.8",
"@esbuild/win32-ia32": "0.25.8",
"@esbuild/win32-x64": "0.25.8"
}
},
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@ -6898,6 +7356,18 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/get-tsconfig": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
"integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==",
"dev": true,
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
},
"funding": {
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
"node_modules/glob": { "node_modules/glob": {
"version": "11.0.1", "version": "11.0.1",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz",
@ -9646,6 +10116,15 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/resolve-pkg-maps": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
"node_modules/resolve.exports": { "node_modules/resolve.exports": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
@ -10886,6 +11365,25 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
}, },
"node_modules/tsx": {
"version": "4.20.4",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.4.tgz",
"integrity": "sha512-yyxBKfORQ7LuRt/BQKBXrpcq59ZvSW0XxwfjAt3w2/8PmdxaFzijtMhTawprSHhpzeM5BgU2hXHG3lklIERZXg==",
"dev": true,
"dependencies": {
"esbuild": "~0.25.0",
"get-tsconfig": "^4.7.5"
},
"bin": {
"tsx": "dist/cli.mjs"
},
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
}
},
"node_modules/type-check": { "node_modules/type-check": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",

View File

@ -17,7 +17,26 @@
"test:watch": "jest --watch", "test:watch": "jest --watch",
"test:cov": "jest --coverage", "test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json" "test:e2e": "jest --config ./test/jest-e2e.json",
"prisma:generate": "prisma generate",
"db:migrate": "prisma migrate dev --name init",
"db:reset": "prisma migrate reset --force",
"seed:01": "tsx prisma/mock-seeds-scripts/01-bankcodes.ts",
"seed:02": "tsx prisma/mock-seeds-scripts/02-users.ts",
"seed:03": "tsx prisma/mock-seeds-scripts/03-employees.ts",
"seed:04": "tsx prisma/mock-seeds-scripts/04-customers.ts",
"seed:05": "tsx prisma/mock-seeds-scripts/05-employees-archive.ts",
"seed:06": "tsx prisma/mock-seeds-scripts/06-customers-archive.ts",
"seed:07": "tsx prisma/mock-seeds-scripts/07-leave-requests-future.ts",
"seed:08": "tsx prisma/mock-seeds-scripts/08-leave-requests-archive.ts",
"seed:09": "tsx prisma/mock-seeds-scripts/09-timesheets.ts",
"seed:10": "tsx prisma/mock-seeds-scripts/10-shifts.ts",
"seed:11": "tsx prisma/mock-seeds-scripts/11-shifts-archive.ts",
"seed:12": "tsx prisma/mock-seeds-scripts/12-expenses.ts",
"seed:13": "tsx prisma/mock-seeds-scripts/13-expenses-archive.ts",
"seed:14": "tsx prisma/mock-seeds-scripts/14-oauth-sessions.ts",
"seed:all": "npm run seed:01 && npm run seed:02 && npm run seed:03 && npm run seed:04 && npm run seed:05 && npm run seed:06 && npm run seed:07 && npm run seed:08 && npm run seed:09 && npm run seed:10 && npm run seed:11 && npm run seed:12 && npm run seed:13 && npm run seed:14",
"db:reseed": "npm run db:reset && npm run seed:all"
}, },
"dependencies": { "dependencies": {
"@nestjs/common": "^11.0.1", "@nestjs/common": "^11.0.1",
@ -66,6 +85,7 @@
"ts-loader": "^9.5.2", "ts-loader": "^9.5.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"tsx": "^4.20.4",
"typescript": "^5.7.3", "typescript": "^5.7.3",
"typescript-eslint": "^8.20.0" "typescript-eslint": "^8.20.0"
}, },

View File

@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "leave_types" ADD VALUE 'WEDDING';

View File

@ -0,0 +1,40 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const presets = [
// type, categorie, modifier, bank_code
['SHIFT', 'REGULAR', 1.0, 'REG'],
['SHIFT', 'EVENING', 1.15, 'EVE'],
['SHIFT', 'NIGHT', 1.25, 'NGT'],
['SHIFT', 'WEEKEND', 1.5, 'WKD'],
['SHIFT', 'HOLIDAY', 2.0, 'HLD'],
['EXPENSE', 'MEAL', 1.0, 'EXP_MEAL'],
['EXPENSE', 'MILEAGE', 1.0, 'EXP_MILE'],
['EXPENSE', 'HOTEL', 1.0, 'EXP_HOTEL'],
['EXPENSE', 'SUPPLIES', 1.0, 'EXP_SUP'],
['LEAVE', 'SICK', 1.0, 'LV_SICK'],
['LEAVE', 'VACATION', 1.0, 'LV_VAC'],
['LEAVE', 'UNPAID', 0.0, 'LV_UNP'],
['LEAVE', 'BEREAVEMENT', 1.0, 'LV_BER'],
['LEAVE', 'PARENTAL', 1.0, 'LV_PAR'],
['LEAVE', 'LEGAL', 1.0, 'LV_LEG'],
];
await prisma.bankCodes.createMany({
data: presets.map(([type, categorie, modifier, bank_code]) => ({
type: String(type),
categorie: String(categorie),
modifier: Number(modifier),
bank_code: String(bank_code),
})),
skipDuplicates: true,
});
console.log('✓ BankCodes: 15 rows');
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,70 @@
import { PrismaClient, Roles } from '@prisma/client';
const prisma = new PrismaClient();
const BASE_PHONE = 1_100_000_000; // < 2_147_483_647
function emailFor(i: number) {
return `user${i + 1}@example.test`;
}
async function main() {
// 50 users total: 40 employees + 10 customers
// Roles distribution for the 40 employees:
// 1 ADMIN, 4 SUPERVISOR, 1 HR, 1 ACCOUNTING, 33 EMPLOYEE
// 10 CUSTOMER (non-employees)
const usersData: {
first_name: string;
last_name: string;
email: string;
phone_number: number;
residence?: string | null;
role: Roles;
}[] = [];
const firstNames = ['Alex','Sam','Chris','Jordan','Taylor','Morgan','Jamie','Robin','Avery','Casey'];
const lastNames = ['Smith','Johnson','Williams','Brown','Jones','Miller','Davis','Wilson','Taylor','Clark'];
// helper to pick
const pick = <T>(arr: T[]) => arr[Math.floor(Math.random() * arr.length)];
const rolesForEmployees: Roles[] = [
Roles.ADMIN,
...Array(4).fill(Roles.SUPERVISOR),
Roles.HR,
Roles.ACCOUNTING,
...Array(33).fill(Roles.EMPLOYEE),
];
// 40 employees
for (let i = 0; i < 40; i++) {
const fn = pick(firstNames);
const ln = pick(lastNames);
usersData.push({
first_name: fn,
last_name: ln,
email: emailFor(i),
phone_number: BASE_PHONE + i,
residence: Math.random() < 0.5 ? 'QC' : 'ON',
role: rolesForEmployees[i],
});
}
// 10 customers
for (let i = 40; i < 50; i++) {
const fn = pick(firstNames);
const ln = pick(lastNames);
usersData.push({
first_name: fn,
last_name: ln,
email: emailFor(i),
phone_number: BASE_PHONE + i,
residence: Math.random() < 0.5 ? 'QC' : 'ON',
role: Roles.CUSTOMER,
});
}
await prisma.users.createMany({ data: usersData, skipDuplicates: true });
console.log('✓ Users: 50 rows (40 employees, 10 customers)');
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,68 @@
import { PrismaClient, Roles } from '@prisma/client';
const prisma = new PrismaClient();
function randInt(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function randomPastDate(yearsBack = 3) {
const now = new Date();
const past = new Date(now);
past.setFullYear(now.getFullYear() - yearsBack);
const t = randInt(past.getTime(), now.getTime());
const d = new Date(t);
d.setHours(0,0,0,0);
return d;
}
async function main() {
const employeeUsers = await prisma.users.findMany({
where: { role: { in: [Roles.ADMIN, Roles.SUPERVISOR, Roles.HR, Roles.ACCOUNTING, Roles.EMPLOYEE] } },
orderBy: { email: 'asc' },
});
// Create supervisors first
const supervisorUsers = employeeUsers.filter(u => u.role === Roles.SUPERVISOR);
const supervisorEmployeeIds: number[] = [];
for (const u of supervisorUsers) {
const emp = await prisma.employees.upsert({
where: { user_id: u.id },
update: {},
create: {
user_id: u.id,
external_payroll_id: randInt(10000, 99999),
company_code: randInt(1, 5),
first_work_day: randomPastDate(3),
last_work_day: null,
},
});
supervisorEmployeeIds.push(emp.id);
}
// Create remaining employees, assign a random supervisor (admin can have none)
for (const u of employeeUsers) {
const already = await prisma.employees.findUnique({ where: { user_id: u.id } });
if (already) continue;
const supervisor_id =
u.role === Roles.ADMIN ? null : supervisorEmployeeIds[randInt(0, supervisorEmployeeIds.length - 1)];
await prisma.employees.create({
data: {
user_id: u.id,
external_payroll_id: randInt(10000, 99999),
company_code: randInt(1, 5),
first_work_day: randomPastDate(3),
last_work_day: null,
supervisor_id,
},
});
}
const total = await prisma.employees.count();
console.log(`✓ Employees: ${total} rows (with supervisors linked)`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,28 @@
import { PrismaClient, Roles } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const customerUsers = await prisma.users.findMany({
where: { role: Roles.CUSTOMER },
orderBy: { email: 'asc' },
});
let i = 0;
for (const u of customerUsers) {
await prisma.customers.upsert({
where: { user_id: u.id },
update: {},
create: {
user_id: u.id,
invoice_id: i % 2 === 0 ? 100000 + i : null, // 1 sur 2 a un invoice_id
},
});
i++;
}
const total = await prisma.customers.count();
console.log(`✓ Customers: ${total} rows`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,38 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
function daysAgo(n: number) {
const d = new Date();
d.setDate(d.getDate() - n);
d.setHours(0,0,0,0);
return d;
}
async function main() {
const employees = await prisma.employees.findMany({
include: { user: true },
take: 10, // archive 10
});
for (const e of employees) {
await prisma.employeesArchive.create({
data: {
employee_id: e.id,
user_id: e.user_id,
first_name: e.user.first_name,
last_name: e.user.last_name,
external_payroll_id: e.external_payroll_id,
company_code: e.company_code,
first_Work_Day: e.first_work_day,
last_work_day: daysAgo(30),
supervisor_id: e.supervisor_id ?? null,
},
});
}
const total = await prisma.employeesArchive.count();
console.log(`✓ EmployeesArchive: ${total} rows (added 10)`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,29 @@
// prisma/mock-seeds-scripts/06-customers-archive.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const customers = await prisma.customers.findMany({
orderBy: { id: 'asc' },
take: 5,
});
for (const c of customers) {
const invoiceId = 200000 + c.id; // déterministe, stable entre runs
await prisma.customersArchive.upsert({
where: { invoice_id: invoiceId }, // invoice_id est unique
update: {}, // idempotent
create: {
customer_id: c.id,
user_id: c.user_id,
invoice_id: invoiceId,
},
});
}
const total = await prisma.customersArchive.count();
console.log(`✓ CustomersArchive upserted for ${customers.length} customers (total=${total})`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,76 @@
import { PrismaClient, Prisma, LeaveTypes, LeaveApprovalStatus } from '@prisma/client';
const prisma = new PrismaClient();
function dateOn(y: number, m: number, d: number) {
// stocke une date (pour @db.Date) à minuit UTC
return new Date(Date.UTC(y, m - 1, d, 0, 0, 0));
}
async function main() {
const year = new Date().getFullYear();
const today = new Date();
const employees = await prisma.employees.findMany({ select: { id: true } });
const bankCodes = await prisma.bankCodes.findMany({
where: { type: 'LEAVE' },
select: { id: true },
});
if (!employees.length || !bankCodes.length) {
console.warn('No employees or LEAVE bank codes; aborting');
return;
}
const types: LeaveTypes[] = [
LeaveTypes.SICK,
LeaveTypes.VACATION,
LeaveTypes.UNPAID,
LeaveTypes.BEREAVEMENT,
LeaveTypes.PARENTAL,
LeaveTypes.LEGAL,
LeaveTypes.WEDDING,
];
const statuses: LeaveApprovalStatus[] = [
LeaveApprovalStatus.PENDING,
LeaveApprovalStatus.APPROVED,
LeaveApprovalStatus.DENIED,
LeaveApprovalStatus.CANCELLED,
LeaveApprovalStatus.ESCALATED,
];
const futureMonths = [8, 9, 10, 11, 12]; // Août→Déc (1-based)
// ✅ typer rows pour éviter never[]
const rows: Prisma.LeaveRequestsCreateManyInput[] = [];
for (let i = 0; i < 10; i++) {
const emp = employees[i % employees.length];
const m = futureMonths[i % futureMonths.length];
const start = dateOn(year, m, 5 + i); // 5..14
if (start <= today) continue; // garantir "futur"
const end = Math.random() < 0.5 ? null : dateOn(year, m, 6 + i);
const type = types[i % types.length];
const status = statuses[i % statuses.length];
const bc = bankCodes[i % bankCodes.length];
rows.push({
employee_id: emp.id,
bank_code_id: bc.id,
leave_type: type,
start_date_time: start,
end_date_time: end, // ok: Date | null
comment: `Future leave #${i + 1}`,
approval_status: status,
});
}
if (rows.length) {
await prisma.leaveRequests.createMany({ data: rows });
}
console.log(`✓ LeaveRequests (future): ${rows.length} rows`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,60 @@
import { PrismaClient, LeaveTypes, LeaveApprovalStatus, LeaveRequests } from '@prisma/client';
const prisma = new PrismaClient();
function daysAgo(n:number) {
const d = new Date();
d.setUTCDate(d.getUTCDate() - n);
d.setUTCHours(0,0,0,0);
return d;
}
async function main() {
const employees = await prisma.employees.findMany({ select: { id: true } });
const bankCodes = await prisma.bankCodes.findMany({ select: { id: true }, where: { type: 'LEAVE' } });
const types = Object.values(LeaveTypes);
const statuses = Object.values(LeaveApprovalStatus);
// ✅ typer le tableau pour éviter never[]
const created: LeaveRequests[] = [];
for (let i = 0; i < 10; i++) {
const emp = employees[i % employees.length];
const bc = bankCodes[i % bankCodes.length];
const start = daysAgo(120 - i * 3); // tous avant aujourd'hui
const end = Math.random() < 0.4 ? null : daysAgo(119 - i * 3);
const lr = await prisma.leaveRequests.create({
data: {
employee_id: emp.id,
bank_code_id: bc.id,
leave_type: types[i % types.length],
start_date_time: start,
end_date_time: end,
comment: `Past leave #${i+1}`,
approval_status: statuses[(i+2) % statuses.length],
},
});
created.push(lr);
}
for (const lr of created) {
await prisma.leaveRequestsArchive.create({
data: {
leave_request_id: lr.id,
employee_id: lr.employee_id,
leave_type: lr.leave_type,
start_date_time: lr.start_date_time,
end_date_time: lr.end_date_time,
comment: lr.comment,
approval_status: lr.approval_status,
},
});
}
console.log(`✓ LeaveRequestsArchive: ${created.length} rows`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,27 @@
import { PrismaClient, Prisma } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const employees = await prisma.employees.findMany({ select: { id: true } });
// ✅ typer rows pour éviter never[]
const rows: Prisma.TimesheetsCreateManyInput[] = [];
// 8 timesheets / employee
for (const e of employees) {
for (let i = 0; i < 8; i++) {
const is_approved = Math.random() < 0.3;
rows.push({ employee_id: e.id, is_approved });
}
}
if (rows.length) {
await prisma.timesheets.createMany({ data: rows });
}
const total = await prisma.timesheets.count();
console.log(`✓ Timesheets: ${total} rows (added ${rows.length})`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,55 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
function timeAt(hour:number, minute:number) {
// stocker une heure (Postgres TIME) via Date (UTC 1970-01-01)
return new Date(Date.UTC(1970, 0, 1, hour, minute, 0));
}
function daysAgo(n:number) {
const d = new Date();
d.setUTCDate(d.getUTCDate() - n);
d.setUTCHours(0,0,0,0);
return d;
}
async function main() {
const bankCodes = await prisma.bankCodes.findMany({ where: { type: 'SHIFT' }, select: { id: true } });
if (!bankCodes.length) throw new Error('Need SHIFT bank codes');
const employees = await prisma.employees.findMany({ select: { id: true } });
for (const e of employees) {
const tss = await prisma.timesheets.findMany({
where: { employee_id: e.id },
select: { id: true },
});
if (!tss.length) continue;
// 10 shifts / employee
for (let i = 0; i < 10; i++) {
const ts = tss[i % tss.length];
const bc = bankCodes[i % bankCodes.length];
const date = daysAgo(7 + i); // la dernière quinzaine
const startH = 8 + (i % 3); // 8..10
const endH = startH + 7 + (i % 2); // 15..17
await prisma.shifts.create({
data: {
timesheet_id: ts.id,
bank_code_id: bc.id,
description: `Shift ${i + 1} for emp ${e.id}`,
date,
start_time: timeAt(startH, 0),
end_time: timeAt(endH, 0),
is_approved: Math.random() < 0.5,
},
});
}
}
const total = await prisma.shifts.count();
console.log(`✓ Shifts: ${total} total rows`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,66 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
function timeAt(h:number,m:number) {
return new Date(Date.UTC(1970,0,1,h,m,0));
}
function daysAgo(n:number) {
const d = new Date();
d.setUTCDate(d.getUTCDate() - n);
d.setUTCHours(0,0,0,0);
return d;
}
async function main() {
const bankCodes = await prisma.bankCodes.findMany({ where: { type: 'SHIFT' }, select: { id: true } });
const employees = await prisma.employees.findMany({ select: { id: true } });
for (const e of employees) {
const tss = await prisma.timesheets.findMany({ where: { employee_id: e.id }, select: { id: true } });
if (!tss.length) continue;
const createdShiftIds: number[] = [];
for (let i = 0; i < 30; i++) {
const ts = tss[i % tss.length];
const bc = bankCodes[i % bankCodes.length];
const date = daysAgo(200 + i); // bien dans le passé
const startH = 7 + (i % 4); // 7..10
const endH = startH + 8; // 15..18
const sh = await prisma.shifts.create({
data: {
timesheet_id: ts.id,
bank_code_id: bc.id,
description: `Archived-era shift ${i + 1} for emp ${e.id}`,
date,
start_time: timeAt(startH, 0),
end_time: timeAt(endH, 0),
is_approved: true,
},
});
createdShiftIds.push(sh.id);
}
for (const sid of createdShiftIds) {
const s = await prisma.shifts.findUnique({ where: { id: sid } });
if (!s) continue;
await prisma.shiftsArchive.create({
data: {
shift_id: s.id,
timesheet_id: s.timesheet_id,
bank_code_id: s.bank_code_id,
description: s.description,
date: s.date,
start_time: s.start_time,
end_time: s.end_time,
},
});
}
}
const total = await prisma.shiftsArchive.count();
console.log(`✓ ShiftsArchive: ${total} rows total`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,44 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
function daysAgo(n:number) {
const d = new Date();
d.setUTCDate(d.getUTCDate() - n);
d.setUTCHours(0,0,0,0);
return d;
}
async function main() {
const expenseCodes = await prisma.bankCodes.findMany({ where: { type: 'EXPENSE' }, select: { id: true } });
if (!expenseCodes.length) throw new Error('Need EXPENSE bank codes');
const timesheets = await prisma.timesheets.findMany({ select: { id: true } });
if (!timesheets.length) {
console.warn('No timesheets found; aborting expenses seed.');
return;
}
// 5 expenses distribuées aléatoirement parmi les employés (via timesheets)
for (let i = 0; i < 5; i++) {
const ts = timesheets[Math.floor(Math.random() * timesheets.length)];
const bc = expenseCodes[i % expenseCodes.length];
await prisma.expenses.create({
data: {
timesheet_id: ts.id,
bank_code_id: bc.id,
date: daysAgo(3 + i),
amount: (50 + i * 10).toFixed(2),
attachement: null,
description: `Expense #${i + 1}`,
is_approved: Math.random() < 0.5,
supervisor_comment: Math.random() < 0.3 ? 'OK' : null,
},
});
}
const total = await prisma.expenses.count();
console.log(`✓ Expenses: ${total} total rows`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,60 @@
// 13-expenses-archive.ts
import { PrismaClient, Expenses } from '@prisma/client';
const prisma = new PrismaClient();
function daysAgo(n:number) {
const d = new Date();
d.setUTCDate(d.getUTCDate() - n);
d.setUTCHours(0,0,0,0);
return d;
}
async function main() {
const expenseCodes = await prisma.bankCodes.findMany({ where: { type: 'EXPENSE' }, select: { id: true } });
const timesheets = await prisma.timesheets.findMany({ select: { id: true } });
// ✅ typer pour éviter never[]
const created: Expenses[] = [];
for (let i = 0; i < 20; i++) {
const ts = timesheets[i % timesheets.length];
const bc = expenseCodes[i % expenseCodes.length];
const exp = await prisma.expenses.create({
data: {
timesheet_id: ts.id,
bank_code_id: bc.id,
date: daysAgo(60 + i),
amount: (20 + i * 3.5).toFixed(2), // ok: Decimal accepte string
attachement: null,
description: `Old expense #${i + 1}`,
is_approved: true,
supervisor_comment: null,
},
});
created.push(exp);
}
for (const e of created) {
await prisma.expensesArchive.create({
data: {
expense_id: e.id,
timesheet_id: e.timesheet_id,
bank_code_id: e.bank_code_id,
date: e.date,
amount: e.amount,
attachement: e.attachement,
description: e.description,
is_approved: e.is_approved,
supervisor_comment: e.supervisor_comment,
},
});
}
const total = await prisma.expensesArchive.count();
console.log(`✓ ExpensesArchive: ${total} total rows (added ${created.length})`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,40 @@
import { PrismaClient } from '@prisma/client';
import crypto from 'crypto';
const prisma = new PrismaClient();
function token() {
return crypto.randomBytes(24).toString('hex');
}
function futureHours(h:number) {
const d = new Date();
d.setHours(d.getHours() + h);
return d;
}
async function main() {
const users = await prisma.users.findMany({ select: { id: true } });
let created = 0;
for (const u of users) {
await prisma.oAuthSessions.create({
data: {
user_id: u.id,
application: 'targo-2.0',
access_token: token(),
refresh_token: token(),
sid: token(),
access_token_expiry: futureHours(2),
refresh_token_expiry: futureHours(24 * 30),
is_revoked: false,
scopes: [],
},
});
created++;
}
const total = await prisma.oAuthSessions.count();
console.log(`✓ OAuthSessions: ${total} total (added ${created})`);
}
main().finally(() => prisma.$disconnect());

View File

@ -0,0 +1,50 @@
# 1) Générer Prisma Client
npm run prisma:generate
# 2) Appliquer les migrations (crée les tables, vues, etc.)
npm run db:migrate
# 3) Lancer tous les seeds dans lordre
npm run seed:all
Complet reseed : npm run db:reseed
Run a specific seed : npm run seed:07 # leave-requests-future
Open prisma studio : npx prisma studio
Data:
users = 50
employees ≈ 40
customers ≈ 10
employees_archive = 10
customers_archive = 5
leave_requests (futur) = 10 (tous > aujourdhui)
leave_requests_archive = 10 (tous < aujourdhui)
timesheets = 8 × (#employees)
shifts = 10 × (#employees)
shifts_archive = 30 × (#employees)
bank_codes = 15
expenses = 5
expenses_archive = 20
oauth_sessions = 50