feat(cardex): implement cardex controller, service, and DTO for stock movements
feat(pos): add POS controller and service for order creation and stock retrieval refactor(pos): enhance stock and product category retrieval with pagination and mapping
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/common": "^11.0.1",
|
"@nestjs/common": "^11.0.1",
|
||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
|
"@nestjs/jwt": "^11.0.2",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
"@nestjs/swagger": "^11.2.3",
|
"@nestjs/swagger": "^11.2.3",
|
||||||
"@prisma/adapter-mariadb": "^7.1.0",
|
"@prisma/adapter-mariadb": "^7.1.0",
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
"dayjs": "^1.11.19",
|
"dayjs": "^1.11.19",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"jalaliday": "^3.1.1",
|
"jalaliday": "^3.1.1",
|
||||||
|
"jsonwebtoken": "^9.0.3",
|
||||||
"mysql2": "^3.15.3",
|
"mysql2": "^3.15.3",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1"
|
||||||
|
|||||||
Generated
+111
@@ -14,6 +14,9 @@ importers:
|
|||||||
'@nestjs/core':
|
'@nestjs/core':
|
||||||
specifier: ^11.0.1
|
specifier: ^11.0.1
|
||||||
version: 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
version: 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||||
|
'@nestjs/jwt':
|
||||||
|
specifier: ^11.0.2
|
||||||
|
version: 11.0.2(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))
|
||||||
'@nestjs/platform-express':
|
'@nestjs/platform-express':
|
||||||
specifier: ^11.0.1
|
specifier: ^11.0.1
|
||||||
version: 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)
|
version: 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)
|
||||||
@@ -41,6 +44,9 @@ importers:
|
|||||||
jalaliday:
|
jalaliday:
|
||||||
specifier: ^3.1.1
|
specifier: ^3.1.1
|
||||||
version: 3.1.1(dayjs@1.11.19)
|
version: 3.1.1(dayjs@1.11.19)
|
||||||
|
jsonwebtoken:
|
||||||
|
specifier: ^9.0.3
|
||||||
|
version: 9.0.3
|
||||||
mysql2:
|
mysql2:
|
||||||
specifier: ^3.15.3
|
specifier: ^3.15.3
|
||||||
version: 3.15.3
|
version: 3.15.3
|
||||||
@@ -915,6 +921,11 @@ packages:
|
|||||||
'@nestjs/websockets':
|
'@nestjs/websockets':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@nestjs/jwt@11.0.2':
|
||||||
|
resolution: {integrity: sha512-rK8aE/3/Ma45gAWfCksAXUNbOoSOUudU0Kn3rT39htPF7wsYXtKfjALKeKKJbFrIWbLjsbqfXX5bIJNvgBugGA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||||
|
|
||||||
'@nestjs/mapped-types@2.1.0':
|
'@nestjs/mapped-types@2.1.0':
|
||||||
resolution: {integrity: sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==}
|
resolution: {integrity: sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1144,9 +1155,15 @@ packages:
|
|||||||
'@types/json-schema@7.0.15':
|
'@types/json-schema@7.0.15':
|
||||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||||
|
|
||||||
|
'@types/jsonwebtoken@9.0.10':
|
||||||
|
resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
|
||||||
|
|
||||||
'@types/methods@1.1.4':
|
'@types/methods@1.1.4':
|
||||||
resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==}
|
resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==}
|
||||||
|
|
||||||
|
'@types/ms@2.1.0':
|
||||||
|
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||||
|
|
||||||
'@types/node@22.19.1':
|
'@types/node@22.19.1':
|
||||||
resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==}
|
resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==}
|
||||||
|
|
||||||
@@ -1575,6 +1592,9 @@ packages:
|
|||||||
bser@2.1.1:
|
bser@2.1.1:
|
||||||
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
|
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1:
|
||||||
|
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||||
|
|
||||||
buffer-from@1.1.2:
|
buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
@@ -1854,6 +1874,9 @@ packages:
|
|||||||
eastasianwidth@0.2.0:
|
eastasianwidth@0.2.0:
|
||||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||||
|
|
||||||
ee-first@1.1.1:
|
ee-first@1.1.1:
|
||||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||||
|
|
||||||
@@ -2555,6 +2578,16 @@ packages:
|
|||||||
jsonfile@6.2.0:
|
jsonfile@6.2.0:
|
||||||
resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
|
resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
|
||||||
|
|
||||||
|
jsonwebtoken@9.0.3:
|
||||||
|
resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==}
|
||||||
|
engines: {node: '>=12', npm: '>=6'}
|
||||||
|
|
||||||
|
jwa@2.0.1:
|
||||||
|
resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
|
||||||
|
|
||||||
|
jws@4.0.1:
|
||||||
|
resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
|
||||||
|
|
||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||||
|
|
||||||
@@ -2592,12 +2625,33 @@ packages:
|
|||||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
lodash.includes@4.3.0:
|
||||||
|
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
|
||||||
|
|
||||||
|
lodash.isboolean@3.0.3:
|
||||||
|
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
|
||||||
|
|
||||||
|
lodash.isinteger@4.0.4:
|
||||||
|
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
|
||||||
|
|
||||||
|
lodash.isnumber@3.0.3:
|
||||||
|
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
|
||||||
|
|
||||||
|
lodash.isplainobject@4.0.6:
|
||||||
|
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||||
|
|
||||||
|
lodash.isstring@4.0.1:
|
||||||
|
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
|
||||||
|
|
||||||
lodash.memoize@4.1.2:
|
lodash.memoize@4.1.2:
|
||||||
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
|
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
|
||||||
|
|
||||||
lodash.merge@4.6.2:
|
lodash.merge@4.6.2:
|
||||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||||
|
|
||||||
|
lodash.once@4.1.1:
|
||||||
|
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||||
|
|
||||||
lodash@4.17.21:
|
lodash@4.17.21:
|
||||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||||
|
|
||||||
@@ -4441,6 +4495,12 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@nestjs/platform-express': 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)
|
'@nestjs/platform-express': 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)
|
||||||
|
|
||||||
|
'@nestjs/jwt@11.0.2(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))':
|
||||||
|
dependencies:
|
||||||
|
'@nestjs/common': 11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||||
|
'@types/jsonwebtoken': 9.0.10
|
||||||
|
jsonwebtoken: 9.0.3
|
||||||
|
|
||||||
'@nestjs/mapped-types@2.1.0(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)':
|
'@nestjs/mapped-types@2.1.0(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nestjs/common': 11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
'@nestjs/common': 11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||||
@@ -4711,8 +4771,15 @@ snapshots:
|
|||||||
|
|
||||||
'@types/json-schema@7.0.15': {}
|
'@types/json-schema@7.0.15': {}
|
||||||
|
|
||||||
|
'@types/jsonwebtoken@9.0.10':
|
||||||
|
dependencies:
|
||||||
|
'@types/ms': 2.1.0
|
||||||
|
'@types/node': 22.19.1
|
||||||
|
|
||||||
'@types/methods@1.1.4': {}
|
'@types/methods@1.1.4': {}
|
||||||
|
|
||||||
|
'@types/ms@2.1.0': {}
|
||||||
|
|
||||||
'@types/node@22.19.1':
|
'@types/node@22.19.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.21.0
|
undici-types: 6.21.0
|
||||||
@@ -5193,6 +5260,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
node-int64: 0.4.0
|
node-int64: 0.4.0
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1: {}
|
||||||
|
|
||||||
buffer-from@1.1.2: {}
|
buffer-from@1.1.2: {}
|
||||||
|
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
@@ -5427,6 +5496,10 @@ snapshots:
|
|||||||
|
|
||||||
eastasianwidth@0.2.0: {}
|
eastasianwidth@0.2.0: {}
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
ee-first@1.1.1: {}
|
ee-first@1.1.1: {}
|
||||||
|
|
||||||
effect@3.18.4:
|
effect@3.18.4:
|
||||||
@@ -6368,6 +6441,30 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
|
|
||||||
|
jsonwebtoken@9.0.3:
|
||||||
|
dependencies:
|
||||||
|
jws: 4.0.1
|
||||||
|
lodash.includes: 4.3.0
|
||||||
|
lodash.isboolean: 3.0.3
|
||||||
|
lodash.isinteger: 4.0.4
|
||||||
|
lodash.isnumber: 3.0.3
|
||||||
|
lodash.isplainobject: 4.0.6
|
||||||
|
lodash.isstring: 4.0.1
|
||||||
|
lodash.once: 4.1.1
|
||||||
|
ms: 2.1.3
|
||||||
|
semver: 7.7.3
|
||||||
|
|
||||||
|
jwa@2.0.1:
|
||||||
|
dependencies:
|
||||||
|
buffer-equal-constant-time: 1.0.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
jws@4.0.1:
|
||||||
|
dependencies:
|
||||||
|
jwa: 2.0.1
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
json-buffer: 3.0.1
|
json-buffer: 3.0.1
|
||||||
@@ -6397,10 +6494,24 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-locate: 5.0.0
|
p-locate: 5.0.0
|
||||||
|
|
||||||
|
lodash.includes@4.3.0: {}
|
||||||
|
|
||||||
|
lodash.isboolean@3.0.3: {}
|
||||||
|
|
||||||
|
lodash.isinteger@4.0.4: {}
|
||||||
|
|
||||||
|
lodash.isnumber@3.0.3: {}
|
||||||
|
|
||||||
|
lodash.isplainobject@4.0.6: {}
|
||||||
|
|
||||||
|
lodash.isstring@4.0.1: {}
|
||||||
|
|
||||||
lodash.memoize@4.1.2: {}
|
lodash.memoize@4.1.2: {}
|
||||||
|
|
||||||
lodash.merge@4.6.2: {}
|
lodash.merge@4.6.2: {}
|
||||||
|
|
||||||
|
lodash.once@4.1.1: {}
|
||||||
|
|
||||||
lodash@4.17.21: {}
|
lodash@4.17.21: {}
|
||||||
|
|
||||||
log-symbols@4.1.0:
|
log-symbols@4.1.0:
|
||||||
|
|||||||
@@ -15,17 +15,13 @@ CREATE INDEX `Sales_Invoices_inventoryId_fkey` ON `Sales_Invoices` (`inventoryId
|
|||||||
ALTER TABLE `Sales_Invoices`
|
ALTER TABLE `Sales_Invoices`
|
||||||
ADD CONSTRAINT `Sales_Invoices_inventoryId_fkey` FOREIGN KEY (`inventoryId`) REFERENCES `Inventories` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
ADD CONSTRAINT `Sales_Invoices_inventoryId_fkey` FOREIGN KEY (`inventoryId`) REFERENCES `Inventories` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- Trigger: trg_transfer_item_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Inventory_Transfer_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_transfer_item_after_insert`;
|
DROP TRIGGER IF EXISTS `trg_transfer_item_after_insert`;
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_transfer_item_after_insert` AFTER INSERT ON `Inventory_Transfer_Items` FOR EACH ROW begin
|
CREATE TRIGGER `trg_transfer_item_after_insert` AFTER
|
||||||
|
INSERT
|
||||||
|
ON `Inventory_Transfer_Items` FOR EACH ROW begin
|
||||||
|
|
||||||
|
DECLARE fromInv INT;
|
||||||
DECLARE fromInv INT;
|
|
||||||
DECLARE toInv INT;
|
DECLARE toInv INT;
|
||||||
DECLARE _avgCost DECIMAL(10,2);
|
DECLARE _avgCost DECIMAL(10,2);
|
||||||
DECLARE latestQuantityInOrigin DECIMAL(10,2);
|
DECLARE latestQuantityInOrigin DECIMAL(10,2);
|
||||||
@@ -61,9 +57,11 @@ end;
|
|||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
DROP TRIGGER IF EXISTS `trg_purchase_receipt_item_after_insert`;
|
DROP TRIGGER IF EXISTS `trg_purchase_receipt_item_after_insert`;
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_receipt_item_after_insert` AFTER INSERT ON `Purchase_Receipt_Items` FOR EACH ROW BEGIN
|
CREATE TRIGGER `trg_purchase_receipt_item_after_insert` AFTER
|
||||||
DECLARE latestQuantity DECIMAL(10,2) DEFAULT 0;
|
INSERT
|
||||||
DECLARE invId INT;
|
ON `Purchase_Receipt_Items` FOR EACH ROW BEGIN DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
|
||||||
|
|
||||||
|
DECLARE invId INT;
|
||||||
DECLARE suppId INT;
|
DECLARE suppId INT;
|
||||||
|
|
||||||
-- Get inventory & supplier from receipt
|
-- Get inventory & supplier from receipt
|
||||||
@@ -107,11 +105,103 @@ CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_receipt_item_after_insert` AFTER
|
|||||||
CASE
|
CASE
|
||||||
WHEN NEW.count = 0 THEN 0
|
WHEN NEW.count = 0 THEN 0
|
||||||
ELSE NEW.total / NEW.count
|
ELSE NEW.total / NEW.count
|
||||||
END,
|
END
|
||||||
|
|
||||||
|
,
|
||||||
suppId,
|
suppId,
|
||||||
latestQuantity + NEW.count,
|
latestQuantity + NEW.count,
|
||||||
NOW()
|
NOW()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
END;
|
||||||
|
|
||||||
|
-- ------------------------------------------
|
||||||
|
-- Trigger: trg_sales_invoice_items_before_insert
|
||||||
|
-- Event: INSERT
|
||||||
|
-- Table: Sales_Invoice_Items
|
||||||
|
-- ------------------------------------------
|
||||||
|
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_before_insert`;
|
||||||
|
|
||||||
|
CREATE TRIGGER `trg_sales_invoice_items_before_insert` BEFORE
|
||||||
|
INSERT
|
||||||
|
ON `Sales_Invoice_Items` FOR EACH ROW begin DECLARE current_stock DECIMAL(10, 2);
|
||||||
|
|
||||||
|
DECLARE inventory_id INT;
|
||||||
|
|
||||||
|
|
||||||
|
SELECT inventoryId INTO inventory_id
|
||||||
|
FROM Sales_Invoices si
|
||||||
|
WHERE si.id = NEW.invoiceId
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
SELECT COALESCE(quantity, 0) INTO current_stock
|
||||||
|
FROM Stock_Balance sb
|
||||||
|
WHERE productId = NEW.productId AND sb.inventoryId = inventory_id
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
IF NEW.count > current_stock THEN
|
||||||
|
SIGNAL SQLSTATE '45000'
|
||||||
|
SET MESSAGE_TEXT = 'موجودی کالا در انبار کافی نیست.';
|
||||||
|
END IF;
|
||||||
|
end;
|
||||||
|
|
||||||
|
-- ------------------------------------------
|
||||||
|
-- Trigger: trg_sales_invoice_items_after_insert
|
||||||
|
-- Event: INSERT
|
||||||
|
-- Table: Sales_Invoice_Items
|
||||||
|
-- ------------------------------------------
|
||||||
|
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_after_insert`;
|
||||||
|
|
||||||
|
CREATE TRIGGER `trg_sales_invoice_items_after_insert` AFTER
|
||||||
|
INSERT
|
||||||
|
ON `Sales_Invoice_Items` FOR EACH ROW begin DECLARE current_stock DECIMAL(10, 2);
|
||||||
|
|
||||||
|
DECLARE inventory_id INT;
|
||||||
|
|
||||||
|
|
||||||
|
SELECT inventoryId INTO inventory_id
|
||||||
|
FROM Sales_Invoices si
|
||||||
|
WHERE si.id = NEW.invoiceId
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
SELECT COALESCE(quantity, 0) INTO current_stock
|
||||||
|
FROM Stock_Balance sb
|
||||||
|
WHERE productId = NEW.productId AND sb.inventoryId = inventory_id
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO Stock_Movements (
|
||||||
|
type,
|
||||||
|
quantity,
|
||||||
|
fee,
|
||||||
|
totalCost,
|
||||||
|
referenceType,
|
||||||
|
referenceId,
|
||||||
|
productId,
|
||||||
|
inventoryId,
|
||||||
|
avgCost,
|
||||||
|
remainedInStock,
|
||||||
|
createdAt
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
'OUT',
|
||||||
|
NEW.count,
|
||||||
|
NEW.fee,
|
||||||
|
NEW.total,
|
||||||
|
'SALES',
|
||||||
|
NEW.invoiceId,
|
||||||
|
NEW.productId,
|
||||||
|
inventory_id,
|
||||||
|
CASE
|
||||||
|
WHEN NEW.count = 0 THEN 0
|
||||||
|
ELSE NEW.total / NEW.count
|
||||||
|
END
|
||||||
|
|
||||||
|
, current_stock + NEW.count, NOW() );
|
||||||
|
|
||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
@@ -121,81 +211,82 @@ END;
|
|||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
DROP TRIGGER IF EXISTS `trg_stock_transfer`;
|
DROP TRIGGER IF EXISTS `trg_stock_transfer`;
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_transfer` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN
|
CREATE TRIGGER `trg_stock_transfer` AFTER
|
||||||
|
INSERT
|
||||||
IF NEW.referenceType = 'INVENTORY_TRANSFER' THEN
|
ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'INVENTORY_TRANSFER' THEN IF NEW.type = 'IN' THEN
|
||||||
|
INSERT INTO
|
||||||
IF NEW.type = 'IN' THEN
|
Stock_Balance (
|
||||||
INSERT INTO Stock_Balance (
|
|
||||||
productId,
|
productId,
|
||||||
inventoryId,
|
inventoryId,
|
||||||
quantity,
|
quantity,
|
||||||
totalCost,
|
totalCost,
|
||||||
avgCost,
|
avgCost,
|
||||||
updatedAt
|
updatedAt
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
NEW.productId,
|
NEW.productId,
|
||||||
NEW.inventoryId,
|
NEW.inventoryId,
|
||||||
NEW.quantity,
|
NEW.quantity,
|
||||||
NEW.totalCost,
|
NEW.totalCost,
|
||||||
CASE
|
CASE
|
||||||
WHEN NEW.quantity = 0 THEN 0
|
WHEN NEW.quantity = 0 THEN 0
|
||||||
ELSE NEW.totalCost / NEW.quantity
|
ELSE NEW.totalCost / NEW.quantity
|
||||||
END,
|
END,
|
||||||
NOW()
|
NOW()
|
||||||
)
|
)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
quantity = quantity + NEW.quantity,
|
quantity = quantity + NEW.quantity,
|
||||||
totalCost = totalCost + NEW.totalCost,
|
totalCost = totalCost + NEW.totalCost,
|
||||||
avgCost = CASE
|
avgCost = CASE
|
||||||
WHEN (quantity + NEW.quantity) = 0 THEN 0
|
WHEN (quantity + NEW.quantity) = 0 THEN 0
|
||||||
ELSE (totalCost + NEW.totalCost) / (quantity + NEW.quantity)
|
ELSE (totalCost + NEW.totalCost) / (quantity + NEW.quantity)
|
||||||
END,
|
END,
|
||||||
updatedAt = NOW();
|
updatedAt = NOW();
|
||||||
END IF;
|
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
IF NEW.type = 'OUT' THEN
|
IF NEW.type = 'OUT' THEN IF EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM Stock_Balance sb
|
||||||
|
WHERE
|
||||||
|
sb.productId = NEW.productId
|
||||||
|
AND sb.inventoryId = NEW.inventoryId
|
||||||
|
) THEN
|
||||||
|
|
||||||
|
UPDATE Stock_Balance sb
|
||||||
|
SET
|
||||||
|
sb.quantity = sb.quantity - NEW.quantity,
|
||||||
|
sb.totalCost = sb.totalCost - (sb.avgCost * NEW.quantity),
|
||||||
|
sb.updatedAt = NOW()
|
||||||
|
WHERE
|
||||||
|
sb.productId = NEW.productId
|
||||||
|
AND sb.inventoryId = NEW.inventoryId;
|
||||||
|
|
||||||
IF EXISTS(
|
ELSE
|
||||||
SELECT 1 FROM Stock_Balance sb
|
INSERT INTO
|
||||||
WHERE sb.productId = NEW.productId
|
Stock_Balance (
|
||||||
AND sb.inventoryId = NEW.inventoryId
|
productId,
|
||||||
) THEN
|
inventoryId,
|
||||||
|
quantity,
|
||||||
|
totalCost,
|
||||||
|
avgCost,
|
||||||
|
updatedAt
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
NEW.productId,
|
||||||
|
NEW.inventoryId,
|
||||||
|
- NEW.quantity,
|
||||||
|
- COALESCE(NEW.fee, 0) * NEW.quantity,
|
||||||
|
COALESCE(NEW.fee, 0),
|
||||||
|
NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
UPDATE Stock_Balance sb
|
END IF;
|
||||||
SET
|
|
||||||
sb.quantity = sb.quantity - NEW.quantity,
|
|
||||||
sb.totalCost = sb.totalCost - (sb.avgCost * NEW.quantity),
|
|
||||||
sb.updatedAt = NOW()
|
|
||||||
WHERE sb.productId = NEW.productId
|
|
||||||
AND sb.inventoryId = NEW.inventoryId;
|
|
||||||
|
|
||||||
ELSE
|
END IF;
|
||||||
INSERT INTO Stock_Balance (
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
quantity,
|
|
||||||
totalCost,
|
|
||||||
avgCost,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.inventoryId,
|
|
||||||
-NEW.quantity,
|
|
||||||
-COALESCE(NEW.fee, 0) * NEW.quantity,
|
|
||||||
COALESCE(NEW.fee, 0),
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
@@ -205,22 +296,69 @@ END;
|
|||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
DROP TRIGGER IF EXISTS `trg_stock_purchase_insert`;
|
DROP TRIGGER IF EXISTS `trg_stock_purchase_insert`;
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_purchase_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN
|
CREATE TRIGGER `trg_stock_purchase_insert` AFTER
|
||||||
IF NEW.referenceType = 'PURCHASE' THEN
|
INSERT
|
||||||
|
ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'PURCHASE' THEN
|
||||||
|
|
||||||
INSERT INTO Stock_Balance (productId, quantity, avgCost, totalCost, inventoryId, updatedAt)
|
INSERT INTO
|
||||||
VALUES (
|
Stock_Balance (
|
||||||
NEW.productId,
|
productId,
|
||||||
NEW.quantity,
|
quantity,
|
||||||
NEW.fee,
|
avgCost,
|
||||||
NEW.totalCost,
|
totalCost,
|
||||||
NEW.inventoryId,
|
inventoryId,
|
||||||
NOW()
|
updatedAt
|
||||||
)
|
)
|
||||||
ON DUPLICATE KEY UPDATE
|
VALUES (
|
||||||
quantity = quantity + NEW.quantity,
|
NEW.productId,
|
||||||
totalCost = totalCost + NEW.totalCost,
|
NEW.quantity,
|
||||||
avgCost = totalCost / quantity;
|
NEW.fee,
|
||||||
|
NEW.totalCost,
|
||||||
|
NEW.inventoryId,
|
||||||
|
NOW()
|
||||||
|
)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
quantity = quantity + NEW.quantity,
|
||||||
|
totalCost = totalCost + NEW.totalCost,
|
||||||
|
avgCost = totalCost / quantity;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END;
|
||||||
|
|
||||||
|
-- ------------------------------------------
|
||||||
|
-- Trigger: trg_stock_sale_insert
|
||||||
|
-- Event: INSERT
|
||||||
|
-- Table: Stock_Movements
|
||||||
|
-- ------------------------------------------
|
||||||
|
DROP TRIGGER IF EXISTS `trg_stock_sale_insert`;
|
||||||
|
|
||||||
|
CREATE TRIGGER `trg_stock_sale_insert` AFTER
|
||||||
|
INSERT
|
||||||
|
ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'SALES' THEN
|
||||||
|
|
||||||
|
INSERT INTO
|
||||||
|
Stock_Balance (
|
||||||
|
productId,
|
||||||
|
quantity,
|
||||||
|
avgCost,
|
||||||
|
totalCost,
|
||||||
|
inventoryId,
|
||||||
|
updatedAt
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
NEW.productId,
|
||||||
|
NEW.quantity,
|
||||||
|
NEW.fee,
|
||||||
|
NEW.totalCost,
|
||||||
|
NEW.inventoryId,
|
||||||
|
NOW()
|
||||||
|
)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
quantity = quantity - NEW.quantity,
|
||||||
|
totalCost = totalCost - NEW.totalCost,
|
||||||
|
avgCost = totalCost / quantity;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
END IF;
|
|
||||||
END;
|
END;
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- A unique constraint covering the columns `[name]` on the table `Roles` will be added. If there are existing duplicate values, this will fail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `Otp_Codes` (
|
||||||
|
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||||
|
`mobileNumber` VARCHAR(20) NOT NULL,
|
||||||
|
`code` VARCHAR(10) NOT NULL,
|
||||||
|
`used` BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
`expiresAt` TIMESTAMP(0) NOT NULL,
|
||||||
|
`createdAt` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
|
||||||
|
INDEX `Otp_Codes_mobileNumber_idx`(`mobileNumber`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `Refresh_Tokens` (
|
||||||
|
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||||
|
`tokenHash` VARCHAR(255) NOT NULL,
|
||||||
|
`userId` INTEGER NOT NULL,
|
||||||
|
`revoked` BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
`expiresAt` TIMESTAMP(0) NOT NULL,
|
||||||
|
`createdAt` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
|
||||||
|
INDEX `Refresh_Tokens_userId_idx`(`userId`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX `Roles_name_key` ON `Roles`(`name`);
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `Refresh_Tokens` ADD CONSTRAINT `Refresh_Tokens_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `Users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
+38
-11
@@ -10,16 +10,17 @@ datasource db {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
mobileNumber String @unique @db.Char(11)
|
mobileNumber String @unique @db.Char(11)
|
||||||
password String
|
password String
|
||||||
firstName String
|
firstName String
|
||||||
lastName String
|
lastName String
|
||||||
roleId Int
|
roleId Int
|
||||||
createdAt DateTime @default(now()) @db.Timestamp(0)
|
createdAt DateTime @default(now()) @db.Timestamp(0)
|
||||||
deletedAt DateTime? @db.Timestamp(0)
|
deletedAt DateTime? @db.Timestamp(0)
|
||||||
updatedAt DateTime @updatedAt @db.Timestamp(0)
|
updatedAt DateTime @updatedAt @db.Timestamp(0)
|
||||||
role Role @relation("User_Role", fields: [roleId], references: [id], onUpdate: NoAction)
|
role Role @relation("User_Role", fields: [roleId], references: [id], onUpdate: NoAction)
|
||||||
|
refreshTokens RefreshToken[]
|
||||||
|
|
||||||
@@index([roleId], map: "Users_roleId_fkey")
|
@@index([roleId], map: "Users_roleId_fkey")
|
||||||
@@map("Users")
|
@@map("Users")
|
||||||
@@ -27,7 +28,7 @@ model User {
|
|||||||
|
|
||||||
model Role {
|
model Role {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
name String @db.VarChar(100)
|
name String @unique() @db.VarChar(100)
|
||||||
description String? @db.Text
|
description String? @db.Text
|
||||||
permissions Json?
|
permissions Json?
|
||||||
createdAt DateTime @default(now()) @db.Timestamp(0)
|
createdAt DateTime @default(now()) @db.Timestamp(0)
|
||||||
@@ -345,6 +346,32 @@ model StockBalance {
|
|||||||
@@map("Stock_Balance")
|
@@map("Stock_Balance")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model OtpCode {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
mobileNumber String @db.VarChar(20)
|
||||||
|
code String @db.VarChar(10)
|
||||||
|
used Boolean @default(false)
|
||||||
|
expiresAt DateTime @db.Timestamp(0)
|
||||||
|
createdAt DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
|
||||||
|
@@index([mobileNumber])
|
||||||
|
@@map("Otp_Codes")
|
||||||
|
}
|
||||||
|
|
||||||
|
model RefreshToken {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
tokenHash String @db.VarChar(255)
|
||||||
|
userId Int
|
||||||
|
revoked Boolean @default(false)
|
||||||
|
expiresAt DateTime @db.Timestamp(0)
|
||||||
|
createdAt DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
|
||||||
|
user User @relation(fields: [userId], references: [id])
|
||||||
|
|
||||||
|
@@index([userId])
|
||||||
|
@@map("Refresh_Tokens")
|
||||||
|
}
|
||||||
|
|
||||||
model InventoryTransfer {
|
model InventoryTransfer {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
code String @unique @db.VarChar(100)
|
code String @unique @db.VarChar(100)
|
||||||
|
|||||||
@@ -11,6 +11,24 @@ async function main() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((await prisma.user.count()) === 0) {
|
||||||
|
const adminRole = await prisma.role.findUnique({ where: { name: 'Admin' } })
|
||||||
|
if (!adminRole) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await prisma.user.upsert({
|
||||||
|
where: { id: 1, firstName: 'عباس', lastName: 'حسنی' },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
firstName: 'عباس',
|
||||||
|
lastName: 'حسنی',
|
||||||
|
roleId: adminRole.id,
|
||||||
|
mobileNumber: '09120258156',
|
||||||
|
password: '12345678',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if ((await prisma.inventory.count()) === 0) {
|
if ((await prisma.inventory.count()) === 0) {
|
||||||
await prisma.inventory.createMany({
|
await prisma.inventory.createMany({
|
||||||
data: [
|
data: [
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
-- AUTO-GENERATED MYSQL TRIGGER DUMP
|
-- AUTO-GENERATED MYSQL TRIGGER DUMP
|
||||||
-- Generated at: 2025-12-15T15:21:49.148Z
|
-- Generated at: 2025-12-21T08:07:11.406Z
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- Trigger: trg_transfer_item_after_insert
|
-- Trigger: trg_transfer_item_after_insert
|
||||||
|
|||||||
+5
-1
@@ -1,11 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
import { AppController } from './app.controller'
|
import { AppController } from './app.controller'
|
||||||
import { AppService } from './app.service'
|
import { AppService } from './app.service'
|
||||||
|
import { AuthModule } from './auth/auth.module'
|
||||||
import { CustomersModule } from './customers/customers.module'
|
import { CustomersModule } from './customers/customers.module'
|
||||||
import { InventoriesModule } from './inventories/inventories.module'
|
import { InventoriesModule } from './inventories/inventories.module'
|
||||||
import { InventoryTransferItemsModule } from './inventory-transfer-items/inventory-transfer-items.module'
|
import { InventoryTransferItemsModule } from './inventory-transfer-items/inventory-transfer-items.module'
|
||||||
import { InventoryTransfersModule } from './inventory-transfers/inventory-transfers.module'
|
import { InventoryTransfersModule } from './inventory-transfers/inventory-transfers.module'
|
||||||
import { PosModule } from './pos/pos.module'
|
import { CardexModule } from './modules/cardex/cardex.module'
|
||||||
|
import { PosModule } from './modules/pos/pos.module'
|
||||||
import { PrismaModule } from './prisma/prisma.module'
|
import { PrismaModule } from './prisma/prisma.module'
|
||||||
import { ProductBrandsModule } from './product-brands/product-brands.module'
|
import { ProductBrandsModule } from './product-brands/product-brands.module'
|
||||||
import { ProductCategoriesModule } from './product-categories/product-categories.module'
|
import { ProductCategoriesModule } from './product-categories/product-categories.module'
|
||||||
@@ -28,6 +30,7 @@ import { UsersModule } from './users/users.module'
|
|||||||
imports: [
|
imports: [
|
||||||
PrismaModule,
|
PrismaModule,
|
||||||
UsersModule,
|
UsersModule,
|
||||||
|
AuthModule,
|
||||||
RolesModule,
|
RolesModule,
|
||||||
ProductsModule,
|
ProductsModule,
|
||||||
ProductVariantsModule,
|
ProductVariantsModule,
|
||||||
@@ -48,6 +51,7 @@ import { UsersModule } from './users/users.module'
|
|||||||
StockAdjustmentsModule,
|
StockAdjustmentsModule,
|
||||||
StockBalanceModule,
|
StockBalanceModule,
|
||||||
PosModule,
|
PosModule,
|
||||||
|
CardexModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common'
|
||||||
|
import { ApiTags } from '@nestjs/swagger'
|
||||||
|
import { ResponseMapper } from '../common/response/response-mapper'
|
||||||
|
import { AuthService } from './auth.service'
|
||||||
|
import { CurrentUser } from './current-user.decorator'
|
||||||
|
import { RefreshTokenDto } from './dto/refresh-token.dto'
|
||||||
|
import { SendCodeDto } from './dto/send-code.dto'
|
||||||
|
import { VerifyCodeDto } from './dto/verify-code.dto'
|
||||||
|
import { JwtAuthGuard } from './jwt-auth.guard'
|
||||||
|
|
||||||
|
@ApiTags('auth')
|
||||||
|
@Controller('auth')
|
||||||
|
export class AuthController {
|
||||||
|
constructor(private readonly auth: AuthService) {}
|
||||||
|
|
||||||
|
@Post('send-code')
|
||||||
|
async sendCode(@Body() dto: SendCodeDto) {
|
||||||
|
return this.auth.sendCode(dto)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('login')
|
||||||
|
async login(@Body() dto: VerifyCodeDto) {
|
||||||
|
return this.auth.loginWithCode(dto)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('refresh')
|
||||||
|
async refresh(@Body() dto: RefreshTokenDto) {
|
||||||
|
return this.auth.refreshToken(dto)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('logout')
|
||||||
|
async logout(@Body() dto: RefreshTokenDto) {
|
||||||
|
return this.auth.logout(dto.refreshToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('me')
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
|
async me(@CurrentUser() user: any) {
|
||||||
|
return ResponseMapper.single(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { JwtModule } from '@nestjs/jwt'
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { env } from 'prisma/config'
|
||||||
|
import { PrismaModule } from '../prisma/prisma.module'
|
||||||
|
import { AuthController } from './auth.controller'
|
||||||
|
import { AuthService } from './auth.service'
|
||||||
|
import { JwtAuthGuard } from './jwt-auth.guard'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
PrismaModule,
|
||||||
|
JwtModule.register({
|
||||||
|
secret: env('JWT_SECRET') || 'secret',
|
||||||
|
signOptions: { expiresIn: Number(env('JWT_EXPIRES_IN')) || '15m' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
providers: [AuthService, JwtAuthGuard],
|
||||||
|
controllers: [AuthController],
|
||||||
|
exports: [AuthService, JwtAuthGuard],
|
||||||
|
})
|
||||||
|
export class AuthModule {}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
Injectable,
|
||||||
|
NotFoundException,
|
||||||
|
UnauthorizedException,
|
||||||
|
} from '@nestjs/common'
|
||||||
|
import { JwtService } from '@nestjs/jwt'
|
||||||
|
import { createHash, randomBytes } from 'crypto'
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { env } from 'prisma/config'
|
||||||
|
import { ResponseMapper } from '../common/response/response-mapper'
|
||||||
|
import { PrismaService } from '../prisma/prisma.service'
|
||||||
|
import { RefreshTokenDto } from './dto/refresh-token.dto'
|
||||||
|
import { SendCodeDto } from './dto/send-code.dto'
|
||||||
|
import { VerifyCodeDto } from './dto/verify-code.dto'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthService {
|
||||||
|
private readonly OTP_TTL_MINUTES = 2
|
||||||
|
private readonly ACCESS_TOKEN_EXP = Number(env('JWT_EXPIRES_IN')) || '15m'
|
||||||
|
private readonly REFRESH_TOKEN_EXP_DAYS = 30
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private prisma: PrismaService,
|
||||||
|
private jwt: JwtService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private generateCode() {
|
||||||
|
// For development you may want fixed code via env, otherwise random 5-digit
|
||||||
|
const staticCode = process.env.OTP_STATIC_CODE
|
||||||
|
if (staticCode) return staticCode
|
||||||
|
return Math.floor(10000 + Math.random() * 90000).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendCode(dto: SendCodeDto) {
|
||||||
|
const { mobileNumber } = dto
|
||||||
|
const user = await this.prisma.user.findFirst({ where: { mobileNumber } })
|
||||||
|
if (!user) {
|
||||||
|
throw new NotFoundException('کاربری با این شماره تماس یافت نشد')
|
||||||
|
}
|
||||||
|
const code = this.generateCode()
|
||||||
|
const expiresAt = new Date(Date.now() + this.OTP_TTL_MINUTES * 60 * 1000)
|
||||||
|
|
||||||
|
await this.prisma.otpCode.create({
|
||||||
|
data: {
|
||||||
|
mobileNumber,
|
||||||
|
code,
|
||||||
|
expiresAt,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: integrate SMS provider. For now return the code for dev.
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async loginWithCode(dto: VerifyCodeDto) {
|
||||||
|
const { mobileNumber, code } = dto
|
||||||
|
const user = await this.prisma.user.findFirst({
|
||||||
|
where: { mobileNumber },
|
||||||
|
include: {
|
||||||
|
role: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (!user) {
|
||||||
|
throw new NotFoundException('کاربری با این شماره تماس یافت نشد')
|
||||||
|
}
|
||||||
|
|
||||||
|
const otp = await this.prisma.otpCode.findFirst({
|
||||||
|
where: { mobileNumber, used: false },
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!otp) throw new BadRequestException('اطلاعات ورودی درست نیست')
|
||||||
|
if (otp.used) throw new BadRequestException('کد قبلن استفاده شده است')
|
||||||
|
if (otp.expiresAt.getTime() < Date.now())
|
||||||
|
throw new BadRequestException('کد وارد شده منقضی شده است')
|
||||||
|
if (otp.code !== code) throw new BadRequestException('کد وارد شده اشتباه است')
|
||||||
|
|
||||||
|
// mark used
|
||||||
|
await this.prisma.otpCode.update({ where: { id: otp.id }, data: { used: true } })
|
||||||
|
|
||||||
|
const accessToken = this.jwt.sign(
|
||||||
|
{ sub: user.id, mobileNumber },
|
||||||
|
{ expiresIn: this.ACCESS_TOKEN_EXP },
|
||||||
|
)
|
||||||
|
const refreshTokenPlain = randomBytes(48).toString('hex')
|
||||||
|
const tokenHash = createHash('sha256').update(refreshTokenPlain).digest('hex')
|
||||||
|
const expiresAt = new Date(
|
||||||
|
Date.now() + this.REFRESH_TOKEN_EXP_DAYS * 24 * 60 * 60 * 1000,
|
||||||
|
)
|
||||||
|
|
||||||
|
await this.prisma.refreshToken.create({
|
||||||
|
data: { tokenHash, userId: user.id, expiresAt },
|
||||||
|
})
|
||||||
|
|
||||||
|
return ResponseMapper.single({ accessToken, refreshToken: refreshTokenPlain, user })
|
||||||
|
}
|
||||||
|
|
||||||
|
async refreshToken(dto: RefreshTokenDto) {
|
||||||
|
const { refreshToken } = dto
|
||||||
|
const tokenHash = createHash('sha256').update(refreshToken).digest('hex')
|
||||||
|
const record = await this.prisma.refreshToken.findFirst({ where: { tokenHash } })
|
||||||
|
if (!record || record.revoked || record.expiresAt.getTime() < Date.now()) {
|
||||||
|
throw new UnauthorizedException('Invalid refresh token')
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await this.prisma.user.findUnique({ where: { id: record.userId } })
|
||||||
|
if (!user) throw new UnauthorizedException('User not found')
|
||||||
|
|
||||||
|
const accessToken = this.jwt.sign(
|
||||||
|
{ sub: user.id, mobileNumber: user.mobileNumber },
|
||||||
|
{ expiresIn: this.ACCESS_TOKEN_EXP },
|
||||||
|
)
|
||||||
|
return { accessToken }
|
||||||
|
}
|
||||||
|
|
||||||
|
async logout(refreshToken: string) {
|
||||||
|
const tokenHash = createHash('sha256').update(refreshToken).digest('hex')
|
||||||
|
await this.prisma.refreshToken.updateMany({
|
||||||
|
where: { tokenHash },
|
||||||
|
data: { revoked: true },
|
||||||
|
})
|
||||||
|
return { ok: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { createParamDecorator, ExecutionContext } from '@nestjs/common'
|
||||||
|
|
||||||
|
export const CurrentUser = createParamDecorator(
|
||||||
|
(data: unknown, ctx: ExecutionContext) => {
|
||||||
|
const req = ctx.switchToHttp().getRequest()
|
||||||
|
return req.user
|
||||||
|
},
|
||||||
|
)
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger'
|
||||||
|
import { IsString } from 'class-validator'
|
||||||
|
|
||||||
|
export class LoginDto {
|
||||||
|
@ApiProperty({ description: 'Mobile number used as username', example: '09123456789' })
|
||||||
|
@IsString()
|
||||||
|
mobileNumber: string
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'OTP password (one-time password)', example: '12345' })
|
||||||
|
@IsString()
|
||||||
|
password: string
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger'
|
||||||
|
import { IsString } from 'class-validator'
|
||||||
|
|
||||||
|
export class RefreshTokenDto {
|
||||||
|
@ApiProperty()
|
||||||
|
@IsString()
|
||||||
|
refreshToken: string
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger'
|
||||||
|
import { IsString } from 'class-validator'
|
||||||
|
|
||||||
|
export class SendCodeDto {
|
||||||
|
@ApiProperty({ example: '09123456789' })
|
||||||
|
@IsString()
|
||||||
|
mobileNumber: string
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger'
|
||||||
|
import { IsString } from 'class-validator'
|
||||||
|
|
||||||
|
export class VerifyCodeDto {
|
||||||
|
@ApiProperty({ example: '09123456789' })
|
||||||
|
@IsString()
|
||||||
|
mobileNumber: string
|
||||||
|
|
||||||
|
@ApiProperty({ example: '12345' })
|
||||||
|
@IsString()
|
||||||
|
code: string
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import {
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
UnauthorizedException,
|
||||||
|
} from '@nestjs/common'
|
||||||
|
import { JwtService } from '@nestjs/jwt'
|
||||||
|
import { Request } from 'express'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class JwtAuthGuard implements CanActivate {
|
||||||
|
constructor(private jwt: JwtService) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const req = context.switchToHttp().getRequest<Request>()
|
||||||
|
const auth = req.headers.authorization
|
||||||
|
if (!auth) throw new UnauthorizedException('Missing Authorization header')
|
||||||
|
|
||||||
|
const parts = auth.split(' ')
|
||||||
|
if (parts.length !== 2 || parts[0] !== 'Bearer') {
|
||||||
|
throw new UnauthorizedException('Invalid Authorization header format')
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = parts[1]
|
||||||
|
try {
|
||||||
|
const payload = this.jwt.verify(token, {
|
||||||
|
secret: process.env.JWT_SECRET || 'secret',
|
||||||
|
})
|
||||||
|
;(req as any).user = payload
|
||||||
|
return true
|
||||||
|
} catch (err) {
|
||||||
|
throw new UnauthorizedException('Invalid or expired token')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -107,6 +107,16 @@ export type StockMovement = Prisma.StockMovementModel
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export type StockBalance = Prisma.StockBalanceModel
|
export type StockBalance = Prisma.StockBalanceModel
|
||||||
|
/**
|
||||||
|
* Model OtpCode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export type OtpCode = Prisma.OtpCodeModel
|
||||||
|
/**
|
||||||
|
* Model RefreshToken
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export type RefreshToken = Prisma.RefreshTokenModel
|
||||||
/**
|
/**
|
||||||
* Model InventoryTransfer
|
* Model InventoryTransfer
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -127,6 +127,16 @@ export type StockMovement = Prisma.StockMovementModel
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export type StockBalance = Prisma.StockBalanceModel
|
export type StockBalance = Prisma.StockBalanceModel
|
||||||
|
/**
|
||||||
|
* Model OtpCode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export type OtpCode = Prisma.OtpCodeModel
|
||||||
|
/**
|
||||||
|
* Model RefreshToken
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export type RefreshToken = Prisma.RefreshTokenModel
|
||||||
/**
|
/**
|
||||||
* Model InventoryTransfer
|
* Model InventoryTransfer
|
||||||
*
|
*
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -402,6 +402,8 @@ export const ModelName = {
|
|||||||
SalesInvoiceItem: 'SalesInvoiceItem',
|
SalesInvoiceItem: 'SalesInvoiceItem',
|
||||||
StockMovement: 'StockMovement',
|
StockMovement: 'StockMovement',
|
||||||
StockBalance: 'StockBalance',
|
StockBalance: 'StockBalance',
|
||||||
|
OtpCode: 'OtpCode',
|
||||||
|
RefreshToken: 'RefreshToken',
|
||||||
InventoryTransfer: 'InventoryTransfer',
|
InventoryTransfer: 'InventoryTransfer',
|
||||||
InventoryTransferItem: 'InventoryTransferItem',
|
InventoryTransferItem: 'InventoryTransferItem',
|
||||||
StockAdjustment: 'StockAdjustment',
|
StockAdjustment: 'StockAdjustment',
|
||||||
@@ -424,7 +426,7 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
|
|||||||
omit: GlobalOmitOptions
|
omit: GlobalOmitOptions
|
||||||
}
|
}
|
||||||
meta: {
|
meta: {
|
||||||
modelProps: "user" | "role" | "productVariant" | "product" | "productBrand" | "productCategory" | "supplier" | "customer" | "inventory" | "store" | "productCharge" | "order" | "purchaseReceipt" | "purchaseReceiptItem" | "salesInvoice" | "salesInvoiceItem" | "stockMovement" | "stockBalance" | "inventoryTransfer" | "inventoryTransferItem" | "stockAdjustment" | "triggerLog" | "inventory_overview" | "stock_cardex" | "stock_view"
|
modelProps: "user" | "role" | "productVariant" | "product" | "productBrand" | "productCategory" | "supplier" | "customer" | "inventory" | "store" | "productCharge" | "order" | "purchaseReceipt" | "purchaseReceiptItem" | "salesInvoice" | "salesInvoiceItem" | "stockMovement" | "stockBalance" | "otpCode" | "refreshToken" | "inventoryTransfer" | "inventoryTransferItem" | "stockAdjustment" | "triggerLog" | "inventory_overview" | "stock_cardex" | "stock_view"
|
||||||
txIsolationLevel: TransactionIsolationLevel
|
txIsolationLevel: TransactionIsolationLevel
|
||||||
}
|
}
|
||||||
model: {
|
model: {
|
||||||
@@ -1616,6 +1618,138 @@ export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
OtpCode: {
|
||||||
|
payload: Prisma.$OtpCodePayload<ExtArgs>
|
||||||
|
fields: Prisma.OtpCodeFieldRefs
|
||||||
|
operations: {
|
||||||
|
findUnique: {
|
||||||
|
args: Prisma.OtpCodeFindUniqueArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload> | null
|
||||||
|
}
|
||||||
|
findUniqueOrThrow: {
|
||||||
|
args: Prisma.OtpCodeFindUniqueOrThrowArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload>
|
||||||
|
}
|
||||||
|
findFirst: {
|
||||||
|
args: Prisma.OtpCodeFindFirstArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload> | null
|
||||||
|
}
|
||||||
|
findFirstOrThrow: {
|
||||||
|
args: Prisma.OtpCodeFindFirstOrThrowArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload>
|
||||||
|
}
|
||||||
|
findMany: {
|
||||||
|
args: Prisma.OtpCodeFindManyArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload>[]
|
||||||
|
}
|
||||||
|
create: {
|
||||||
|
args: Prisma.OtpCodeCreateArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload>
|
||||||
|
}
|
||||||
|
createMany: {
|
||||||
|
args: Prisma.OtpCodeCreateManyArgs<ExtArgs>
|
||||||
|
result: BatchPayload
|
||||||
|
}
|
||||||
|
delete: {
|
||||||
|
args: Prisma.OtpCodeDeleteArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload>
|
||||||
|
}
|
||||||
|
update: {
|
||||||
|
args: Prisma.OtpCodeUpdateArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload>
|
||||||
|
}
|
||||||
|
deleteMany: {
|
||||||
|
args: Prisma.OtpCodeDeleteManyArgs<ExtArgs>
|
||||||
|
result: BatchPayload
|
||||||
|
}
|
||||||
|
updateMany: {
|
||||||
|
args: Prisma.OtpCodeUpdateManyArgs<ExtArgs>
|
||||||
|
result: BatchPayload
|
||||||
|
}
|
||||||
|
upsert: {
|
||||||
|
args: Prisma.OtpCodeUpsertArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$OtpCodePayload>
|
||||||
|
}
|
||||||
|
aggregate: {
|
||||||
|
args: Prisma.OtpCodeAggregateArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.Optional<Prisma.AggregateOtpCode>
|
||||||
|
}
|
||||||
|
groupBy: {
|
||||||
|
args: Prisma.OtpCodeGroupByArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.Optional<Prisma.OtpCodeGroupByOutputType>[]
|
||||||
|
}
|
||||||
|
count: {
|
||||||
|
args: Prisma.OtpCodeCountArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.Optional<Prisma.OtpCodeCountAggregateOutputType> | number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RefreshToken: {
|
||||||
|
payload: Prisma.$RefreshTokenPayload<ExtArgs>
|
||||||
|
fields: Prisma.RefreshTokenFieldRefs
|
||||||
|
operations: {
|
||||||
|
findUnique: {
|
||||||
|
args: Prisma.RefreshTokenFindUniqueArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload> | null
|
||||||
|
}
|
||||||
|
findUniqueOrThrow: {
|
||||||
|
args: Prisma.RefreshTokenFindUniqueOrThrowArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload>
|
||||||
|
}
|
||||||
|
findFirst: {
|
||||||
|
args: Prisma.RefreshTokenFindFirstArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload> | null
|
||||||
|
}
|
||||||
|
findFirstOrThrow: {
|
||||||
|
args: Prisma.RefreshTokenFindFirstOrThrowArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload>
|
||||||
|
}
|
||||||
|
findMany: {
|
||||||
|
args: Prisma.RefreshTokenFindManyArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload>[]
|
||||||
|
}
|
||||||
|
create: {
|
||||||
|
args: Prisma.RefreshTokenCreateArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload>
|
||||||
|
}
|
||||||
|
createMany: {
|
||||||
|
args: Prisma.RefreshTokenCreateManyArgs<ExtArgs>
|
||||||
|
result: BatchPayload
|
||||||
|
}
|
||||||
|
delete: {
|
||||||
|
args: Prisma.RefreshTokenDeleteArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload>
|
||||||
|
}
|
||||||
|
update: {
|
||||||
|
args: Prisma.RefreshTokenUpdateArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload>
|
||||||
|
}
|
||||||
|
deleteMany: {
|
||||||
|
args: Prisma.RefreshTokenDeleteManyArgs<ExtArgs>
|
||||||
|
result: BatchPayload
|
||||||
|
}
|
||||||
|
updateMany: {
|
||||||
|
args: Prisma.RefreshTokenUpdateManyArgs<ExtArgs>
|
||||||
|
result: BatchPayload
|
||||||
|
}
|
||||||
|
upsert: {
|
||||||
|
args: Prisma.RefreshTokenUpsertArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.PayloadToResult<Prisma.$RefreshTokenPayload>
|
||||||
|
}
|
||||||
|
aggregate: {
|
||||||
|
args: Prisma.RefreshTokenAggregateArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.Optional<Prisma.AggregateRefreshToken>
|
||||||
|
}
|
||||||
|
groupBy: {
|
||||||
|
args: Prisma.RefreshTokenGroupByArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.Optional<Prisma.RefreshTokenGroupByOutputType>[]
|
||||||
|
}
|
||||||
|
count: {
|
||||||
|
args: Prisma.RefreshTokenCountArgs<ExtArgs>
|
||||||
|
result: runtime.Types.Utils.Optional<Prisma.RefreshTokenCountAggregateOutputType> | number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
InventoryTransfer: {
|
InventoryTransfer: {
|
||||||
payload: Prisma.$InventoryTransferPayload<ExtArgs>
|
payload: Prisma.$InventoryTransferPayload<ExtArgs>
|
||||||
fields: Prisma.InventoryTransferFieldRefs
|
fields: Prisma.InventoryTransferFieldRefs
|
||||||
@@ -2289,6 +2423,30 @@ export const StockBalanceScalarFieldEnum = {
|
|||||||
export type StockBalanceScalarFieldEnum = (typeof StockBalanceScalarFieldEnum)[keyof typeof StockBalanceScalarFieldEnum]
|
export type StockBalanceScalarFieldEnum = (typeof StockBalanceScalarFieldEnum)[keyof typeof StockBalanceScalarFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
|
export const OtpCodeScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
mobileNumber: 'mobileNumber',
|
||||||
|
code: 'code',
|
||||||
|
used: 'used',
|
||||||
|
expiresAt: 'expiresAt',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type OtpCodeScalarFieldEnum = (typeof OtpCodeScalarFieldEnum)[keyof typeof OtpCodeScalarFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
|
export const RefreshTokenScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
tokenHash: 'tokenHash',
|
||||||
|
userId: 'userId',
|
||||||
|
revoked: 'revoked',
|
||||||
|
expiresAt: 'expiresAt',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type RefreshTokenScalarFieldEnum = (typeof RefreshTokenScalarFieldEnum)[keyof typeof RefreshTokenScalarFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
export const InventoryTransferScalarFieldEnum = {
|
export const InventoryTransferScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
code: 'code',
|
code: 'code',
|
||||||
@@ -2553,6 +2711,21 @@ export const StockMovementOrderByRelevanceFieldEnum = {
|
|||||||
export type StockMovementOrderByRelevanceFieldEnum = (typeof StockMovementOrderByRelevanceFieldEnum)[keyof typeof StockMovementOrderByRelevanceFieldEnum]
|
export type StockMovementOrderByRelevanceFieldEnum = (typeof StockMovementOrderByRelevanceFieldEnum)[keyof typeof StockMovementOrderByRelevanceFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
|
export const OtpCodeOrderByRelevanceFieldEnum = {
|
||||||
|
mobileNumber: 'mobileNumber',
|
||||||
|
code: 'code'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type OtpCodeOrderByRelevanceFieldEnum = (typeof OtpCodeOrderByRelevanceFieldEnum)[keyof typeof OtpCodeOrderByRelevanceFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
|
export const RefreshTokenOrderByRelevanceFieldEnum = {
|
||||||
|
tokenHash: 'tokenHash'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type RefreshTokenOrderByRelevanceFieldEnum = (typeof RefreshTokenOrderByRelevanceFieldEnum)[keyof typeof RefreshTokenOrderByRelevanceFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
export const InventoryTransferOrderByRelevanceFieldEnum = {
|
export const InventoryTransferOrderByRelevanceFieldEnum = {
|
||||||
code: 'code',
|
code: 'code',
|
||||||
description: 'description'
|
description: 'description'
|
||||||
@@ -2778,6 +2951,8 @@ export type GlobalOmitConfig = {
|
|||||||
salesInvoiceItem?: Prisma.SalesInvoiceItemOmit
|
salesInvoiceItem?: Prisma.SalesInvoiceItemOmit
|
||||||
stockMovement?: Prisma.StockMovementOmit
|
stockMovement?: Prisma.StockMovementOmit
|
||||||
stockBalance?: Prisma.StockBalanceOmit
|
stockBalance?: Prisma.StockBalanceOmit
|
||||||
|
otpCode?: Prisma.OtpCodeOmit
|
||||||
|
refreshToken?: Prisma.RefreshTokenOmit
|
||||||
inventoryTransfer?: Prisma.InventoryTransferOmit
|
inventoryTransfer?: Prisma.InventoryTransferOmit
|
||||||
inventoryTransferItem?: Prisma.InventoryTransferItemOmit
|
inventoryTransferItem?: Prisma.InventoryTransferItemOmit
|
||||||
stockAdjustment?: Prisma.StockAdjustmentOmit
|
stockAdjustment?: Prisma.StockAdjustmentOmit
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ export const ModelName = {
|
|||||||
SalesInvoiceItem: 'SalesInvoiceItem',
|
SalesInvoiceItem: 'SalesInvoiceItem',
|
||||||
StockMovement: 'StockMovement',
|
StockMovement: 'StockMovement',
|
||||||
StockBalance: 'StockBalance',
|
StockBalance: 'StockBalance',
|
||||||
|
OtpCode: 'OtpCode',
|
||||||
|
RefreshToken: 'RefreshToken',
|
||||||
InventoryTransfer: 'InventoryTransfer',
|
InventoryTransfer: 'InventoryTransfer',
|
||||||
InventoryTransferItem: 'InventoryTransferItem',
|
InventoryTransferItem: 'InventoryTransferItem',
|
||||||
StockAdjustment: 'StockAdjustment',
|
StockAdjustment: 'StockAdjustment',
|
||||||
@@ -374,6 +376,30 @@ export const StockBalanceScalarFieldEnum = {
|
|||||||
export type StockBalanceScalarFieldEnum = (typeof StockBalanceScalarFieldEnum)[keyof typeof StockBalanceScalarFieldEnum]
|
export type StockBalanceScalarFieldEnum = (typeof StockBalanceScalarFieldEnum)[keyof typeof StockBalanceScalarFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
|
export const OtpCodeScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
mobileNumber: 'mobileNumber',
|
||||||
|
code: 'code',
|
||||||
|
used: 'used',
|
||||||
|
expiresAt: 'expiresAt',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type OtpCodeScalarFieldEnum = (typeof OtpCodeScalarFieldEnum)[keyof typeof OtpCodeScalarFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
|
export const RefreshTokenScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
tokenHash: 'tokenHash',
|
||||||
|
userId: 'userId',
|
||||||
|
revoked: 'revoked',
|
||||||
|
expiresAt: 'expiresAt',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type RefreshTokenScalarFieldEnum = (typeof RefreshTokenScalarFieldEnum)[keyof typeof RefreshTokenScalarFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
export const InventoryTransferScalarFieldEnum = {
|
export const InventoryTransferScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
code: 'code',
|
code: 'code',
|
||||||
@@ -638,6 +664,21 @@ export const StockMovementOrderByRelevanceFieldEnum = {
|
|||||||
export type StockMovementOrderByRelevanceFieldEnum = (typeof StockMovementOrderByRelevanceFieldEnum)[keyof typeof StockMovementOrderByRelevanceFieldEnum]
|
export type StockMovementOrderByRelevanceFieldEnum = (typeof StockMovementOrderByRelevanceFieldEnum)[keyof typeof StockMovementOrderByRelevanceFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
|
export const OtpCodeOrderByRelevanceFieldEnum = {
|
||||||
|
mobileNumber: 'mobileNumber',
|
||||||
|
code: 'code'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type OtpCodeOrderByRelevanceFieldEnum = (typeof OtpCodeOrderByRelevanceFieldEnum)[keyof typeof OtpCodeOrderByRelevanceFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
|
export const RefreshTokenOrderByRelevanceFieldEnum = {
|
||||||
|
tokenHash: 'tokenHash'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type RefreshTokenOrderByRelevanceFieldEnum = (typeof RefreshTokenOrderByRelevanceFieldEnum)[keyof typeof RefreshTokenOrderByRelevanceFieldEnum]
|
||||||
|
|
||||||
|
|
||||||
export const InventoryTransferOrderByRelevanceFieldEnum = {
|
export const InventoryTransferOrderByRelevanceFieldEnum = {
|
||||||
code: 'code',
|
code: 'code',
|
||||||
description: 'description'
|
description: 'description'
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ export type * from './models/SalesInvoice.js'
|
|||||||
export type * from './models/SalesInvoiceItem.js'
|
export type * from './models/SalesInvoiceItem.js'
|
||||||
export type * from './models/StockMovement.js'
|
export type * from './models/StockMovement.js'
|
||||||
export type * from './models/StockBalance.js'
|
export type * from './models/StockBalance.js'
|
||||||
|
export type * from './models/OtpCode.js'
|
||||||
|
export type * from './models/RefreshToken.js'
|
||||||
export type * from './models/InventoryTransfer.js'
|
export type * from './models/InventoryTransfer.js'
|
||||||
export type * from './models/InventoryTransferItem.js'
|
export type * from './models/InventoryTransferItem.js'
|
||||||
export type * from './models/StockAdjustment.js'
|
export type * from './models/StockAdjustment.js'
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -245,17 +245,17 @@ export type RoleOrderByWithRelationInput = {
|
|||||||
|
|
||||||
export type RoleWhereUniqueInput = Prisma.AtLeast<{
|
export type RoleWhereUniqueInput = Prisma.AtLeast<{
|
||||||
id?: number
|
id?: number
|
||||||
|
name?: string
|
||||||
AND?: Prisma.RoleWhereInput | Prisma.RoleWhereInput[]
|
AND?: Prisma.RoleWhereInput | Prisma.RoleWhereInput[]
|
||||||
OR?: Prisma.RoleWhereInput[]
|
OR?: Prisma.RoleWhereInput[]
|
||||||
NOT?: Prisma.RoleWhereInput | Prisma.RoleWhereInput[]
|
NOT?: Prisma.RoleWhereInput | Prisma.RoleWhereInput[]
|
||||||
name?: Prisma.StringFilter<"Role"> | string
|
|
||||||
description?: Prisma.StringNullableFilter<"Role"> | string | null
|
description?: Prisma.StringNullableFilter<"Role"> | string | null
|
||||||
permissions?: Prisma.JsonNullableFilter<"Role">
|
permissions?: Prisma.JsonNullableFilter<"Role">
|
||||||
createdAt?: Prisma.DateTimeFilter<"Role"> | Date | string
|
createdAt?: Prisma.DateTimeFilter<"Role"> | Date | string
|
||||||
updatedAt?: Prisma.DateTimeFilter<"Role"> | Date | string
|
updatedAt?: Prisma.DateTimeFilter<"Role"> | Date | string
|
||||||
deletedAt?: Prisma.DateTimeNullableFilter<"Role"> | Date | string | null
|
deletedAt?: Prisma.DateTimeNullableFilter<"Role"> | Date | string | null
|
||||||
users?: Prisma.UserListRelationFilter
|
users?: Prisma.UserListRelationFilter
|
||||||
}, "id">
|
}, "id" | "name">
|
||||||
|
|
||||||
export type RoleOrderByWithAggregationInput = {
|
export type RoleOrderByWithAggregationInput = {
|
||||||
id?: Prisma.SortOrder
|
id?: Prisma.SortOrder
|
||||||
|
|||||||
@@ -253,6 +253,7 @@ export type UserWhereInput = {
|
|||||||
deletedAt?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null
|
deletedAt?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null
|
||||||
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
|
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
|
||||||
role?: Prisma.XOR<Prisma.RoleScalarRelationFilter, Prisma.RoleWhereInput>
|
role?: Prisma.XOR<Prisma.RoleScalarRelationFilter, Prisma.RoleWhereInput>
|
||||||
|
refreshTokens?: Prisma.RefreshTokenListRelationFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserOrderByWithRelationInput = {
|
export type UserOrderByWithRelationInput = {
|
||||||
@@ -266,6 +267,7 @@ export type UserOrderByWithRelationInput = {
|
|||||||
deletedAt?: Prisma.SortOrderInput | Prisma.SortOrder
|
deletedAt?: Prisma.SortOrderInput | Prisma.SortOrder
|
||||||
updatedAt?: Prisma.SortOrder
|
updatedAt?: Prisma.SortOrder
|
||||||
role?: Prisma.RoleOrderByWithRelationInput
|
role?: Prisma.RoleOrderByWithRelationInput
|
||||||
|
refreshTokens?: Prisma.RefreshTokenOrderByRelationAggregateInput
|
||||||
_relevance?: Prisma.UserOrderByRelevanceInput
|
_relevance?: Prisma.UserOrderByRelevanceInput
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +285,7 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{
|
|||||||
deletedAt?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null
|
deletedAt?: Prisma.DateTimeNullableFilter<"User"> | Date | string | null
|
||||||
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
|
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
|
||||||
role?: Prisma.XOR<Prisma.RoleScalarRelationFilter, Prisma.RoleWhereInput>
|
role?: Prisma.XOR<Prisma.RoleScalarRelationFilter, Prisma.RoleWhereInput>
|
||||||
|
refreshTokens?: Prisma.RefreshTokenListRelationFilter
|
||||||
}, "id" | "mobileNumber">
|
}, "id" | "mobileNumber">
|
||||||
|
|
||||||
export type UserOrderByWithAggregationInput = {
|
export type UserOrderByWithAggregationInput = {
|
||||||
@@ -326,6 +329,7 @@ export type UserCreateInput = {
|
|||||||
deletedAt?: Date | string | null
|
deletedAt?: Date | string | null
|
||||||
updatedAt?: Date | string
|
updatedAt?: Date | string
|
||||||
role: Prisma.RoleCreateNestedOneWithoutUsersInput
|
role: Prisma.RoleCreateNestedOneWithoutUsersInput
|
||||||
|
refreshTokens?: Prisma.RefreshTokenCreateNestedManyWithoutUserInput
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserUncheckedCreateInput = {
|
export type UserUncheckedCreateInput = {
|
||||||
@@ -338,6 +342,7 @@ export type UserUncheckedCreateInput = {
|
|||||||
createdAt?: Date | string
|
createdAt?: Date | string
|
||||||
deletedAt?: Date | string | null
|
deletedAt?: Date | string | null
|
||||||
updatedAt?: Date | string
|
updatedAt?: Date | string
|
||||||
|
refreshTokens?: Prisma.RefreshTokenUncheckedCreateNestedManyWithoutUserInput
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserUpdateInput = {
|
export type UserUpdateInput = {
|
||||||
@@ -349,6 +354,7 @@ export type UserUpdateInput = {
|
|||||||
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
||||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
role?: Prisma.RoleUpdateOneRequiredWithoutUsersNestedInput
|
role?: Prisma.RoleUpdateOneRequiredWithoutUsersNestedInput
|
||||||
|
refreshTokens?: Prisma.RefreshTokenUpdateManyWithoutUserNestedInput
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserUncheckedUpdateInput = {
|
export type UserUncheckedUpdateInput = {
|
||||||
@@ -361,6 +367,7 @@ export type UserUncheckedUpdateInput = {
|
|||||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
||||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
|
refreshTokens?: Prisma.RefreshTokenUncheckedUpdateManyWithoutUserNestedInput
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserCreateManyInput = {
|
export type UserCreateManyInput = {
|
||||||
@@ -459,6 +466,11 @@ export type UserOrderByRelationAggregateInput = {
|
|||||||
_count?: Prisma.SortOrder
|
_count?: Prisma.SortOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UserScalarRelationFilter = {
|
||||||
|
is?: Prisma.UserWhereInput
|
||||||
|
isNot?: Prisma.UserWhereInput
|
||||||
|
}
|
||||||
|
|
||||||
export type StringFieldUpdateOperationsInput = {
|
export type StringFieldUpdateOperationsInput = {
|
||||||
set?: string
|
set?: string
|
||||||
}
|
}
|
||||||
@@ -521,6 +533,20 @@ export type UserUncheckedUpdateManyWithoutRoleNestedInput = {
|
|||||||
deleteMany?: Prisma.UserScalarWhereInput | Prisma.UserScalarWhereInput[]
|
deleteMany?: Prisma.UserScalarWhereInput | Prisma.UserScalarWhereInput[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UserCreateNestedOneWithoutRefreshTokensInput = {
|
||||||
|
create?: Prisma.XOR<Prisma.UserCreateWithoutRefreshTokensInput, Prisma.UserUncheckedCreateWithoutRefreshTokensInput>
|
||||||
|
connectOrCreate?: Prisma.UserCreateOrConnectWithoutRefreshTokensInput
|
||||||
|
connect?: Prisma.UserWhereUniqueInput
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserUpdateOneRequiredWithoutRefreshTokensNestedInput = {
|
||||||
|
create?: Prisma.XOR<Prisma.UserCreateWithoutRefreshTokensInput, Prisma.UserUncheckedCreateWithoutRefreshTokensInput>
|
||||||
|
connectOrCreate?: Prisma.UserCreateOrConnectWithoutRefreshTokensInput
|
||||||
|
upsert?: Prisma.UserUpsertWithoutRefreshTokensInput
|
||||||
|
connect?: Prisma.UserWhereUniqueInput
|
||||||
|
update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutRefreshTokensInput, Prisma.UserUpdateWithoutRefreshTokensInput>, Prisma.UserUncheckedUpdateWithoutRefreshTokensInput>
|
||||||
|
}
|
||||||
|
|
||||||
export type UserCreateWithoutRoleInput = {
|
export type UserCreateWithoutRoleInput = {
|
||||||
mobileNumber: string
|
mobileNumber: string
|
||||||
password: string
|
password: string
|
||||||
@@ -529,6 +555,7 @@ export type UserCreateWithoutRoleInput = {
|
|||||||
createdAt?: Date | string
|
createdAt?: Date | string
|
||||||
deletedAt?: Date | string | null
|
deletedAt?: Date | string | null
|
||||||
updatedAt?: Date | string
|
updatedAt?: Date | string
|
||||||
|
refreshTokens?: Prisma.RefreshTokenCreateNestedManyWithoutUserInput
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserUncheckedCreateWithoutRoleInput = {
|
export type UserUncheckedCreateWithoutRoleInput = {
|
||||||
@@ -540,6 +567,7 @@ export type UserUncheckedCreateWithoutRoleInput = {
|
|||||||
createdAt?: Date | string
|
createdAt?: Date | string
|
||||||
deletedAt?: Date | string | null
|
deletedAt?: Date | string | null
|
||||||
updatedAt?: Date | string
|
updatedAt?: Date | string
|
||||||
|
refreshTokens?: Prisma.RefreshTokenUncheckedCreateNestedManyWithoutUserInput
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserCreateOrConnectWithoutRoleInput = {
|
export type UserCreateOrConnectWithoutRoleInput = {
|
||||||
@@ -583,6 +611,68 @@ export type UserScalarWhereInput = {
|
|||||||
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
|
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UserCreateWithoutRefreshTokensInput = {
|
||||||
|
mobileNumber: string
|
||||||
|
password: string
|
||||||
|
firstName: string
|
||||||
|
lastName: string
|
||||||
|
createdAt?: Date | string
|
||||||
|
deletedAt?: Date | string | null
|
||||||
|
updatedAt?: Date | string
|
||||||
|
role: Prisma.RoleCreateNestedOneWithoutUsersInput
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserUncheckedCreateWithoutRefreshTokensInput = {
|
||||||
|
id?: number
|
||||||
|
mobileNumber: string
|
||||||
|
password: string
|
||||||
|
firstName: string
|
||||||
|
lastName: string
|
||||||
|
roleId: number
|
||||||
|
createdAt?: Date | string
|
||||||
|
deletedAt?: Date | string | null
|
||||||
|
updatedAt?: Date | string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserCreateOrConnectWithoutRefreshTokensInput = {
|
||||||
|
where: Prisma.UserWhereUniqueInput
|
||||||
|
create: Prisma.XOR<Prisma.UserCreateWithoutRefreshTokensInput, Prisma.UserUncheckedCreateWithoutRefreshTokensInput>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserUpsertWithoutRefreshTokensInput = {
|
||||||
|
update: Prisma.XOR<Prisma.UserUpdateWithoutRefreshTokensInput, Prisma.UserUncheckedUpdateWithoutRefreshTokensInput>
|
||||||
|
create: Prisma.XOR<Prisma.UserCreateWithoutRefreshTokensInput, Prisma.UserUncheckedCreateWithoutRefreshTokensInput>
|
||||||
|
where?: Prisma.UserWhereInput
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserUpdateToOneWithWhereWithoutRefreshTokensInput = {
|
||||||
|
where?: Prisma.UserWhereInput
|
||||||
|
data: Prisma.XOR<Prisma.UserUpdateWithoutRefreshTokensInput, Prisma.UserUncheckedUpdateWithoutRefreshTokensInput>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserUpdateWithoutRefreshTokensInput = {
|
||||||
|
mobileNumber?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
|
password?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
|
firstName?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
|
lastName?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
|
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
|
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
||||||
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
|
role?: Prisma.RoleUpdateOneRequiredWithoutUsersNestedInput
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserUncheckedUpdateWithoutRefreshTokensInput = {
|
||||||
|
id?: Prisma.IntFieldUpdateOperationsInput | number
|
||||||
|
mobileNumber?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
|
password?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
|
firstName?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
|
lastName?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
|
roleId?: Prisma.IntFieldUpdateOperationsInput | number
|
||||||
|
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
|
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
||||||
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
|
}
|
||||||
|
|
||||||
export type UserCreateManyRoleInput = {
|
export type UserCreateManyRoleInput = {
|
||||||
id?: number
|
id?: number
|
||||||
mobileNumber: string
|
mobileNumber: string
|
||||||
@@ -602,6 +692,7 @@ export type UserUpdateWithoutRoleInput = {
|
|||||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
||||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
|
refreshTokens?: Prisma.RefreshTokenUpdateManyWithoutUserNestedInput
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserUncheckedUpdateWithoutRoleInput = {
|
export type UserUncheckedUpdateWithoutRoleInput = {
|
||||||
@@ -613,6 +704,7 @@ export type UserUncheckedUpdateWithoutRoleInput = {
|
|||||||
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
|
||||||
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
|
||||||
|
refreshTokens?: Prisma.RefreshTokenUncheckedUpdateManyWithoutUserNestedInput
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserUncheckedUpdateManyWithoutRoleInput = {
|
export type UserUncheckedUpdateManyWithoutRoleInput = {
|
||||||
@@ -627,6 +719,35 @@ export type UserUncheckedUpdateManyWithoutRoleInput = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count Type UserCountOutputType
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type UserCountOutputType = {
|
||||||
|
refreshTokens: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||||
|
refreshTokens?: boolean | UserCountOutputTypeCountRefreshTokensArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UserCountOutputType without action
|
||||||
|
*/
|
||||||
|
export type UserCountOutputTypeDefaultArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||||
|
/**
|
||||||
|
* Select specific fields to fetch from the UserCountOutputType
|
||||||
|
*/
|
||||||
|
select?: Prisma.UserCountOutputTypeSelect<ExtArgs> | null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UserCountOutputType without action
|
||||||
|
*/
|
||||||
|
export type UserCountOutputTypeCountRefreshTokensArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||||
|
where?: Prisma.RefreshTokenWhereInput
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
||||||
id?: boolean
|
id?: boolean
|
||||||
@@ -639,6 +760,8 @@ export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = r
|
|||||||
deletedAt?: boolean
|
deletedAt?: boolean
|
||||||
updatedAt?: boolean
|
updatedAt?: boolean
|
||||||
role?: boolean | Prisma.RoleDefaultArgs<ExtArgs>
|
role?: boolean | Prisma.RoleDefaultArgs<ExtArgs>
|
||||||
|
refreshTokens?: boolean | Prisma.User$refreshTokensArgs<ExtArgs>
|
||||||
|
_count?: boolean | Prisma.UserCountOutputTypeDefaultArgs<ExtArgs>
|
||||||
}, ExtArgs["result"]["user"]>
|
}, ExtArgs["result"]["user"]>
|
||||||
|
|
||||||
|
|
||||||
@@ -658,12 +781,15 @@ export type UserSelectScalar = {
|
|||||||
export type UserOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "mobileNumber" | "password" | "firstName" | "lastName" | "roleId" | "createdAt" | "deletedAt" | "updatedAt", ExtArgs["result"]["user"]>
|
export type UserOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "mobileNumber" | "password" | "firstName" | "lastName" | "roleId" | "createdAt" | "deletedAt" | "updatedAt", ExtArgs["result"]["user"]>
|
||||||
export type UserInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
export type UserInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||||
role?: boolean | Prisma.RoleDefaultArgs<ExtArgs>
|
role?: boolean | Prisma.RoleDefaultArgs<ExtArgs>
|
||||||
|
refreshTokens?: boolean | Prisma.User$refreshTokensArgs<ExtArgs>
|
||||||
|
_count?: boolean | Prisma.UserCountOutputTypeDefaultArgs<ExtArgs>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type $UserPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
export type $UserPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||||
name: "User"
|
name: "User"
|
||||||
objects: {
|
objects: {
|
||||||
role: Prisma.$RolePayload<ExtArgs>
|
role: Prisma.$RolePayload<ExtArgs>
|
||||||
|
refreshTokens: Prisma.$RefreshTokenPayload<ExtArgs>[]
|
||||||
}
|
}
|
||||||
scalars: runtime.Types.Extensions.GetPayloadResult<{
|
scalars: runtime.Types.Extensions.GetPayloadResult<{
|
||||||
id: number
|
id: number
|
||||||
@@ -1016,6 +1142,7 @@ readonly fields: UserFieldRefs;
|
|||||||
export interface Prisma__UserClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> {
|
export interface Prisma__UserClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> {
|
||||||
readonly [Symbol.toStringTag]: "PrismaPromise"
|
readonly [Symbol.toStringTag]: "PrismaPromise"
|
||||||
role<T extends Prisma.RoleDefaultArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.RoleDefaultArgs<ExtArgs>>): Prisma.Prisma__RoleClient<runtime.Types.Result.GetResult<Prisma.$RolePayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions>
|
role<T extends Prisma.RoleDefaultArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.RoleDefaultArgs<ExtArgs>>): Prisma.Prisma__RoleClient<runtime.Types.Result.GetResult<Prisma.$RolePayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions>
|
||||||
|
refreshTokens<T extends Prisma.User$refreshTokensArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$refreshTokensArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$RefreshTokenPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
|
||||||
/**
|
/**
|
||||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||||
@@ -1396,6 +1523,30 @@ export type UserDeleteManyArgs<ExtArgs extends runtime.Types.Extensions.Internal
|
|||||||
limit?: number
|
limit?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User.refreshTokens
|
||||||
|
*/
|
||||||
|
export type User$refreshTokensArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||||
|
/**
|
||||||
|
* Select specific fields to fetch from the RefreshToken
|
||||||
|
*/
|
||||||
|
select?: Prisma.RefreshTokenSelect<ExtArgs> | null
|
||||||
|
/**
|
||||||
|
* Omit specific fields from the RefreshToken
|
||||||
|
*/
|
||||||
|
omit?: Prisma.RefreshTokenOmit<ExtArgs> | null
|
||||||
|
/**
|
||||||
|
* Choose, which related nodes to fetch as well
|
||||||
|
*/
|
||||||
|
include?: Prisma.RefreshTokenInclude<ExtArgs> | null
|
||||||
|
where?: Prisma.RefreshTokenWhereInput
|
||||||
|
orderBy?: Prisma.RefreshTokenOrderByWithRelationInput | Prisma.RefreshTokenOrderByWithRelationInput[]
|
||||||
|
cursor?: Prisma.RefreshTokenWhereUniqueInput
|
||||||
|
take?: number
|
||||||
|
skip?: number
|
||||||
|
distinct?: Prisma.RefreshTokenScalarFieldEnum | Prisma.RefreshTokenScalarFieldEnum[]
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User without action
|
* User without action
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Controller, Get, Query } from '@nestjs/common'
|
||||||
|
import { ApiQuery } from '@nestjs/swagger'
|
||||||
|
import { CardexService } from './cardex.service'
|
||||||
|
|
||||||
|
@Controller('cardex')
|
||||||
|
export class CardexController {
|
||||||
|
constructor(private readonly service: CardexService) {}
|
||||||
|
|
||||||
|
@Get('')
|
||||||
|
@ApiQuery({ name: 'startDate', required: true, type: Date })
|
||||||
|
@ApiQuery({ name: 'endDate', required: false, type: Date })
|
||||||
|
@ApiQuery({ name: 'inventoryId', required: false, type: Number })
|
||||||
|
@ApiQuery({ name: 'productId', required: false, type: Number })
|
||||||
|
async getStock(
|
||||||
|
@Query('startDate') startDate: Date,
|
||||||
|
@Query('endDate') endDate: Date,
|
||||||
|
@Query('inventoryId') inventoryId: number,
|
||||||
|
@Query('productId') productId: number,
|
||||||
|
) {
|
||||||
|
return this.service.getCardex({
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
inventoryId,
|
||||||
|
productId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { PrismaModule } from '../../prisma/prisma.module'
|
||||||
|
import { CardexController } from './cardex.controller'
|
||||||
|
import { CardexService } from './cardex.service'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [PrismaModule],
|
||||||
|
controllers: [CardexController],
|
||||||
|
providers: [CardexService],
|
||||||
|
})
|
||||||
|
export class CardexModule {}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import { ResponseMapper } from '../../common/response/response-mapper'
|
||||||
|
import { Prisma } from '../../generated/prisma/client'
|
||||||
|
import { PrismaService } from '../../prisma/prisma.service'
|
||||||
|
import { ReadCardexDto } from './dto/read-pos.dto'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CardexService {
|
||||||
|
constructor(private prisma: PrismaService) {}
|
||||||
|
|
||||||
|
async getCardex({ startDate, endDate, inventoryId, productId }: ReadCardexDto) {
|
||||||
|
if (!endDate) {
|
||||||
|
endDate = dayjs(startDate).add(1, 'months').toDate()
|
||||||
|
}
|
||||||
|
const where: Prisma.StockMovementWhereInput = {}
|
||||||
|
|
||||||
|
if (inventoryId !== undefined) where.inventoryId = inventoryId
|
||||||
|
if (productId !== undefined) where.productId = productId
|
||||||
|
|
||||||
|
if (startDate || endDate) {
|
||||||
|
where.createdAt = {}
|
||||||
|
if (startDate) where.createdAt.gte = new Date(startDate)
|
||||||
|
if (endDate) where.createdAt.lte = new Date(endDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = await this.prisma.stockMovement.findMany({
|
||||||
|
where,
|
||||||
|
include: { product: true, inventory: true },
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapped = items.map(i => ({
|
||||||
|
id: i.id,
|
||||||
|
type: i.type,
|
||||||
|
quantity: Number(i.quantity),
|
||||||
|
fee: Number(i.fee),
|
||||||
|
totalCost: Number(i.totalCost),
|
||||||
|
referenceType: i.referenceType,
|
||||||
|
referenceId: i.referenceId,
|
||||||
|
createdAt: i.createdAt,
|
||||||
|
avgCost: Number(i.avgCost),
|
||||||
|
product: {
|
||||||
|
name: i.product.name,
|
||||||
|
sku: i.product.sku,
|
||||||
|
id: i.productId,
|
||||||
|
},
|
||||||
|
inventory: {
|
||||||
|
name: i.inventory.name,
|
||||||
|
id: i.inventoryId,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
return ResponseMapper.list(mapped)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ApiPropertyOptional } from '@nestjs/swagger'
|
||||||
|
import { IsDateString, IsNumber, IsOptional } from 'class-validator'
|
||||||
|
|
||||||
|
export class ReadCardexDto {
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsDateString()
|
||||||
|
startDate: Date
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
endDate?: Date
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
inventoryId?: number
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
productId?: number
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
import { PrismaModule } from '../prisma/prisma.module'
|
import { PrismaModule } from '../../prisma/prisma.module'
|
||||||
import { PosController } from './pos.controller'
|
import { PosController } from './pos.controller'
|
||||||
import { PosService } from './pos.service'
|
import { PosService } from './pos.service'
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
import { ResponseMapper } from '../common/response/response-mapper'
|
import { ResponseMapper } from '../../common/response/response-mapper'
|
||||||
import { Prisma } from '../generated/prisma/client'
|
import { Prisma } from '../../generated/prisma/client'
|
||||||
import { PrismaService } from '../prisma/prisma.service'
|
import { PrismaService } from '../../prisma/prisma.service'
|
||||||
import { CreateOrderDto } from './dto/create-pos.dto'
|
import { CreateOrderDto } from './dto/create-pos.dto'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common'
|
import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from '@nestjs/common'
|
||||||
|
import { ApiQuery } from '@nestjs/swagger'
|
||||||
import { CreateProductDto } from './dto/create-product.dto'
|
import { CreateProductDto } from './dto/create-product.dto'
|
||||||
import { UpdateProductDto } from './dto/update-product.dto'
|
import { UpdateProductDto } from './dto/update-product.dto'
|
||||||
import { ProductsService } from './products.service'
|
import { ProductsService } from './products.service'
|
||||||
@@ -13,8 +14,10 @@ export class ProductsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
findAll() {
|
@ApiQuery({ name: 'page', required: false, type: Number, default: 1 })
|
||||||
return this.productsService.findAll()
|
@ApiQuery({ name: 'pageSize', required: false, type: Number, default: 30 })
|
||||||
|
findAll(@Query('page') page: number = 1, @Query('pageSize') pageSize: number = 30) {
|
||||||
|
return this.productsService.findAll(page, pageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
import { ShortEntity } from '../common/interfaces/response-models'
|
import { ShortEntity } from '../common/interfaces/response-models'
|
||||||
import { ResponseMapper } from '../common/response/response-mapper'
|
import { ResponseMapper } from '../common/response/response-mapper'
|
||||||
|
import { Prisma } from '../generated/prisma/client'
|
||||||
import { PrismaService } from '../prisma/prisma.service'
|
import { PrismaService } from '../prisma/prisma.service'
|
||||||
import { CreateProductDto } from './dto/create-product.dto'
|
import { CreateProductDto } from './dto/create-product.dto'
|
||||||
|
|
||||||
@@ -28,10 +29,17 @@ export class ProductsService {
|
|||||||
return ResponseMapper.create(item)
|
return ResponseMapper.create(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll() {
|
async findAll(page = 1, pageSize = 20) {
|
||||||
const items = await this.prisma.product.findMany({
|
const query: Prisma.ProductFindManyArgs = {}
|
||||||
include: { brand: true, category: true, stockBalances: true },
|
|
||||||
})
|
const [items, count] = await this.prisma.$transaction([
|
||||||
|
this.prisma.product.findMany({
|
||||||
|
include: { brand: true, category: true, stockBalances: true },
|
||||||
|
skip: (page - 1) * pageSize,
|
||||||
|
take: pageSize,
|
||||||
|
}),
|
||||||
|
this.prisma.product.count(),
|
||||||
|
])
|
||||||
|
|
||||||
const mapped = items.map(p => {
|
const mapped = items.map(p => {
|
||||||
const { brandId, categoryId, ...rest } = p as any
|
const { brandId, categoryId, ...rest } = p as any
|
||||||
@@ -48,7 +56,7 @@ export class ProductsService {
|
|||||||
|
|
||||||
return { ...rest, brand, category, stock }
|
return { ...rest, brand, category, stock }
|
||||||
})
|
})
|
||||||
return ResponseMapper.list(mapped)
|
return ResponseMapper.paginate(mapped, count, page, pageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(id: number) {
|
async findOne(id: number) {
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ export class PurchaseReceiptItemsService {
|
|||||||
const item = await this.prisma.purchaseReceiptItem.create({ data: payload })
|
const item = await this.prisma.purchaseReceiptItem.create({ data: payload })
|
||||||
return ResponseMapper.create(item)
|
return ResponseMapper.create(item)
|
||||||
}
|
}
|
||||||
async findAll(receiptId?: number) {
|
async findAll(receiptId: number) {
|
||||||
const where = receiptId ? { receiptId: Number(receiptId) } : undefined
|
const where = { receiptId: Number(receiptId) }
|
||||||
const items = await this.prisma.purchaseReceiptItem.findMany({
|
const items = await this.prisma.purchaseReceiptItem.findMany({
|
||||||
where,
|
where,
|
||||||
include: { product: true },
|
include: { product: true },
|
||||||
|
|||||||
@@ -47,7 +47,22 @@ export class PurchaseReceiptsService {
|
|||||||
async findOne(id: number) {
|
async findOne(id: number) {
|
||||||
const item = await this.prisma.purchaseReceipt.findUnique({
|
const item = await this.prisma.purchaseReceipt.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: { supplier: true, inventory: true, items: true },
|
include: {
|
||||||
|
supplier: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inventory: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if (!item) return null
|
if (!item) return null
|
||||||
return ResponseMapper.single(item)
|
return ResponseMapper.single(item)
|
||||||
|
|||||||
@@ -17,9 +17,22 @@ export class SuppliersController {
|
|||||||
return this.suppliersService.findAll()
|
return this.suppliersService.findAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':supplierId')
|
||||||
findOne(@Param('id') id: string) {
|
findOne(@Param('supplierId') supplierId: string) {
|
||||||
return this.suppliersService.findOne(Number(id))
|
return this.suppliersService.findOne(Number(supplierId))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':supplierId/invoices')
|
||||||
|
getInvoices(@Param('supplierId') supplierId: string) {
|
||||||
|
return this.suppliersService.getInvoices(Number(supplierId))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':supplierId/invoices/:invoiceId')
|
||||||
|
getInvoice(
|
||||||
|
@Param('supplierId') supplierId: string,
|
||||||
|
@Param('invoiceId') invoiceId: string,
|
||||||
|
) {
|
||||||
|
return this.suppliersService.getInvoice(Number(supplierId), Number(invoiceId))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
|
|||||||
@@ -18,7 +18,82 @@ export class SuppliersService {
|
|||||||
async findOne(id: number) {
|
async findOne(id: number) {
|
||||||
const item = await this.prisma.supplier.findUnique({ where: { id } })
|
const item = await this.prisma.supplier.findUnique({ where: { id } })
|
||||||
if (!item) return null
|
if (!item) return null
|
||||||
return ResponseMapper.single(item)
|
const receiptsInfo = await this.prisma.purchaseReceipt.aggregate({
|
||||||
|
where: {
|
||||||
|
supplierId: id,
|
||||||
|
},
|
||||||
|
_count: true,
|
||||||
|
_sum: {
|
||||||
|
totalAmount: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return ResponseMapper.single({
|
||||||
|
...item,
|
||||||
|
receiptsOverview: {
|
||||||
|
totalPayment: receiptsInfo._sum.totalAmount,
|
||||||
|
count: receiptsInfo._count,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async getInvoices(supplierId: number) {
|
||||||
|
const items = await this.prisma.purchaseReceipt.findMany({
|
||||||
|
where: {
|
||||||
|
supplierId,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
inventory: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
count: true,
|
||||||
|
fee: true,
|
||||||
|
total: true,
|
||||||
|
product: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
sku: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
omit: {
|
||||||
|
inventoryId: true,
|
||||||
|
supplierId: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ResponseMapper.list(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getInvoice(supplierId: number, invoiceId: number) {
|
||||||
|
const invoice = await this.prisma.purchaseReceipt.findUnique({
|
||||||
|
where: {
|
||||||
|
id: invoiceId,
|
||||||
|
supplierId,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
inventory: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: true,
|
||||||
|
},
|
||||||
|
omit: {
|
||||||
|
inventoryId: true,
|
||||||
|
supplierId: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ResponseMapper.single(invoice)
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(id: number, data: any) {
|
async update(id: number, data: any) {
|
||||||
|
|||||||
Reference in New Issue
Block a user