Compare commits
1370 Commits
ddc9258dfe
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 52c182cb5f | |||
| 9cef3964e9 | |||
| cf0fb724a2 | |||
| bbb893dd6c | |||
| 724f152d70 | |||
| 27be8241bf | |||
| d27e437ba6 | |||
| f5253b29f4 | |||
| 0141a243ce | |||
| a0e1b8c0eb | |||
| 45fb45845a | |||
| 409db82368 | |||
| 30d761f899 | |||
| 70636f6ac5 | |||
| 59392a723c | |||
| c782492ab5 | |||
| 844af30b18 | |||
| 6fded3993a | |||
| f26d6bd4f3 | |||
| 2621cc0d8d | |||
| a8238dc9ba | |||
| 49d35f080d | |||
| 189a52b3cd | |||
| 3f8ce5daf7 | |||
| 087ba1126e | |||
| db4e9612a0 | |||
| cb4917c536 | |||
| 9f32eb5439 | |||
| f596b46364 | |||
| 117da523d2 | |||
| c2901dc0a9 | |||
| 8c2a8a7998 | |||
| 1dc74947f4 | |||
| f63e793c88 | |||
| 29a84b899d | |||
| be706a70f8 | |||
| 474b3e762c | |||
| f793d4cce6 | |||
| c3f46cd184 | |||
| 6bf336356d | |||
| 55699da42c | |||
| 053f184a33 | |||
| 6541cb2adf | |||
| 7dca84947e | |||
| 45fd6fda08 | |||
| 31e80fb386 | |||
| 7ea28cc6c0 | |||
| c0faa398b8 | |||
| 19be1f0d03 | |||
| c43d3225e3 | |||
| 7125d15b3f | |||
| 4b7cf171c8 | |||
| 59fdedfaa0 | |||
| 71d249d8bf | |||
| e496a62b36 | |||
| 0bfef0806b | |||
| 5c69388f1c | |||
| 7ed0388acb | |||
| 3aa0c7d77a | |||
| 77aa277347 | |||
| 2fff1ca8a8 | |||
| e58929d9a0 | |||
| 90560ecd2c | |||
| b07953fb7d | |||
| 01ef3c5a42 | |||
| 2aed851224 | |||
| c56fcfbd14 | |||
| ca2020b9c6 | |||
| c87212d54a | |||
| db22d47900 | |||
| 143485e107 | |||
| c1d4b24418 | |||
| 9655d4fa05 | |||
| 4efe452f1c | |||
| cb21a85736 | |||
| d2b70e5883 | |||
| 1a065b649c | |||
| 34c58c3755 | |||
| 37d8a414d3 | |||
| 7f4f232c32 | |||
| d6f257bcc6 | |||
| 3109f4d5ff | |||
| 235b33ae08 | |||
| 2d135b7068 | |||
| 8831320a4c | |||
| 000d409e4d | |||
| 160124a184 | |||
| 26dad422ec | |||
| e59cbade53 | |||
| 6423886930 | |||
| 6adf09faa0 | |||
| d7f3920763 | |||
| 3af92ebf71 | |||
| 5ab90830a0 | |||
| 4f72919269 | |||
| f2c9dcc900 | |||
| b4ec792cc0 | |||
| 9b3f48defe | |||
| 5edc90bd4d | |||
| d140251aa0 | |||
| e7fb2df5c7 | |||
| f27fd3f6da | |||
| d3e2b106af | |||
| 769d2059ca | |||
| 53349fae83 | |||
| d8eb1559c8 | |||
| 6b9de04d83 | |||
| 529ec0c77d | |||
| 246677b750 | |||
| c839714945 | |||
| 8614917a05 | |||
| 2de80ea6ca | |||
| 6f5fed0ffb | |||
| 767152c535 | |||
| 3128893ba2 | |||
| bcf460cfd5 | |||
| da704be925 | |||
| c049730599 | |||
| 0194345ed8 | |||
| 82d8cd36b9 | |||
| 66110da6c4 | |||
| 267648074c | |||
| 32b4c40e11 | |||
| f044195d86 | |||
| 202e20ddd5 | |||
| 905f2e7bf4 | |||
| b39a52fb20 | |||
| 098bd02808 | |||
| b35c991634 | |||
| dc376894be | |||
| 90788f22da | |||
| d901ebe365 | |||
| 7f6ba99328 | |||
| 8afdf06c8e | |||
| e1205a8de5 | |||
| 08da93b6c3 | |||
| b0ace924d4 | |||
| 593118c181 | |||
| 67d2a05ac4 | |||
| b95d539907 | |||
| 76b363fdaf | |||
| 2cb0d9b607 | |||
| 037a10e93e | |||
| c36b9aa872 | |||
| 14a9435a5a | |||
| 8126c2d3f4 | |||
| a892b7a6e4 | |||
| be7b219569 | |||
| 998d725528 | |||
| 17cd3dc3a3 | |||
| 1d9488b64d | |||
| 9fb520d8c3 | |||
| 3bcfacdf84 | |||
| 8ea41802dd | |||
| af5bd12577 | |||
| 6f3d4c0bff | |||
| 125c16a20c | |||
| d01bd7fc0c | |||
| d3fc2e6ad3 | |||
| c1ed8cd028 | |||
| 786ac06e09 | |||
| a00fd6d51f | |||
| c439396595 | |||
| b013ef8f4b | |||
| 7c3968636d | |||
| bf3f0cc784 | |||
| 7f09ef2911 | |||
| 8b9b5744bf | |||
| fa369f7b81 | |||
| 5485d2c0cc | |||
| c1ff4d1a08 | |||
| 8a2e91e702 | |||
| 65acad1c0d | |||
| bc3b944f5d | |||
| e8fe6940c2 | |||
| 7df88ef5e4 | |||
| 8a87113275 | |||
| 94ed9ac343 | |||
| 848c9e4b2f | |||
| b26c9432f1 | |||
| 3c573380a8 | |||
| a5f82c3ef3 | |||
| 78ae8989ba | |||
| cebe20fd43 | |||
| 3da3aee50d | |||
| 2c7449ef7a | |||
| fb746b4d59 | |||
| b3fd5eafbc | |||
| 4121666c70 | |||
| a3df87caee | |||
| 8db4ad2203 | |||
| 0d1b4b7eb8 | |||
| e0f73c20c9 | |||
| 3e5c6ca8da | |||
| bffc5666fe | |||
| 7d7689999e | |||
| fb52f88ec3 | |||
| 902e3ac59a | |||
| 97f66f808a | |||
| 240264aafb | |||
| d5999bfb20 | |||
| bded9189e3 | |||
| 282d1eb052 | |||
| 7d4adbb3e4 | |||
| 8e9b9dfc98 | |||
| bb1e73443b | |||
| 2b12e6ada7 | |||
| 1ae640dc02 | |||
| 9d6f2de4ab | |||
| 280cf4518a | |||
| 439ec3438d | |||
| 049a5b2264 | |||
| 5aac81f601 | |||
| 6053b7340f | |||
| 8e1a28577c | |||
| e6bc123481 | |||
| 6d8193296e | |||
| 6ded3b859f | |||
| 94c252ec6c | |||
| 9a0a757757 | |||
| 780b899d42 | |||
| 5270313b3d | |||
| 1281976ec3 | |||
| 267a57c4ea | |||
| e5c3863eee | |||
| c8f85496ce | |||
| 9ddda1a933 | |||
| ca393d1625 | |||
| d916ed471b | |||
| 3d51a1aa6d | |||
| 3328279581 | |||
| 053f3ce557 | |||
| 6d936c4be7 | |||
| d210eb857f | |||
| 1e0f18c854 | |||
| 9263c24ede | |||
| 3f7f8a4498 | |||
| 1ab124ac7a | |||
| 65da63d1c8 | |||
| eeceb4a8f6 | |||
| 58836fb0ef | |||
| 4016c8b6b5 | |||
| ab2b5135c0 | |||
| ac2ed79e10 | |||
| 7ce5616e65 | |||
| aefd8ffba4 | |||
| c3467bdd9d | |||
| 641130e506 | |||
| 6d05001812 | |||
| 4a3515f6f3 | |||
| b88e840ff5 | |||
| 84c88ef69e | |||
| 8b70b77b85 | |||
| 76941abbf2 | |||
| a161306359 | |||
| 8a528f0711 | |||
| 6c1f95db9f | |||
| 861984e4b1 | |||
| c6354ac656 | |||
| 0c1287d3b9 | |||
| 862912cd66 | |||
| a605fdc351 | |||
| d234a2371b | |||
| 183fefb557 | |||
| 64b3ec626c | |||
| fd52cadbff | |||
| b694340f38 | |||
| 888336dd04 | |||
| e35e857380 | |||
| c1120d1878 | |||
| 428a002e9f | |||
| 1d3bf94b88 | |||
| 8f0efc0d72 | |||
| e760bd5f97 | |||
| 899f8dce20 | |||
| aa1f3b1cb3 | |||
| f5825f9a18 | |||
| 607024c813 | |||
| 206bdc6392 | |||
| eda8d357da | |||
| 32b46f58a4 | |||
| e92eccc7d3 | |||
| af5f9567f1 | |||
| 8faaef1ef5 | |||
| d33b908775 | |||
| 5968329c8f | |||
| 09d67a7522 | |||
| 0b32b69d10 | |||
| 9bfb880f7b | |||
| b90e056e7c | |||
| dc0b49355d | |||
| 76e40cd9e1 | |||
| 0f3c8c862f | |||
| dff2b05401 | |||
| 765f3c42c1 | |||
| 1e71e54314 | |||
| d895583ea2 | |||
| 7450f90a0f | |||
| 63af22b671 | |||
| 407592680a | |||
| d6badafeb9 | |||
| d408dadd88 | |||
| 253b04ec0d | |||
| de2692f704 | |||
| 665f0d1454 | |||
| 24f576aeaa | |||
| f8c62a90f0 | |||
| 951011bc0e | |||
| 5fd683eacc | |||
| 5f6df7c69d | |||
| da074df63c | |||
| 32c71fe49b | |||
| c4d0a20bbc | |||
| 263f389e91 | |||
| 24e80a6a0a | |||
| e0638b5a98 | |||
| 57abbe8534 | |||
| f61c780185 | |||
| 48263b28b5 | |||
| 7cd9a3e074 | |||
| 914c7e4fc1 | |||
| 94aee4540a | |||
| aaf61760a3 | |||
| 8a88c6878e | |||
| 4f01d2407b | |||
| d6dd0a1602 | |||
| c1dc88cdd9 | |||
| 1beb0dbaf3 | |||
| de32d72eda | |||
| 87aaa28d92 | |||
| 70347920f2 | |||
| 2f177ad603 | |||
| 06b97cbdae | |||
| 2382b2dfae | |||
| fc3ed1fb11 | |||
| 29cfaccd02 | |||
| d6e11766da | |||
| 3cd7120b4b | |||
| 433bb7d05e | |||
| 65598bceac | |||
| 67389a5f78 | |||
| 0909f34649 | |||
| 4cfa4dbffd | |||
| f3892861b1 | |||
| 572d564135 | |||
| 7eb4a32552 | |||
| 9d2cecd55b | |||
| 16962a6df8 | |||
| cf2b88199a | |||
| 75e2f84726 | |||
| 8b34609e53 | |||
| d7939a9ca4 | |||
| ee8e17d80e | |||
| 29bebe6149 | |||
| 6d0b764ee2 | |||
| 89abbde753 | |||
| 61d22dbfa1 | |||
| 62146ff970 | |||
| 802c0c3f09 | |||
| d54a3aab7a | |||
| 6d22aec2f4 | |||
| 86a5b7e63e | |||
| 3a0c0fc9a7 | |||
| 10b29c336a | |||
| e4ae514830 | |||
| d9f35602b2 | |||
| 1838d07082 | |||
| 655601dddb | |||
| 3ac8b63164 | |||
| 43a6d1d631 | |||
| 1526879a38 | |||
| 157533bb9d | |||
| cf31d43702 | |||
| 26b7dfc06c | |||
| 61835c3f26 | |||
| 55c101df12 | |||
| c439eec66c | |||
| 75518897f1 | |||
| 3bd4ac1f56 | |||
| 2eb19b36a6 | |||
| bbd5bbab9b | |||
| 8ff63fadec | |||
| 8af09e1841 | |||
| 5d3cdeb960 | |||
| d4fe665462 | |||
| 560b15ec93 | |||
| efaebb2f4e | |||
| 9658ad621a | |||
| f918e735a5 | |||
| 4907dd478a | |||
| 31c7bd34b7 | |||
| e0ed8f41bb | |||
| ef0af906ff | |||
| 2d332f1ded | |||
| 6c3189c8f0 | |||
| 4abb3917e6 | |||
| 59c32ef8d8 | |||
| 4514627ec0 | |||
| ceae4972b8 | |||
| 4b754b5ef5 | |||
| f7f239fcb9 | |||
| 78846fd85a | |||
| 33411c4e7d | |||
| 0a9731be37 | |||
| 7bf29ffe32 | |||
| ce8e35b628 | |||
| c85b61000a | |||
| 39820d7122 | |||
| 4054d1acf8 | |||
| 02330e2173 | |||
| 7ab53557ce | |||
| 50f1ed8d41 | |||
| f9b69be791 | |||
| c092696a9a | |||
| d1cf575845 | |||
| ce3f6323ea | |||
| 008d96d0b8 | |||
| 473980d6b4 | |||
| 625bb4be4a | |||
| f74b717bc0 | |||
| ffb91586a0 | |||
| 103499a163 | |||
| 1fd568c562 | |||
| b61a3de40a | |||
| c729c595ee | |||
| f05c222c42 | |||
| 3b9c77f321 | |||
| ccf25a69f0 | |||
| 5744e19344 | |||
| 29a6d885b4 | |||
| 80d1d205a1 | |||
| f81d9ebb40 | |||
| 4588c2b9e9 | |||
| 22ce0d6e7a | |||
| 26cb53b231 | |||
| 183313b550 | |||
| f917d8e370 | |||
| fc6e76d756 | |||
| 8750ccbb7d | |||
| 87411d9b87 | |||
| 1dfcc694ef | |||
| 67a86ed9ab | |||
| 5f31d0a89c | |||
| 6d6f8b419a | |||
| 2cfdafa507 | |||
| 6d0f83fab1 | |||
| bae41efdf5 | |||
| 467410af6a | |||
| 5b09a11a6e | |||
| 72f8064d06 | |||
| a222da1970 | |||
| 3cbd6b265e | |||
| 9aefa5d08f | |||
| f51ced1c31 | |||
| f683f149e6 | |||
| 7482e974f2 | |||
| 83fc24be0c | |||
| 4e61b20ba8 | |||
| 1c3c6adcc2 | |||
| 2a2078a85f | |||
| 3e17709998 | |||
| e2b24964bc | |||
| cfcbdfb749 | |||
| fbf8e883d9 | |||
| 969fa60518 | |||
| 63ee3c7b9f | |||
| 6bb1222e0b | |||
| baa59f16ce | |||
| 906e893bf0 | |||
| c68fe87622 | |||
| 7851dd80ca | |||
| c95cc818b5 | |||
| 25483dd8f2 | |||
| c81ab45919 | |||
| 4d9b1f1dff | |||
| 3aed09d023 | |||
| 68763996ad | |||
| 347bc0cf7b | |||
| 29b12cdc46 | |||
| 0e03a5914b | |||
| 936c6cdf00 | |||
| efba076c41 | |||
| 7f0f6567b0 | |||
| e5696191af | |||
| 62c403307f | |||
| 7f2a6ba438 | |||
| 9afd5c3bf5 | |||
| dd2bf7a8ff | |||
| 4a05bd5bc3 | |||
| 850ef006c5 | |||
| ce39e96c0a | |||
| 2366790cc0 | |||
| 4fa752f7c9 | |||
| 76e1a333dc | |||
| 0da2beaa64 | |||
| 40c12ae487 | |||
| 2656341956 | |||
| 9894f003e3 | |||
| b57b11ca9a | |||
| 46d0cbfd41 | |||
| a207237bc2 | |||
| 476b4b5d4f | |||
| 911f5f049a | |||
| 5588d5a76c | |||
| 0ae247ac98 | |||
| 8480ce1512 | |||
| 07b914675d | |||
| 64d4569655 | |||
| 8ab20cee51 | |||
| 3f4636d698 | |||
| cc9f7e58ec | |||
| 168ebead92 | |||
| f79c569383 | |||
| b67e4cc6d2 | |||
| cb19fa63f8 | |||
| fd3ac28ae2 | |||
| e504ca60ce | |||
| d3f70942b2 | |||
| 51ca916056 | |||
| 4ae55a4956 | |||
| a23376c727 | |||
| 55ac79c717 | |||
| 95a122c4bf | |||
| f30ccd6c45 | |||
| cd1d9f4cf2 | |||
| caa92843b3 | |||
| 717eaf0851 | |||
| 975acb9833 | |||
| 85479435b0 | |||
| d134f5541d | |||
| 18b63272b7 | |||
| e60c0df77b | |||
| eea7937225 | |||
| 9fad0eafd0 | |||
| 91a62f88d2 | |||
| 8f0e5ad37a | |||
| cf42caa519 | |||
| 8f7ce314fb | |||
| d45d16a810 | |||
| 0fe16ad79e | |||
| af1bf82c75 | |||
| 9b6af75e98 | |||
| f35d375c5f | |||
| 522af71f9b | |||
| 1dfc1fd2c1 | |||
| a9d0a060b8 | |||
| d3104bb5a2 | |||
| 800b7d883e | |||
| 6d190d2501 | |||
| 0f03deeadd | |||
| fc46e807e7 | |||
| c98394b5bf | |||
| 95e8da2e39 | |||
| a19aa47e34 | |||
| 00d9361aad | |||
| 577e5d947a | |||
| 1985f7b725 | |||
| 30da08689d | |||
| 9a210bceb9 | |||
| 8302b00a9c | |||
| 0d918b8719 | |||
| 278afb5ee8 | |||
| c7e18d689e | |||
| 6d233f5bfb | |||
| 949b094490 | |||
| 34c5764472 | |||
| 9f59b94336 | |||
| f5f2949545 | |||
| 01e3d878d3 | |||
| 45741a6295 | |||
| 42edd626fd | |||
| af86fdd8ed | |||
| dc385b8422 | |||
| 8d5e158d59 | |||
| 7c4272ffe9 | |||
| 27af6a0953 | |||
| 97a095b422 | |||
| 6d76acc0bc | |||
| aeaba64865 | |||
| c492442d3d | |||
| b0497142ed | |||
| 95b1c16cf1 | |||
| 7265164b0a | |||
| 841bb67d60 | |||
| c70cd797ac | |||
| 80d68e0aa9 | |||
| 23573caceb | |||
| 661e826767 | |||
| 8989975be1 | |||
| a4d68cafd8 | |||
| 472ee0fd53 | |||
| 86a12cc223 | |||
| 01469d97f0 | |||
| c58b6ca2aa | |||
| 58ef4ec620 | |||
| e3c3a5c444 | |||
| a7336999ef | |||
| 0e3586dccf | |||
| 2490c69beb | |||
| 986f27a48c | |||
| 6bc8e4e7f0 | |||
| dcac52ff9d | |||
| 6cfaf3fdbe | |||
| 10c686bfa1 | |||
| f77ffeaf4c | |||
| ff6ee91075 | |||
| 93d0f97a56 | |||
| e5b4409df7 | |||
| f4fae86d31 | |||
| fe8aa2e758 | |||
| 0209c49503 | |||
| 2b1e2a12eb | |||
| e98e1dc634 | |||
| 583ca15dcc | |||
| 1264b987fe | |||
| ffec9b7dc4 | |||
| a742fc8c54 | |||
| cf8845848a | |||
| 6b1e697209 | |||
| a6b9247305 | |||
| bfc11bcace | |||
| 132016f562 | |||
| 96cd94d77f | |||
| bab0187467 | |||
| 8d4ff3c88e | |||
| dd89a70789 | |||
| 50e583389e | |||
| ef8e0d0e83 | |||
| 08f104d4c9 | |||
| 4346fbffe5 | |||
| 03231ab3f3 | |||
| 80f05c7029 | |||
| 5199afb9b5 | |||
| 3fa50c158c | |||
| cdbf1785a3 | |||
| 3eadedcb19 | |||
| 4e469a3ffc | |||
| f93eb9ec71 | |||
| eb37257ae8 | |||
| bb99d5ae1c | |||
| e982684d95 | |||
| e2e368e9f8 | |||
| 4a3c4f4bd7 | |||
| fd3b96a11c | |||
| 9d3aba9179 | |||
| 1b30825b76 | |||
| 6f6754db39 | |||
| f1eb857eda | |||
| cad2ed9dba | |||
| c94e4c3194 | |||
| 6599fdc6c2 | |||
| f5431ddade | |||
| 835486d04f | |||
| db53043b19 | |||
| 131a7a95b9 | |||
| 6a68c2fbcd | |||
| 5606858dc7 | |||
| b17af2620b | |||
| 55038d2bcb | |||
| a0ffdce1bb | |||
| a9ea5982cf | |||
| 557d0eff2f | |||
| 241a912f08 | |||
| caba8348bf | |||
| 3332b7f258 | |||
| f1ef5fce58 | |||
| b647518d2f | |||
| 834f96f258 | |||
| 57b7d0b35b | |||
| 1679bfdc7d | |||
| d9dc7c67be | |||
| 3986c9cd0a | |||
| e71118ad09 | |||
| 795a8662f9 | |||
| 81165c6954 | |||
| c419fe610d | |||
| 87dc8ead08 | |||
| c231994ad1 | |||
| fe8902ba7f | |||
| f4f28c095d | |||
| 50a22877e4 | |||
| 1b2bc1424d | |||
| e6c9942d7d | |||
| 3998c997d4 | |||
| 207ed7ce36 | |||
| 415dbed67a | |||
| e3196460b9 | |||
| 34b566343f | |||
| 7b4d6d7858 | |||
| b310d96482 | |||
| 9877206825 | |||
| 7fd088b758 | |||
| 8220db14f3 | |||
| dc79787f70 | |||
| 0272c9434c | |||
| 658e3f66b3 | |||
| 0d8f403058 | |||
| 4623bb3bb7 | |||
| ec741acf7c | |||
| 8edd996b89 | |||
| d762bb3228 | |||
| 842afcfdb2 | |||
| e17f8aa734 | |||
| 577b2dd035 | |||
| 8f6ca1593e | |||
| 7e95547eb1 | |||
| 8d39c16e26 | |||
| fa25923e62 | |||
| b9cd79cabe | |||
| 6049fcbb1b | |||
| 93b36be42c | |||
| e21e46b2c8 | |||
| 78b16d2c1c | |||
| 9afe62eae5 | |||
| bd2fe9bb03 | |||
| dd10760da1 | |||
| 3bf54a4e32 | |||
| 7750415e9a | |||
| ba1aa84ac4 | |||
| 9d89b547b2 | |||
| 808df9a6ad | |||
| abc10a77f8 | |||
| bc5ba9c352 | |||
| 554f871a1a | |||
| af90c6fcf3 | |||
| 977e9e0344 | |||
| b924c92908 | |||
| b7ff4a915b | |||
| 56334128ae | |||
| fe14591e02 | |||
| ab7f8b0846 | |||
| bb4aea512d | |||
| f49d6f45b6 | |||
| 74be47b84c | |||
| 1a29b47583 | |||
| d3b4f217e2 | |||
| cfcfceb9e8 | |||
| 5b913799d0 | |||
| f0c96f5e10 | |||
| e45ff93100 | |||
| 05b47fa2e9 | |||
| c53154d115 | |||
| e79d034c2c | |||
| 1136d59f20 | |||
| b1ed0b17ed | |||
| 8604a18ed5 | |||
| 267b68283f | |||
| a47426af70 | |||
| 035b5f2eac | |||
| 70000c776e | |||
| 8593720c15 | |||
| 9f5409cc70 | |||
| 621c61c094 | |||
| b5287f4a7d | |||
| 5f483b4980 | |||
| ff5593ebc5 | |||
| 684f65250f | |||
| 7a986189df | |||
| a3bec6a9b1 | |||
| ea6181265d | |||
| 65e1025289 | |||
| a144bba54b | |||
| 7f8efcf32f | |||
| 95968681ce | |||
| 338bcd0df9 | |||
| eeec6d2f92 | |||
| 6ea58d7990 | |||
| 7d3cba7e79 | |||
| f4ab1b382d | |||
| d9a2384701 | |||
| 235f3690cb | |||
| 548e85a00a | |||
| 4d2401ff59 | |||
| eac0a6573a | |||
| c77198625c | |||
| b3fd996f3f | |||
| 830c71ada7 | |||
| 4fbde89251 | |||
| 9eae5740a8 | |||
| c019b2608c | |||
| 57a4512a0e | |||
| 7deffc885e | |||
| b33ad857b1 | |||
| 207d9ce5f6 | |||
| ee1aa1bbed | |||
| 856ebd1b60 | |||
| bb7d7ae3a9 | |||
| 5418c0195e | |||
| 35c98ebb97 | |||
| 6cb9653dea | |||
| f0550f5233 | |||
| f21cd63367 | |||
| 325c37e26e | |||
| 4ff9fed3df | |||
| ff69796eab | |||
| cd7cecb61b | |||
| e85a1def90 | |||
| ba72a896bb | |||
| b5b1741f21 | |||
| 19a5d906da | |||
| 34e6fb7b64 | |||
| bd15ac8b2d | |||
| 76e207cd20 | |||
| bd1916bdaa | |||
| 3dcaeb1d4f | |||
| f1fa6d2762 | |||
| bb4b9734aa | |||
| 78b0ee6f9b | |||
| 6d234ffb5b | |||
| be4f586613 | |||
| 02b8768f8e | |||
| 38be27a89c | |||
| cff5d9be29 | |||
| 11594e6dc7 | |||
| 44e8ce0105 | |||
| ea7ffaca5d | |||
| 898663344b | |||
| 15a889dfcf | |||
| 5442accb48 | |||
| b7d64b1f9e | |||
| aa849f591b | |||
| c3fcb83da2 | |||
| 0d75678ffd | |||
| d907f1ca01 | |||
| e42dd9cc6e | |||
| 14e4e79c43 | |||
| d83f31c3c2 | |||
| 6f47b12501 | |||
| 99cd9dd195 | |||
| 5fb62313d4 | |||
| 41aa40b237 | |||
| 1f5d4434be | |||
| 3d83100eda | |||
| 29860684cb | |||
| 4c6cce416d | |||
| 449386a906 | |||
| 3be4b4eb50 | |||
| f8af82d0a8 | |||
| 855f527a87 | |||
| 69c056a35f | |||
| 11e43e6a9b | |||
| 8b49ae373e | |||
| b084f13f0c | |||
| c616fe1154 | |||
| 89cb068db6 | |||
| c96ff65bc7 | |||
| 57b631ad72 | |||
| 7980efec50 | |||
| 79c1d2d361 | |||
| ba0646e768 | |||
| 58a9d72946 | |||
| f3ce52d247 | |||
| 08acee792b | |||
| 183bac752e | |||
| dc587029e1 | |||
| bb7cd71a07 | |||
| bb68f29d4d | |||
| 1b1ef80983 | |||
| eb99adafab | |||
| 96341185c0 | |||
| 07e7c43a2e | |||
| f1e50f7c38 | |||
| 288163aded | |||
| 4e37915516 | |||
| 53b13bc6a5 | |||
| ff27862bdd | |||
| 3eda49d468 | |||
| 62e891f594 | |||
| 2ed4d9d1d4 | |||
| 1beeb4ea6d | |||
| 48ee83a77e | |||
| f01b307865 | |||
| f315c920e7 | |||
| 79c169ef2a | |||
| ac6aa470af | |||
| e8263a8bb5 | |||
| 7c64447c9d | |||
| 2a728e0ee7 | |||
| 855e137376 | |||
| 074985a2ac | |||
| eedc8fe67f | |||
| c63bcb9246 | |||
| efd929b153 | |||
| a7ed13ae9a | |||
| 8ffc070622 | |||
| 9e67654272 | |||
| d81d2d89d4 | |||
| c1591099c6 | |||
| a84f906d43 | |||
| f6c1dc1cab | |||
| e448bac0d8 | |||
| 1c22561acc | |||
| e1ee5a89f0 | |||
| c75e97252c | |||
| 20ec16c3d1 | |||
| 36a039f72e | |||
| 21f5b17673 | |||
| d675eb96a6 | |||
| 4401692de0 | |||
| 85ffd61c16 | |||
| abbc8bf945 | |||
| 291762a49e | |||
| 05d2575544 | |||
| 83b2120ef5 | |||
| b0d99f0a86 | |||
| 80af069669 | |||
| 1dc71d5791 | |||
| abc5b8ff38 | |||
| 6dc61da519 | |||
| 52f3eb15a7 | |||
| 524b4b17c8 | |||
| c109344b07 | |||
| 15e480d26d | |||
| 807503c88f | |||
| d05d5c687c | |||
| 8b6aa4b502 | |||
| d586f8d9a6 | |||
| 4f72c53648 | |||
| 4bcce61829 | |||
| aebfe7dac6 | |||
| 2e45ff3561 | |||
| d3d7799812 | |||
| 984831eaff | |||
| ceb0f7c33e | |||
| 75b6e630fb | |||
| 70cca68f30 | |||
| 2a63ff827b | |||
| ce52c983a8 | |||
| cc81d18344 | |||
| c207329a3e | |||
| f4b0964e25 | |||
| 162f516647 | |||
| e459c0a4e5 | |||
| d5378f1f83 | |||
| 1d5471f463 | |||
| 673f1b8d58 | |||
| 85c7a18b1a | |||
| 6676d6314b | |||
| 8048d73551 | |||
| 88103c01eb | |||
| 06aa639ae4 | |||
| 7385fc1a7e | |||
| 3711fa75cf | |||
| 66feca3323 | |||
| 148619eb05 | |||
| 30a658b083 | |||
| 4f45bd2b76 | |||
| 5098332d20 | |||
| 335a01d448 | |||
| 61de673741 | |||
| 7ea5da8d0f | |||
| eb1eacdad9 | |||
| 3188409bac | |||
| cbc1f5a84d | |||
| 6139f12e0d | |||
| ce4efeaf2d | |||
| 7dcddba401 | |||
| 0bd894a61b | |||
| ab3437989a | |||
| 540fe100cf | |||
| b388f29df5 | |||
| b3f1295809 | |||
| 80a465fad8 | |||
| 00e7e7e01e | |||
| 43a28c9b2e | |||
| 06c775f563 | |||
| 2f9bad0f8f | |||
| ec9fae9e5a | |||
| 9efa596059 | |||
| 01914fcc1b | |||
| 33818033a4 | |||
| e655d9cecd | |||
| 94d61a6d52 | |||
| 830e5d3602 | |||
| ada3143ffb | |||
| 879a8da1f4 | |||
| 96a66f24e6 | |||
| f6aae59e72 | |||
| 9758c7b406 | |||
| bec94e4c6a | |||
| e71281dcee | |||
| 6626bd568d | |||
| cdb3131185 | |||
| 57c0f81263 | |||
| b40553cc54 | |||
| 62b29fb644 | |||
| 5555239fb3 | |||
| b2bc69f782 | |||
| eff2b8a0bb | |||
| f2d4107172 | |||
| 0911678db0 | |||
| 120aa12727 | |||
| f48bcdcd7b | |||
| 39b6ad28d0 | |||
| 2bd8b2b03a | |||
| 0d4d5227a0 | |||
| 07909550c3 | |||
| 4f7bffe6fe | |||
| f3590ebf7c | |||
| 8b1950fc54 | |||
| 9a61a309a7 | |||
| 542f941879 | |||
| c57ea6add6 | |||
| 0d949c7894 | |||
| f6accf0aa7 | |||
| 1ecf89a2b1 | |||
| 630d04fb46 | |||
| 8a00dffce0 | |||
| 423733967e | |||
| 38c6e01d9f | |||
| 566efb0d2c | |||
| 06725ee497 | |||
| 4df416a818 | |||
| 26fef320ef | |||
| ff1685a721 | |||
| 0baba63542 | |||
| 2c175ad1b2 | |||
| cd190132f9 | |||
| 0bab558c75 | |||
| af38afc5b5 | |||
| 96184e4853 | |||
| 46fb5de260 | |||
| ceed45e409 | |||
| 8d9aed0ee1 | |||
| 308e9629b5 | |||
| 778308940a | |||
| 5ee5e671e7 | |||
| 7f23d8efd8 | |||
| 639cdb4c1f | |||
| 3a4b1a7a56 | |||
| c103e9402a | |||
| a326c6ab3a | |||
| efbb97967a | |||
| 1c6c6e4a33 | |||
| 159b77334b | |||
| cae33c92c9 | |||
| cbdf3edd8d | |||
| 8723540b0d | |||
| 4f395a01d3 | |||
| b877d5f91b | |||
| 595531683b | |||
| 6989dd61f7 | |||
| 4ef7d410f4 | |||
| cacdb442ca | |||
| 9a70879778 | |||
| d5ef6469bd | |||
| f44ac5960c | |||
| 803b155f65 | |||
| a55d4817bd | |||
| da3dc1e663 | |||
| 9884a08e83 | |||
| cd463bd1d1 | |||
| ee5ebfe0b9 | |||
| 92ec684066 | |||
| 4dcce6238f | |||
| 98619a9082 | |||
| 334ee2f897 | |||
| 156ca348aa | |||
| 8cfa5eaa43 | |||
| d3c865a10f | |||
| 42686efbe7 | |||
| a1e6061579 | |||
| 2bda15d264 | |||
| 43c7148637 | |||
| 1a79f9dbd9 | |||
| 325d25034d | |||
| 4a0e092115 | |||
| 1ba3d9c3e9 | |||
| 61110da453 | |||
| 565d531376 | |||
| b465f4a75a | |||
| 813944fc23 | |||
| c8521ad1f6 | |||
| 0d849f5fcb | |||
| 8abfce0fa1 | |||
| acf5d1c2ea | |||
| a6c1eaf69f | |||
| 756bfb8478 | |||
| 1af63705ff | |||
| 9e02e1f99d | |||
| 05a4ecc654 | |||
| 847d8512e7 | |||
| 6b8bf96bec | |||
| 586a2f5fc1 | |||
| ff5d20421e | |||
| 8e68858489 | |||
| a6712f7c98 | |||
| 9993217ed1 | |||
| 5928c34b03 | |||
| 5817931099 | |||
| 024adba069 | |||
| c093f9d191 | |||
| 60658a2ef9 | |||
| 3633b8ee37 | |||
| 46ddd5659b | |||
| f9ab8f4050 | |||
| 4b6857958c | |||
| d9a22518da | |||
| 818bfd5b1c | |||
| fbf1f78d64 | |||
| 59424f067c | |||
| 869f381a1b | |||
| 988c33d07d | |||
| fc9984eb3a | |||
| ce4a6fcd67 | |||
| 60c2870123 | |||
| 1c15f02d34 | |||
| 0140ffaf5e | |||
| 2899633436 | |||
| 9812c0a122 | |||
| 947fe710a3 | |||
| a246263424 | |||
| f69b30b5ba | |||
| 928e4d0ca9 | |||
| 45a81d90df | |||
| 27ccfd2c72 | |||
| a61382486f | |||
| c67c4a70c4 | |||
| 53b59bd95f | |||
| 3a55c80ae2 | |||
| 34533b401c | |||
| ecf7110781 | |||
| d3a7f0636b | |||
| 13c91fe728 | |||
| d3c2c8f642 | |||
| a905b1f966 | |||
| 8dbf43b672 | |||
| ca15cfbd0b | |||
| 2cbc30de6f | |||
| 163c6232b8 | |||
| 3efbd9065a | |||
| 7fb9744847 | |||
| 06badd590c | |||
| e1f94cfb72 | |||
| 16932ad71c | |||
| 856628bce6 | |||
| 1e1f82cc2d | |||
| 0f92dbe61c | |||
| 42bfb2d8eb | |||
| f461bb7694 | |||
| da62213579 | |||
| c1282c613e | |||
| 782f97afcc | |||
| a75506b183 | |||
| 5d7714519a | |||
| 082573f6d9 | |||
| ffea7627cf | |||
| f9995505a8 | |||
| f31e76ac3a | |||
| 2458b3573f | |||
| 3c5f80f8b5 | |||
| eee6060e58 | |||
| b0f186dc4e | |||
| db3880a31a | |||
| 673bcb279a | |||
| 805ed8e9f4 | |||
| 51dbb10b45 | |||
| 516bf5dd7f | |||
| fc0a6eaa76 | |||
| 93a2d96c21 | |||
| c546e2cf3c | |||
| 1e4d0153b4 | |||
| d5c2ed86f7 | |||
| c70b172b08 | |||
| 6f965b1704 | |||
| 9cad48cb31 | |||
| 5a8d8fd5a9 | |||
| acd8fc8290 | |||
| c8265aebea | |||
| ab7df093c4 | |||
| 876c8774fa | |||
| 26f8d8f710 | |||
| 133fd1d892 | |||
| 60a860d9b5 | |||
| 725fe01b69 | |||
| 3b8aeb3b87 | |||
| 22d99ba39e | |||
| 5e4118acdd | |||
| 734c9ec8f3 | |||
| 4127c6d4fb | |||
| b71814369d | |||
| 1c76d8e63c | |||
| 7457abb173 | |||
| a349b1eb4f | |||
| 0bc0a59939 | |||
| 75963ce8b4 | |||
| db096e462c | |||
| 9846e91c2f | |||
| 98d14a3e34 | |||
| 4ded159c49 | |||
| baa06b60fb | |||
| c776100ed0 | |||
| 8f7cfe8362 | |||
| d915cce277 | |||
| d31478a858 | |||
| dc480f38b6 | |||
| 510ce73ecd | |||
| 91bc893001 | |||
| 269c5f4b59 | |||
| 013ae3c69c | |||
| de327850ae | |||
| 53000988d9 | |||
| 02beb31e43 | |||
| c27fd4cd2d | |||
| fc0caf2d00 | |||
| d01869fca8 | |||
| 1e952e008e | |||
| f9909a87aa | |||
| dc3c8a2b60 | |||
| eb4b8a8d9b | |||
| 101b8d3361 | |||
| 669f50de6c | |||
| 10c6e72d87 | |||
| d327277bac | |||
| d2da96eaa3 | |||
| e8b75956d0 | |||
| de1fe083d8 | |||
| de70c4ca80 | |||
| bc24f49476 | |||
| e139eb771c | |||
| 4cd4a9c7c4 | |||
| 26d0148525 | |||
| eca1cd380b | |||
| 28ff274107 | |||
| 491d502c40 | |||
| 7966173385 | |||
| 86cd55102c | |||
| 7a337482d4 | |||
| 1cbb8cbacf | |||
| 633d75b798 | |||
| ac9fadf922 | |||
| eddaae2d87 | |||
| 1269d3b838 | |||
| c1108314c1 | |||
| 0fd9db2357 | |||
| aa322a3234 | |||
| 34dfb334ec | |||
| f9d7c93d21 | |||
| 6114c96b14 | |||
| bb158c1353 | |||
| bf04b9c563 | |||
| 9fa1059301 | |||
| 0f7555907b | |||
| ca62d492ba | |||
| 44a0e10a94 | |||
| 3a0f3f75b4 | |||
| e2a15644ce | |||
| 129c0e4d25 | |||
| 2fe1aeb4f2 | |||
| d51ad2c4eb | |||
| 895f508c29 | |||
| e0750e755f | |||
| 491cbf15b6 | |||
| d7fafda78e | |||
| 092f3aa6bd | |||
| 281f3562ec | |||
| 7c162f157a | |||
| e4b02af524 | |||
| cd79725a27 | |||
| 88bca67745 | |||
| c0e0345faa | |||
| 34096f877a | |||
| 66ee33cdde | |||
| edf1de189b | |||
| d4edc66c2c | |||
| 6ef8573032 | |||
| e4a41d9126 | |||
| 39a2f19b0d | |||
| 73d3c6311a | |||
| aef8cce755 | |||
| 874ff01551 | |||
| d1419fdad1 | |||
| 85dd60c197 | |||
| 6791342879 | |||
| 423b2638aa | |||
| 99b8738c31 | |||
| 62b5e1bc57 | |||
| 5783fb1f2e | |||
| 5cbfbff4ac | |||
| 1cbea757d0 | |||
| fb8041c32e | |||
| 8f444bd917 | |||
| 8e69cda09b | |||
| b4b70d8e7c | |||
| 3924fd79d2 | |||
| 0d86e4c4f9 | |||
| 96d4ee7356 | |||
| c6e0854544 | |||
| 4e3ac183d4 | |||
| 436cb2c163 | |||
| ddb3b90788 | |||
| 6e2e419a1c | |||
| d5c3034758 | |||
| 0ccd5635e7 | |||
| 0495f40bef | |||
| 630798c89f | |||
| fa0eb73363 | |||
| 1a0b7288df | |||
| 2fc45b3ea0 | |||
| 22a3b8698c | |||
| fa661ff6b3 | |||
| bd09d07698 | |||
| 34d1eb9c71 | |||
| fe74e7d91b | |||
| 3167b6a20a | |||
| 6f6e835b0a | |||
| 497d768d4e | |||
| 9f5a142680 | |||
| f6c1f4219b | |||
| f5e7700809 | |||
| 05130052af | |||
| 291b0350e8 | |||
| 7aa06f595d | |||
| 3227414a92 | |||
| 12323382a5 | |||
| d62fc5d668 | |||
| 8822854040 | |||
| 61793838bb | |||
| 991cac18f2 | |||
| 57e856c71c | |||
| c41b99f29d | |||
| 9e092823e4 | |||
| 8a1e2384d1 | |||
| 8d777a3d50 | |||
| 3625db30ec | |||
| 1573cb2b1e | |||
| 537896503f | |||
| e792ed39c9 | |||
| cc636ce040 | |||
| c82a0e5e1c | |||
| b9772def05 | |||
| 0590fa0875 | |||
| cd36514e1c | |||
| 2dd31690e5 | |||
| 2721a3b2d4 | |||
| 5503c572f1 | |||
| 6ffc4f01d9 | |||
| 5182959881 | |||
| 36371f94e8 | |||
| 2b7bf12bc7 | |||
| ce3a013f86 | |||
| 987f8a0bec | |||
| 73678f0507 | |||
| 0d6357af26 | |||
| e863bea269 | |||
| 6d13d02efb | |||
| 6a5238d2bb | |||
| 76aa6631f3 | |||
| 4b413e0209 | |||
| 04f4ccbe03 | |||
| ef9105e286 | |||
| 68a5775717 | |||
| fb6e8a89c0 | |||
| 999738ed4b | |||
|
|
19401d27c0 | ||
| 465a531bf4 | |||
|
|
5da6b4ae99 | ||
| f63bda171f | |||
| 45da05c9a4 | |||
| 098bc97fa4 | |||
| d74d7abc90 | |||
| ff966418b2 | |||
| 7cc942b42f | |||
| dea4f7eddc | |||
| cb3d48d42c | |||
| 8b76434b41 | |||
| 2ed3ed4b45 | |||
| f400833213 | |||
|
|
832a0b9f29 | ||
|
|
677030f712 |
38
.gitea/ISSUE_TEMPLATE/bug_report.md
Normal file
38
.gitea/ISSUE_TEMPLATE/bug_report.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: Erstelle einen Bericht, um uns zu helfen, das Projekt zu verbessern.
|
||||
title: '[BUG] '
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Beschreibung**
|
||||
Eine klare und prägnante Beschreibung des Fehlers.
|
||||
|
||||
**Reproduktion**
|
||||
Schritte, um den Fehler zu reproduzieren:
|
||||
|
||||
Entweder:
|
||||
1. Gehe zu '...'
|
||||
2. Klicke auf '...'
|
||||
3. Scrolle runter zu '...'
|
||||
4. Siehe Fehler
|
||||
|
||||
Oder Link zur Seite
|
||||
|
||||
**Erwartetes Verhalten**
|
||||
Eine klare Beschreibung dessen, was du erwartet hast.
|
||||
|
||||
**Screenshots**
|
||||
Falls zutreffend, füge hier Screenshots oder Gifs hinzu, um das Problem zu verdeutlichen.
|
||||
|
||||
**Achtung: Achte bitte auf Datenschutz deiner Daten sowie der Daten deiner Kunden. Sollten ein Screenshot nur mit Daten möglich sein, schwärze diese bitte vor dem Upload.**
|
||||
|
||||
**Umgebung:**
|
||||
- Betriebssystem: [z.B. Windows, macOS, Linux]
|
||||
- Browser / Version (falls relevant): [z.B. Chrome 120]
|
||||
- Projekt-Version: [z.B. v1.0.2]
|
||||
|
||||
**Zusätzlicher Kontext**
|
||||
Füge hier alle anderen Informationen zum Problem hinzu.
|
||||
20
.gitea/ISSUE_TEMPLATE/feature_request.md
Normal file
20
.gitea/ISSUE_TEMPLATE/feature_request.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: ✨ Feature Request
|
||||
about: Schlage eine Idee für dieses Projekt vor.
|
||||
title: '[FEATURE] '
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Ist dein Feature-Wunsch mit einem Problem verbunden?**
|
||||
Eine klare Beschreibung des Problems (z.B. "Ich bin immer genervt, wenn...").
|
||||
|
||||
**Lösungsvorschlag**
|
||||
Eine klare Beschreibung dessen, was du dir wünschst und wie es funktionieren soll.
|
||||
|
||||
**Alternativen**
|
||||
Hast du über alternative Lösungen oder Workarounds nachgedacht?
|
||||
|
||||
**Zusätzlicher Kontext**
|
||||
Hier ist Platz für weitere Informationen, Skizzen oder Beispiele von anderen Tools.
|
||||
77
.gitea/workflows/build-push.yaml
Normal file
77
.gitea/workflows/build-push.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
name: Build and Push Docker Images
|
||||
run-name: Build Backend & Frontend by @${{ github.actor }}
|
||||
|
||||
on: [push]
|
||||
|
||||
env:
|
||||
# Passe dies an deine Registry an.
|
||||
# Wenn du die Gitea-interne Registry nutzt, ist es meist einfach der Hostname deiner Gitea-Instanz.
|
||||
# Beispiel: gitea.deine-domain.de
|
||||
REGISTRY_HOST: git.federspiel.tech
|
||||
# Der Name des Repos (z.B. user/repo)
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
ACTOR: flfeders
|
||||
|
||||
jobs:
|
||||
build-backend:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Log in to Docker Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ env.REGISTRY_HOST }}
|
||||
# Gitea stellt secrets.GITHUB_TOKEN automatisch bereit (wie GitLab CI_JOB_TOKEN)
|
||||
username: ${{ env.ACTOR }}
|
||||
password: ${{ vars.CI_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Backend
|
||||
id: meta-backend
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.REGISTRY_HOST }}/${{ env.IMAGE_NAME }}/backend
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Build and push Backend
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: ./backend # Hier wird der Ordner gewechselt (wie 'cd backend')
|
||||
push: true
|
||||
tags: ${{ steps.meta-backend.outputs.tags }}
|
||||
labels: ${{ steps.meta-backend.outputs.labels }}
|
||||
|
||||
build-frontend:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Log in to Docker Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ env.REGISTRY_HOST }}
|
||||
username: ${{ env.ACTOR }}
|
||||
password: ${{ vars.CI_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Frontend
|
||||
id: meta-frontend
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.REGISTRY_HOST }}/${{ env.IMAGE_NAME }}/frontend
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Build and push Frontend
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: ./frontend # Hier wird der Ordner gewechselt (wie 'cd frontend')
|
||||
push: true
|
||||
tags: ${{ steps.meta-frontend.outputs.tags }}
|
||||
labels: ${{ steps.meta-frontend.outputs.labels }}
|
||||
110
README.md
110
README.md
@@ -1 +1,109 @@
|
||||
TEST
|
||||
|
||||
|
||||
|
||||
# Docker Compose Setup
|
||||
|
||||
## ENV Vars
|
||||
|
||||
- DOMAIN
|
||||
- PDF_LICENSE
|
||||
- DB_PASS
|
||||
- DB_USER
|
||||
- CONTACT_EMAIL
|
||||
|
||||
## Docker Compose File
|
||||
~~~
|
||||
services:
|
||||
frontend:
|
||||
image: git.federspiel.tech/flfeders/fedeo/frontend:main
|
||||
restart: always
|
||||
environment:
|
||||
- NUXT_PUBLIC_API_BASE=https://${DOMAIN}/backend
|
||||
- NUXT_PUBLIC_PDF_LICENSE=${PDF_LICENSE}
|
||||
networks:
|
||||
- traefik
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik"
|
||||
- "traefik.port=3000"
|
||||
# Middlewares
|
||||
- "traefik.http.middlewares.fedeo-frontend-redirect-web-secure.redirectscheme.scheme=https"
|
||||
# Web Entrypoint
|
||||
- "traefik.http.routers.fedeo-frontend.middlewares=fedeo-frontend-redirect-web-secure"
|
||||
- "traefik.http.routers.fedeo-frontend.rule=Host(`${DOMAIN}`) && PathPrefix(`/`)"
|
||||
- "traefik.http.routers.fedeo-frontend.entrypoints=web"
|
||||
# Web Secure Entrypoint
|
||||
- "traefik.http.routers.fedeo-frontend-secure.rule=Host(`${DOMAIN}`) && PathPrefix(`/`)"
|
||||
- "traefik.http.routers.fedeo-frontend-secure.entrypoints=web-secured" #
|
||||
- "traefik.http.routers.fedeo-frontend-secure.tls.certresolver=mytlschallenge"
|
||||
backend:
|
||||
image: git.federspiel.tech/flfeders/fedeo/backend:main
|
||||
restart: always
|
||||
environment:
|
||||
- INFISICAL_CLIENT_ID=
|
||||
- INFISICAL_CLIENT_SECRET=
|
||||
- NODE_ENV=production
|
||||
networks:
|
||||
- traefik
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik"
|
||||
- "traefik.port=3100"
|
||||
# Middlewares
|
||||
- "traefik.http.middlewares.fedeo-backend-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.middlewares.fedeo-backend-strip.stripprefix.prefixes=/backend"
|
||||
# Web Entrypoint
|
||||
- "traefik.http.routers.fedeo-backend.middlewares=fedeo-backend-redirect-web-secure"
|
||||
- "traefik.http.routers.fedeo-backend.rule=Host(`${DOMAIN}`) && PathPrefix(`/backend`)"
|
||||
- "traefik.http.routers.fedeo-backend.entrypoints=web"
|
||||
# Web Secure Entrypoint
|
||||
- "traefik.http.routers.fedeo-backend-secure.rule=Host(`${DOMAIN}`) && PathPrefix(`/backend`)"
|
||||
- "traefik.http.routers.fedeo-backend-secure.entrypoints=web-secured" #
|
||||
- "traefik.http.routers.fedeo-backend-secure.tls.certresolver=mytlschallenge"
|
||||
- "traefik.http.routers.fedeo-backend-secure.middlewares=fedeo-backend-strip"
|
||||
# db:
|
||||
# image: postgres
|
||||
# restart: always
|
||||
# shm_size: 128mb
|
||||
# environment:
|
||||
# POSTGRES_PASSWORD:
|
||||
# POSTGRES_USER:
|
||||
# POSTGRES_DB:
|
||||
# volumes:
|
||||
# - ./pg-data:/var/lib/postgresql/data
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
traefik:
|
||||
image: traefik:v2.11
|
||||
restart: unless-stopped
|
||||
container_name: traefik
|
||||
command:
|
||||
- "--api.insecure=false"
|
||||
- "--api.dashboard=false"
|
||||
- "--api.debug=false"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--providers.docker.network=traefik"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.web-secured.address=:443"
|
||||
- "--accesslog=true"
|
||||
- "--accesslog.filepath=/logs/access.log"
|
||||
- "--accesslog.bufferingsize=5000"
|
||||
- "--accesslog.fields.defaultMode=keep"
|
||||
- "--accesslog.fields.headers.defaultMode=keep"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true" #
|
||||
- "--certificatesresolvers.mytlschallenge.acme.email=${CONTACT_EMAIL}"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
volumes:
|
||||
- "./traefik/letsencrypt:/letsencrypt" # <== Volume for certs (TLS)
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
- "./traefik/logs:/logs"
|
||||
networks:
|
||||
- traefik
|
||||
networks:
|
||||
traefik:
|
||||
external: false
|
||||
~~~
|
||||
5
backend/.gitignore
vendored
Normal file
5
backend/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
# Keep environment variables out of version control
|
||||
.env
|
||||
|
||||
/src/generated/prisma
|
||||
18
backend/.gitlab-ci.yml
Normal file
18
backend/.gitlab-ci.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
before_script:
|
||||
- docker info
|
||||
|
||||
stages:
|
||||
- build
|
||||
|
||||
build-backend:
|
||||
stage: build
|
||||
tags:
|
||||
- shell
|
||||
- docker-daemon
|
||||
variables:
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
|
||||
script:
|
||||
- echo $IMAGE_TAG
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
- docker build -t $IMAGE_TAG .
|
||||
- docker push $IMAGE_TAG
|
||||
3
backend/.secretlintrc.json
Normal file
3
backend/.secretlintrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"rules": []
|
||||
}
|
||||
20
backend/Dockerfile
Normal file
20
backend/Dockerfile
Normal file
@@ -0,0 +1,20 @@
|
||||
FROM node:20-alpine
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Package-Dateien
|
||||
COPY package*.json ./
|
||||
|
||||
# Dev + Prod Dependencies (für TS-Build nötig)
|
||||
RUN npm install
|
||||
|
||||
# Restlicher Sourcecode
|
||||
COPY . .
|
||||
|
||||
# TypeScript Build
|
||||
RUN npm run build
|
||||
|
||||
# Port freigeben
|
||||
EXPOSE 3100
|
||||
|
||||
# Start der App
|
||||
CMD ["node", "dist/src/index.js"]
|
||||
32
backend/TODO.md
Normal file
32
backend/TODO.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Projekt To-Do Liste
|
||||
|
||||
## ✅ Erledigt
|
||||
- JWT-basierte Authentifizierung mit Cookie
|
||||
- Prefix für Auth-Tabellen (`auth_users`, `auth_roles`, …)
|
||||
- `/me` liefert User + Rechte (via `auth_get_user_permissions`)
|
||||
- Basis-Seed für Standardrollen + Rechte eingespielt
|
||||
- Auth Middleware im Frontend korrigiert (Login-Redirects)
|
||||
- Nuxt API Plugin unterstützt JWT im Header
|
||||
- Login-Seite an Nuxt UI Pro (v2) anpassen
|
||||
- `usePermission()` Composable im Frontend vorbereitet
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Offene Punkte
|
||||
|
||||
### Backend
|
||||
- [ ] `/me` erweitern: Rollen + deren Rechte strukturiert zurückgeben (`{ role: "manager", permissions: [...] }`)
|
||||
- [ ] Loading Flag im Auth-Flow berücksichtigen (damit `me` nicht doppelt feuert)
|
||||
- [ ] Gemeinsames Schema für Entities (Backend stellt per Endpoint bereit)
|
||||
- [ ] Soft Delete vereinheitlichen (`archived = true` statt DELETE)
|
||||
- [ ] Swagger-Doku verbessern (Schemas, Beispiele)
|
||||
|
||||
### Frontend
|
||||
- [ ] Loading Flag in Middleware/Store einbauen
|
||||
- [ ] Einheitliches Laden des Schemas beim Start
|
||||
- [ ] Pinia-Store für Auth/User/Tenant konsolidieren
|
||||
- [ ] Composable `usePermission(key)` implementieren, um Rechte einfach im Template zu prüfen
|
||||
- [ ] Entity-Seiten schrittweise auf API-Routen umstellen
|
||||
- [ ] Page Guards für Routen einbauen (z. B. `/projects/create` nur bei `projects-create`)
|
||||
|
||||
---
|
||||
27
backend/db/index.ts
Normal file
27
backend/db/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// src/db/index.ts
|
||||
import { drizzle } from "drizzle-orm/node-postgres";
|
||||
import { Pool } from "pg";
|
||||
import * as schema from "./schema";
|
||||
import {secrets} from "../src/utils/secrets";
|
||||
|
||||
console.log("[DB INIT] 1. Suche Connection String...");
|
||||
|
||||
// Checken woher die URL kommt
|
||||
let connectionString = process.env.DATABASE_URL || secrets.DATABASE_URL;
|
||||
if (connectionString) {
|
||||
console.log("[DB INIT] -> Gefunden in process.env.DATABASE_URL");
|
||||
} else {
|
||||
console.error("[DB INIT] ❌ KEIN CONNECTION STRING GEFUNDEN! .env nicht geladen?");
|
||||
}
|
||||
|
||||
export const pool = new Pool({
|
||||
connectionString,
|
||||
max: 10,
|
||||
});
|
||||
|
||||
// TEST: Ist die DB wirklich da?
|
||||
pool.query('SELECT NOW()')
|
||||
.then(res => console.log(`[DB INIT] ✅ VERBINDUNG ERFOLGREICH! Zeit auf DB: ${res.rows[0].now}`))
|
||||
.catch(err => console.error(`[DB INIT] ❌ VERBINDUNGSFEHLER:`, err.message));
|
||||
|
||||
export const db = drizzle(pool, { schema });
|
||||
1312
backend/db/migrations/0000_brief_dark_beast.sql
Normal file
1312
backend/db/migrations/0000_brief_dark_beast.sql
Normal file
File diff suppressed because it is too large
Load Diff
32
backend/db/migrations/0001_medical_big_bertha.sql
Normal file
32
backend/db/migrations/0001_medical_big_bertha.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
CREATE TABLE "time_events" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"tenant_id" bigint NOT NULL,
|
||||
"user_id" uuid NOT NULL,
|
||||
"actor_type" text NOT NULL,
|
||||
"actor_user_id" uuid,
|
||||
"event_time" timestamp with time zone NOT NULL,
|
||||
"event_type" text NOT NULL,
|
||||
"source" text NOT NULL,
|
||||
"invalidates_event_id" uuid,
|
||||
"metadata" jsonb,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "time_events_actor_user_check" CHECK (
|
||||
(actor_type = 'system' AND actor_user_id IS NULL)
|
||||
OR
|
||||
(actor_type = 'user' AND actor_user_id IS NOT NULL)
|
||||
)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "bankstatements" DROP CONSTRAINT "bankstatements_incomingInvoice_incominginvoices_id_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "bankstatements" DROP CONSTRAINT "bankstatements_createdDocument_createddocuments_id_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "time_events" ADD CONSTRAINT "time_events_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "time_events" ADD CONSTRAINT "time_events_user_id_auth_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "time_events" ADD CONSTRAINT "time_events_actor_user_id_auth_users_id_fk" FOREIGN KEY ("actor_user_id") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "time_events" ADD CONSTRAINT "time_events_invalidates_event_id_time_events_id_fk" FOREIGN KEY ("invalidates_event_id") REFERENCES "public"."time_events"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "idx_time_events_tenant_user_time" ON "time_events" USING btree ("tenant_id","user_id","event_time");--> statement-breakpoint
|
||||
CREATE INDEX "idx_time_events_created_at" ON "time_events" USING btree ("created_at");--> statement-breakpoint
|
||||
CREATE INDEX "idx_time_events_invalidates" ON "time_events" USING btree ("invalidates_event_id");--> statement-breakpoint
|
||||
ALTER TABLE "bankstatements" DROP COLUMN "incomingInvoice";--> statement-breakpoint
|
||||
ALTER TABLE "bankstatements" DROP COLUMN "createdDocument";
|
||||
13
backend/db/migrations/0002_silent_christian_walker.sql
Normal file
13
backend/db/migrations/0002_silent_christian_walker.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
ALTER TABLE "time_events" RENAME TO "staff_time_events";--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" DROP CONSTRAINT "time_events_tenant_id_tenants_id_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" DROP CONSTRAINT "time_events_user_id_auth_users_id_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" DROP CONSTRAINT "time_events_actor_user_id_auth_users_id_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" DROP CONSTRAINT "time_events_invalidates_event_id_time_events_id_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_user_id_auth_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_actor_user_id_auth_users_id_fk" FOREIGN KEY ("actor_user_id") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_invalidates_event_id_staff_time_events_id_fk" FOREIGN KEY ("invalidates_event_id") REFERENCES "public"."staff_time_events"("id") ON DELETE no action ON UPDATE no action;
|
||||
2
backend/db/migrations/0003_woozy_adam_destine.sql
Normal file
2
backend/db/migrations/0003_woozy_adam_destine.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- No-op migration: Datei war im Journal referenziert, aber fehlte im Repository.
|
||||
SELECT 1;
|
||||
2
backend/db/migrations/0004_stormy_onslaught.sql
Normal file
2
backend/db/migrations/0004_stormy_onslaught.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- No-op migration: Datei war im Journal referenziert, aber fehlte im Repository.
|
||||
SELECT 1;
|
||||
123
backend/db/migrations/0005_green_shinobi_shaw.sql
Normal file
123
backend/db/migrations/0005_green_shinobi_shaw.sql
Normal file
@@ -0,0 +1,123 @@
|
||||
CREATE TABLE "m2m_api_keys" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"tenant_id" bigint NOT NULL,
|
||||
"user_id" uuid NOT NULL,
|
||||
"created_by" uuid,
|
||||
"name" text NOT NULL,
|
||||
"key_prefix" text NOT NULL,
|
||||
"key_hash" text NOT NULL,
|
||||
"active" boolean DEFAULT true NOT NULL,
|
||||
"last_used_at" timestamp with time zone,
|
||||
"expires_at" timestamp with time zone,
|
||||
CONSTRAINT "m2m_api_keys_key_hash_unique" UNIQUE("key_hash")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "staff_time_events" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"tenant_id" bigint NOT NULL,
|
||||
"user_id" uuid NOT NULL,
|
||||
"actor_type" text NOT NULL,
|
||||
"actor_user_id" uuid,
|
||||
"event_time" timestamp with time zone NOT NULL,
|
||||
"event_type" text NOT NULL,
|
||||
"source" text NOT NULL,
|
||||
"invalidates_event_id" uuid,
|
||||
"related_event_id" uuid,
|
||||
"metadata" jsonb,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "time_events_actor_user_check" CHECK (
|
||||
(actor_type = 'system' AND actor_user_id IS NULL)
|
||||
OR
|
||||
(actor_type = 'user' AND actor_user_id IS NOT NULL)
|
||||
)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "serialtypes" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "serialtypes_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"intervall" text,
|
||||
"icon" text,
|
||||
"tenant" bigint NOT NULL,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "serial_executions" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"execution_date" timestamp NOT NULL,
|
||||
"status" text DEFAULT 'draft',
|
||||
"created_by" text,
|
||||
"created_at" timestamp DEFAULT now(),
|
||||
"summary" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "public_links" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"token" text NOT NULL,
|
||||
"tenant" integer NOT NULL,
|
||||
"default_profile" uuid,
|
||||
"is_protected" boolean DEFAULT false NOT NULL,
|
||||
"pin_hash" text,
|
||||
"config" jsonb DEFAULT '{}'::jsonb,
|
||||
"name" text NOT NULL,
|
||||
"description" text,
|
||||
"active" boolean DEFAULT true NOT NULL,
|
||||
"created_at" timestamp DEFAULT now(),
|
||||
"updated_at" timestamp DEFAULT now(),
|
||||
CONSTRAINT "public_links_token_unique" UNIQUE("token")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "wiki_pages" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"tenant_id" bigint NOT NULL,
|
||||
"parent_id" uuid,
|
||||
"title" text NOT NULL,
|
||||
"content" jsonb,
|
||||
"is_folder" boolean DEFAULT false NOT NULL,
|
||||
"sort_order" integer DEFAULT 0 NOT NULL,
|
||||
"entity_type" text,
|
||||
"entity_id" bigint,
|
||||
"entity_uuid" uuid,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"created_by" uuid,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "time_events" DISABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
DROP TABLE "time_events" CASCADE;--> statement-breakpoint
|
||||
ALTER TABLE "projects" ALTER COLUMN "active_phase" SET DEFAULT 'Erstkontakt';--> statement-breakpoint
|
||||
ALTER TABLE "createddocuments" ADD COLUMN "serialexecution" uuid;--> statement-breakpoint
|
||||
ALTER TABLE "devices" ADD COLUMN "last_seen" timestamp with time zone;--> statement-breakpoint
|
||||
ALTER TABLE "devices" ADD COLUMN "last_debug_info" jsonb;--> statement-breakpoint
|
||||
ALTER TABLE "files" ADD COLUMN "size" bigint;--> statement-breakpoint
|
||||
ALTER TABLE "m2m_api_keys" ADD CONSTRAINT "m2m_api_keys_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "m2m_api_keys" ADD CONSTRAINT "m2m_api_keys_user_id_auth_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."auth_users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "m2m_api_keys" ADD CONSTRAINT "m2m_api_keys_created_by_auth_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."auth_users"("id") ON DELETE set null ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_user_id_auth_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_actor_user_id_auth_users_id_fk" FOREIGN KEY ("actor_user_id") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_invalidates_event_id_staff_time_events_id_fk" FOREIGN KEY ("invalidates_event_id") REFERENCES "public"."staff_time_events"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "staff_time_events" ADD CONSTRAINT "staff_time_events_related_event_id_staff_time_events_id_fk" FOREIGN KEY ("related_event_id") REFERENCES "public"."staff_time_events"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "serialtypes" ADD CONSTRAINT "serialtypes_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "serialtypes" ADD CONSTRAINT "serialtypes_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "serial_executions" ADD CONSTRAINT "serial_executions_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "public_links" ADD CONSTRAINT "public_links_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "public_links" ADD CONSTRAINT "public_links_default_profile_auth_profiles_id_fk" FOREIGN KEY ("default_profile") REFERENCES "public"."auth_profiles"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "wiki_pages" ADD CONSTRAINT "wiki_pages_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "wiki_pages" ADD CONSTRAINT "wiki_pages_parent_id_wiki_pages_id_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."wiki_pages"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "wiki_pages" ADD CONSTRAINT "wiki_pages_created_by_auth_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "wiki_pages" ADD CONSTRAINT "wiki_pages_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "idx_time_events_tenant_user_time" ON "staff_time_events" USING btree ("tenant_id","user_id","event_time");--> statement-breakpoint
|
||||
CREATE INDEX "idx_time_events_created_at" ON "staff_time_events" USING btree ("created_at");--> statement-breakpoint
|
||||
CREATE INDEX "idx_time_events_invalidates" ON "staff_time_events" USING btree ("invalidates_event_id");--> statement-breakpoint
|
||||
CREATE INDEX "wiki_pages_tenant_idx" ON "wiki_pages" USING btree ("tenant_id");--> statement-breakpoint
|
||||
CREATE INDEX "wiki_pages_parent_idx" ON "wiki_pages" USING btree ("parent_id");--> statement-breakpoint
|
||||
CREATE INDEX "wiki_pages_entity_int_idx" ON "wiki_pages" USING btree ("tenant_id","entity_type","entity_id");--> statement-breakpoint
|
||||
CREATE INDEX "wiki_pages_entity_uuid_idx" ON "wiki_pages" USING btree ("tenant_id","entity_type","entity_uuid");--> statement-breakpoint
|
||||
ALTER TABLE "createddocuments" ADD CONSTRAINT "createddocuments_serialexecution_serial_executions_id_fk" FOREIGN KEY ("serialexecution") REFERENCES "public"."serial_executions"("id") ON DELETE no action ON UPDATE no action;
|
||||
1
backend/db/migrations/0006_nifty_price_lock.sql
Normal file
1
backend/db/migrations/0006_nifty_price_lock.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "services" ADD COLUMN "priceUpdateLocked" boolean DEFAULT false NOT NULL;
|
||||
1
backend/db/migrations/0007_bright_default_tax_type.sql
Normal file
1
backend/db/migrations/0007_bright_default_tax_type.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "customers" ADD COLUMN "customTaxType" text;
|
||||
16
backend/db/migrations/0008_quick_contracttypes.sql
Normal file
16
backend/db/migrations/0008_quick_contracttypes.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
CREATE TABLE "contracttypes" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "contracttypes_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"description" text,
|
||||
"paymentType" text,
|
||||
"recurring" boolean DEFAULT false NOT NULL,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "contracttypes" ADD CONSTRAINT "contracttypes_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "contracttypes" ADD CONSTRAINT "contracttypes_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "contracts" ADD COLUMN "contracttype" bigint;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "contracts" ADD CONSTRAINT "contracts_contracttype_contracttypes_id_fk" FOREIGN KEY ("contracttype") REFERENCES "public"."contracttypes"("id") ON DELETE no action ON UPDATE no action;
|
||||
3
backend/db/migrations/0010_sudden_billing_interval.sql
Normal file
3
backend/db/migrations/0010_sudden_billing_interval.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "contracttypes" ADD COLUMN "billingInterval" text;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "contracts" ADD COLUMN "billingInterval" text;
|
||||
16
backend/db/migrations/0011_mighty_member_bankaccounts.sql
Normal file
16
backend/db/migrations/0011_mighty_member_bankaccounts.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
CREATE TABLE "entitybankaccounts" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "entitybankaccounts_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"iban_encrypted" jsonb NOT NULL,
|
||||
"bic_encrypted" jsonb NOT NULL,
|
||||
"bank_name_encrypted" jsonb NOT NULL,
|
||||
"description" text,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid,
|
||||
"archived" boolean DEFAULT false NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "entitybankaccounts" ADD CONSTRAINT "entitybankaccounts_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "entitybankaccounts" ADD CONSTRAINT "entitybankaccounts_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;
|
||||
73
backend/db/migrations/0012_shiny_customer_inventory.sql
Normal file
73
backend/db/migrations/0012_shiny_customer_inventory.sql
Normal file
@@ -0,0 +1,73 @@
|
||||
CREATE TABLE "customerspaces" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "customerspaces_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"type" text NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"customer" bigint NOT NULL,
|
||||
"spaceNumber" text NOT NULL,
|
||||
"parentSpace" bigint,
|
||||
"infoData" jsonb DEFAULT '{"zip":"","city":"","streetNumber":""}'::jsonb NOT NULL,
|
||||
"description" text,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "customerinventoryitems" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "customerinventoryitems_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"description" text,
|
||||
"tenant" bigint NOT NULL,
|
||||
"customer" bigint NOT NULL,
|
||||
"customerspace" bigint,
|
||||
"customerInventoryId" text NOT NULL,
|
||||
"serialNumber" text,
|
||||
"quantity" bigint DEFAULT 0 NOT NULL,
|
||||
"manufacturer" text,
|
||||
"manufacturerNumber" text,
|
||||
"purchaseDate" date,
|
||||
"purchasePrice" double precision DEFAULT 0,
|
||||
"currentValue" double precision,
|
||||
"product" bigint,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerspaces" ADD CONSTRAINT "customerspaces_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerspaces" ADD CONSTRAINT "customerspaces_customer_customers_id_fk" FOREIGN KEY ("customer") REFERENCES "public"."customers"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerspaces" ADD CONSTRAINT "customerspaces_parentSpace_customerspaces_id_fk" FOREIGN KEY ("parentSpace") REFERENCES "public"."customerspaces"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerspaces" ADD CONSTRAINT "customerspaces_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_customer_customers_id_fk" FOREIGN KEY ("customer") REFERENCES "public"."customers"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_customerspace_customerspaces_id_fk" FOREIGN KEY ("customerspace") REFERENCES "public"."customerspaces"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_product_products_id_fk" FOREIGN KEY ("product") REFERENCES "public"."products"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "customerinventoryitems_tenant_customerInventoryId_idx" ON "customerinventoryitems" USING btree ("tenant","customerInventoryId");
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD COLUMN "customerspace" bigint;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD COLUMN "customerinventoryitem" bigint;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD CONSTRAINT "historyitems_customerspace_customerspaces_id_fk" FOREIGN KEY ("customerspace") REFERENCES "public"."customerspaces"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD CONSTRAINT "historyitems_customerinventoryitem_customerinventoryitems_id_fk" FOREIGN KEY ("customerinventoryitem") REFERENCES "public"."customerinventoryitems"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "tenants" ALTER COLUMN "numberRanges" SET DEFAULT '{"vendors":{"prefix":"","suffix":"","nextNumber":10000},"customers":{"prefix":"","suffix":"","nextNumber":10000},"products":{"prefix":"AT-","suffix":"","nextNumber":1000},"quotes":{"prefix":"AN-","suffix":"","nextNumber":1000},"confirmationOrders":{"prefix":"AB-","suffix":"","nextNumber":1000},"invoices":{"prefix":"RE-","suffix":"","nextNumber":1000},"spaces":{"prefix":"LP-","suffix":"","nextNumber":1000},"customerspaces":{"prefix":"KLP-","suffix":"","nextNumber":1000},"inventoryitems":{"prefix":"IA-","suffix":"","nextNumber":1000},"customerinventoryitems":{"prefix":"KIA-","suffix":"","nextNumber":1000},"projects":{"prefix":"PRJ-","suffix":"","nextNumber":1000},"costcentres":{"prefix":"KST-","suffix":"","nextNumber":1000}}'::jsonb;
|
||||
--> statement-breakpoint
|
||||
UPDATE "tenants"
|
||||
SET "numberRanges" = COALESCE("numberRanges", '{}'::jsonb) || jsonb_build_object(
|
||||
'customerspaces', COALESCE("numberRanges"->'customerspaces', '{"prefix":"KLP-","suffix":"","nextNumber":1000}'::jsonb),
|
||||
'customerinventoryitems', COALESCE("numberRanges"->'customerinventoryitems', '{"prefix":"KIA-","suffix":"","nextNumber":1000}'::jsonb)
|
||||
);
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "customerinventoryitems" ADD COLUMN "vendor" bigint;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_vendor_vendors_id_fk" FOREIGN KEY ("vendor") REFERENCES "public"."vendors"("id") ON DELETE no action ON UPDATE no action;
|
||||
20
backend/db/migrations/0014_smart_memberrelations.sql
Normal file
20
backend/db/migrations/0014_smart_memberrelations.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
CREATE TABLE "memberrelations" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "memberrelations_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"type" text NOT NULL,
|
||||
"billingInterval" text NOT NULL,
|
||||
"billingAmount" double precision DEFAULT 0 NOT NULL,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customers" ADD COLUMN "memberrelation" bigint;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "memberrelations" ADD CONSTRAINT "memberrelations_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "memberrelations" ADD CONSTRAINT "memberrelations_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customers" ADD CONSTRAINT "customers_memberrelation_memberrelations_id_fk" FOREIGN KEY ("memberrelation") REFERENCES "public"."memberrelations"("id") ON DELETE no action ON UPDATE no action;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
ALTER TABLE "historyitems" ADD COLUMN "memberrelation" bigint;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD CONSTRAINT "historyitems_memberrelation_memberrelations_id_fk" FOREIGN KEY ("memberrelation") REFERENCES "public"."memberrelations"("id") ON DELETE no action ON UPDATE no action;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
ALTER TABLE "customers" ADD COLUMN IF NOT EXISTS "memberrelation" bigint;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'customers_memberrelation_memberrelations_id_fk'
|
||||
) THEN
|
||||
ALTER TABLE "customers"
|
||||
ADD CONSTRAINT "customers_memberrelation_memberrelations_id_fk"
|
||||
FOREIGN KEY ("memberrelation")
|
||||
REFERENCES "public"."memberrelations"("id")
|
||||
ON DELETE no action
|
||||
ON UPDATE no action;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
UPDATE "customers"
|
||||
SET "memberrelation" = ("infoData"->>'memberrelation')::bigint
|
||||
WHERE
|
||||
"memberrelation" IS NULL
|
||||
AND "type" = 'Mitglied'
|
||||
AND jsonb_typeof(COALESCE("infoData", '{}'::jsonb)) = 'object'
|
||||
AND COALESCE("infoData", '{}'::jsonb) ? 'memberrelation'
|
||||
AND ("infoData"->>'memberrelation') ~ '^[0-9]+$';
|
||||
|
||||
UPDATE "customers"
|
||||
SET "infoData" = COALESCE("infoData", '{}'::jsonb) - 'memberrelation'
|
||||
WHERE
|
||||
"type" = 'Mitglied'
|
||||
AND jsonb_typeof(COALESCE("infoData", '{}'::jsonb)) = 'object'
|
||||
AND COALESCE("infoData", '{}'::jsonb) ? 'memberrelation';
|
||||
108
backend/db/migrations/0017_slow_the_hood.sql
Normal file
108
backend/db/migrations/0017_slow_the_hood.sql
Normal file
@@ -0,0 +1,108 @@
|
||||
CREATE TABLE "contracttypes" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "contracttypes_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"description" text,
|
||||
"paymentType" text,
|
||||
"recurring" boolean DEFAULT false NOT NULL,
|
||||
"billingInterval" text,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "customerinventoryitems" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "customerinventoryitems_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"description" text,
|
||||
"tenant" bigint NOT NULL,
|
||||
"customer" bigint NOT NULL,
|
||||
"customerspace" bigint,
|
||||
"customerInventoryId" text NOT NULL,
|
||||
"serialNumber" text,
|
||||
"quantity" bigint DEFAULT 0 NOT NULL,
|
||||
"manufacturer" text,
|
||||
"manufacturerNumber" text,
|
||||
"purchaseDate" date,
|
||||
"purchasePrice" double precision DEFAULT 0,
|
||||
"currentValue" double precision,
|
||||
"product" bigint,
|
||||
"vendor" bigint,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "customerspaces" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "customerspaces_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"type" text NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"customer" bigint NOT NULL,
|
||||
"spaceNumber" text NOT NULL,
|
||||
"parentSpace" bigint,
|
||||
"infoData" jsonb DEFAULT '{"zip":"","city":"","streetNumber":""}'::jsonb NOT NULL,
|
||||
"description" text,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "entitybankaccounts" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "entitybankaccounts_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"iban_encrypted" jsonb NOT NULL,
|
||||
"bic_encrypted" jsonb NOT NULL,
|
||||
"bank_name_encrypted" jsonb NOT NULL,
|
||||
"description" text,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid,
|
||||
"archived" boolean DEFAULT false NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "memberrelations" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "memberrelations_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"tenant" bigint NOT NULL,
|
||||
"type" text NOT NULL,
|
||||
"billingInterval" text NOT NULL,
|
||||
"billingAmount" double precision DEFAULT 0 NOT NULL,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"updated_at" timestamp with time zone,
|
||||
"updated_by" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "tenants" ALTER COLUMN "numberRanges" SET DEFAULT '{"vendors":{"prefix":"","suffix":"","nextNumber":10000},"customers":{"prefix":"","suffix":"","nextNumber":10000},"products":{"prefix":"AT-","suffix":"","nextNumber":1000},"quotes":{"prefix":"AN-","suffix":"","nextNumber":1000},"confirmationOrders":{"prefix":"AB-","suffix":"","nextNumber":1000},"invoices":{"prefix":"RE-","suffix":"","nextNumber":1000},"spaces":{"prefix":"LP-","suffix":"","nextNumber":1000},"customerspaces":{"prefix":"KLP-","suffix":"","nextNumber":1000},"inventoryitems":{"prefix":"IA-","suffix":"","nextNumber":1000},"customerinventoryitems":{"prefix":"KIA-","suffix":"","nextNumber":1000},"projects":{"prefix":"PRJ-","suffix":"","nextNumber":1000},"costcentres":{"prefix":"KST-","suffix":"","nextNumber":1000}}'::jsonb;--> statement-breakpoint
|
||||
ALTER TABLE "contracts" ADD COLUMN "contracttype" bigint;--> statement-breakpoint
|
||||
ALTER TABLE "contracts" ADD COLUMN "billingInterval" text;--> statement-breakpoint
|
||||
ALTER TABLE "customers" ADD COLUMN "customTaxType" text;--> statement-breakpoint
|
||||
ALTER TABLE "customers" ADD COLUMN "memberrelation" bigint;--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD COLUMN "customerspace" bigint;--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD COLUMN "customerinventoryitem" bigint;--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD COLUMN "memberrelation" bigint;--> statement-breakpoint
|
||||
ALTER TABLE "services" ADD COLUMN "priceUpdateLocked" boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "contracttypes" ADD CONSTRAINT "contracttypes_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "contracttypes" ADD CONSTRAINT "contracttypes_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_customer_customers_id_fk" FOREIGN KEY ("customer") REFERENCES "public"."customers"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_customerspace_customerspaces_id_fk" FOREIGN KEY ("customerspace") REFERENCES "public"."customerspaces"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_product_products_id_fk" FOREIGN KEY ("product") REFERENCES "public"."products"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_vendor_vendors_id_fk" FOREIGN KEY ("vendor") REFERENCES "public"."vendors"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerinventoryitems" ADD CONSTRAINT "customerinventoryitems_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerspaces" ADD CONSTRAINT "customerspaces_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerspaces" ADD CONSTRAINT "customerspaces_customer_customers_id_fk" FOREIGN KEY ("customer") REFERENCES "public"."customers"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerspaces" ADD CONSTRAINT "customerspaces_parentSpace_customerspaces_id_fk" FOREIGN KEY ("parentSpace") REFERENCES "public"."customerspaces"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customerspaces" ADD CONSTRAINT "customerspaces_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "entitybankaccounts" ADD CONSTRAINT "entitybankaccounts_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "entitybankaccounts" ADD CONSTRAINT "entitybankaccounts_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "memberrelations" ADD CONSTRAINT "memberrelations_tenant_tenants_id_fk" FOREIGN KEY ("tenant") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "memberrelations" ADD CONSTRAINT "memberrelations_updated_by_auth_users_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "contracts" ADD CONSTRAINT "contracts_contracttype_contracttypes_id_fk" FOREIGN KEY ("contracttype") REFERENCES "public"."contracttypes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customers" ADD CONSTRAINT "customers_memberrelation_memberrelations_id_fk" FOREIGN KEY ("memberrelation") REFERENCES "public"."memberrelations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD CONSTRAINT "historyitems_customerspace_customerspaces_id_fk" FOREIGN KEY ("customerspace") REFERENCES "public"."customerspaces"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD CONSTRAINT "historyitems_customerinventoryitem_customerinventoryitems_id_fk" FOREIGN KEY ("customerinventoryitem") REFERENCES "public"."customerinventoryitems"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "historyitems" ADD CONSTRAINT "historyitems_memberrelation_memberrelations_id_fk" FOREIGN KEY ("memberrelation") REFERENCES "public"."memberrelations"("id") ON DELETE no action ON UPDATE no action;
|
||||
3
backend/db/migrations/0018_account_chart.sql
Normal file
3
backend/db/migrations/0018_account_chart.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "accounts" ADD COLUMN "accountChart" text DEFAULT 'skr03' NOT NULL;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "tenants" ADD COLUMN "accountChart" text DEFAULT 'skr03' NOT NULL;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "createddocuments"
|
||||
ALTER COLUMN "customSurchargePercentage" TYPE double precision
|
||||
USING "customSurchargePercentage"::double precision;
|
||||
9788
backend/db/migrations/meta/0000_snapshot.json
Normal file
9788
backend/db/migrations/meta/0000_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
9947
backend/db/migrations/meta/0001_snapshot.json
Normal file
9947
backend/db/migrations/meta/0001_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
139
backend/db/migrations/meta/_journal.json
Normal file
139
backend/db/migrations/meta/_journal.json
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1764947303113,
|
||||
"tag": "0000_brief_dark_beast",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "7",
|
||||
"when": 1765641431341,
|
||||
"tag": "0001_medical_big_bertha",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "7",
|
||||
"when": 1765642446738,
|
||||
"tag": "0002_silent_christian_walker",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"version": "7",
|
||||
"when": 1765716484200,
|
||||
"tag": "0003_woozy_adam_destine",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"version": "7",
|
||||
"when": 1765716877146,
|
||||
"tag": "0004_stormy_onslaught",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "7",
|
||||
"when": 1771096926109,
|
||||
"tag": "0005_green_shinobi_shaw",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "7",
|
||||
"when": 1772000000000,
|
||||
"tag": "0006_nifty_price_lock",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "7",
|
||||
"when": 1772000100000,
|
||||
"tag": "0007_bright_default_tax_type",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"version": "7",
|
||||
"when": 1773000000000,
|
||||
"tag": "0008_quick_contracttypes",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"version": "7",
|
||||
"when": 1773000100000,
|
||||
"tag": "0009_heavy_contract_contracttype",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"version": "7",
|
||||
"when": 1773000200000,
|
||||
"tag": "0010_sudden_billing_interval",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"version": "7",
|
||||
"when": 1773000300000,
|
||||
"tag": "0011_mighty_member_bankaccounts",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"version": "7",
|
||||
"when": 1773000400000,
|
||||
"tag": "0012_shiny_customer_inventory",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"version": "7",
|
||||
"when": 1773000500000,
|
||||
"tag": "0013_brisk_customer_inventory_vendor",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"version": "7",
|
||||
"when": 1773000600000,
|
||||
"tag": "0014_smart_memberrelations",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"version": "7",
|
||||
"when": 1773000700000,
|
||||
"tag": "0015_wise_memberrelation_history",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"version": "7",
|
||||
"when": 1773000800000,
|
||||
"tag": "0016_fix_memberrelation_column_usage",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"version": "7",
|
||||
"when": 1771704862789,
|
||||
"tag": "0017_slow_the_hood",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"version": "7",
|
||||
"when": 1773000900000,
|
||||
"tag": "0018_account_chart",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
25
backend/db/schema/accounts.ts
Normal file
25
backend/db/schema/accounts.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
export const accounts = pgTable("accounts", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
number: text("number").notNull(),
|
||||
label: text("label").notNull(),
|
||||
accountChart: text("accountChart").notNull().default("skr03"),
|
||||
|
||||
description: text("description"),
|
||||
})
|
||||
|
||||
export type Account = typeof accounts.$inferSelect
|
||||
export type NewAccount = typeof accounts.$inferInsert
|
||||
83
backend/db/schema/auth_profiles.ts
Normal file
83
backend/db/schema/auth_profiles.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
text,
|
||||
timestamp,
|
||||
date,
|
||||
boolean,
|
||||
bigint,
|
||||
doublePrecision,
|
||||
jsonb,
|
||||
} from "drizzle-orm/pg-core"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const authProfiles = pgTable("auth_profiles", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
user_id: uuid("user_id").references(() => authUsers.id),
|
||||
|
||||
tenant_id: bigint("tenant_id", { mode: "number" }).notNull(),
|
||||
|
||||
created_at: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
first_name: text("first_name").notNull(),
|
||||
last_name: text("last_name").notNull(),
|
||||
|
||||
full_name: text("full_name").generatedAlwaysAs(
|
||||
`((first_name || ' ') || last_name)`
|
||||
),
|
||||
|
||||
mobile_tel: text("mobile_tel"),
|
||||
fixed_tel: text("fixed_tel"),
|
||||
salutation: text("salutation"),
|
||||
employee_number: text("employee_number"),
|
||||
|
||||
weekly_working_hours: doublePrecision("weekly_working_hours").default(0),
|
||||
annual_paid_leave_days: bigint("annual_paid_leave_days", { mode: "number" }),
|
||||
|
||||
weekly_regular_working_hours: jsonb("weekly_regular_working_hours").default("{}"),
|
||||
|
||||
clothing_size_top: text("clothing_size_top"),
|
||||
clothing_size_bottom: text("clothing_size_bottom"),
|
||||
clothing_size_shoe: text("clothing_size_shoe"),
|
||||
|
||||
email_signature: text("email_signature").default("<p>Mit freundlichen Grüßen</p>"),
|
||||
|
||||
birthday: date("birthday"),
|
||||
entry_date: date("entry_date").defaultNow(),
|
||||
|
||||
automatic_hour_corrections: jsonb("automatic_hour_corrections").default("[]"),
|
||||
|
||||
recreation_days_compensation: boolean("recreation_days_compensation")
|
||||
.notNull()
|
||||
.default(true),
|
||||
|
||||
customer_for_portal: bigint("customer_for_portal", { mode: "number" }),
|
||||
|
||||
pinned_on_navigation: jsonb("pinned_on_navigation").notNull().default("[]"),
|
||||
|
||||
email: text("email"),
|
||||
token_id: text("token_id"),
|
||||
|
||||
weekly_working_days: doublePrecision("weekly_working_days"),
|
||||
|
||||
old_profile_id: uuid("old_profile_id"),
|
||||
temp_config: jsonb("temp_config"),
|
||||
|
||||
state_code: text("state_code").default("DE-NI"),
|
||||
|
||||
contract_type: text("contract_type"),
|
||||
position: text("position"),
|
||||
qualification: text("qualification"),
|
||||
|
||||
address_street: text("address_street"),
|
||||
address_zip: text("address_zip"),
|
||||
address_city: text("address_city"),
|
||||
|
||||
active: boolean("active").notNull().default(true),
|
||||
})
|
||||
|
||||
export type AuthProfile = typeof authProfiles.$inferSelect
|
||||
export type NewAuthProfile = typeof authProfiles.$inferInsert
|
||||
23
backend/db/schema/auth_role_permisssions.ts
Normal file
23
backend/db/schema/auth_role_permisssions.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { pgTable, uuid, text, timestamp } from "drizzle-orm/pg-core"
|
||||
import { authRoles } from "./auth_roles"
|
||||
|
||||
export const authRolePermissions = pgTable(
|
||||
"auth_role_permissions",
|
||||
{
|
||||
created_at: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
role_id: uuid("role_id")
|
||||
.notNull()
|
||||
.references(() => authRoles.id),
|
||||
|
||||
permission: text("permission").notNull(),
|
||||
},
|
||||
(table) => ({
|
||||
primaryKey: [table.role_id, table.permission],
|
||||
})
|
||||
)
|
||||
|
||||
export type AuthRolePermission = typeof authRolePermissions.$inferSelect
|
||||
export type NewAuthRolePermission = typeof authRolePermissions.$inferInsert
|
||||
19
backend/db/schema/auth_roles.ts
Normal file
19
backend/db/schema/auth_roles.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { pgTable, uuid, text, timestamp, bigint } from "drizzle-orm/pg-core"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const authRoles = pgTable("auth_roles", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
created_at: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
description: text("description"),
|
||||
|
||||
created_by: uuid("created_by").references(() => authUsers.id),
|
||||
tenant_id: bigint("tenant_id", {mode: "number"}),
|
||||
})
|
||||
|
||||
export type AuthRole = typeof authRoles.$inferSelect
|
||||
export type NewAuthRole = typeof authRoles.$inferInsert
|
||||
22
backend/db/schema/auth_tenant_users.ts
Normal file
22
backend/db/schema/auth_tenant_users.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { pgTable, uuid, bigint, timestamp } from "drizzle-orm/pg-core"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const authTenantUsers = pgTable(
|
||||
"auth_tenant_users",
|
||||
{
|
||||
created_at: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant_id: bigint("tenant_id", { mode: "number" }).notNull(),
|
||||
user_id: uuid("user_id").notNull(),
|
||||
|
||||
created_by: uuid("created_by").references(() => authUsers.id),
|
||||
},
|
||||
(table) => ({
|
||||
primaryKey: [table.tenant_id, table.user_id],
|
||||
})
|
||||
)
|
||||
|
||||
export type AuthTenantUser = typeof authTenantUsers.$inferSelect
|
||||
export type NewAuthTenantUser = typeof authTenantUsers.$inferInsert
|
||||
30
backend/db/schema/auth_user_roles.ts
Normal file
30
backend/db/schema/auth_user_roles.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { pgTable, uuid, bigint, timestamp } from "drizzle-orm/pg-core"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { authRoles } from "./auth_roles"
|
||||
|
||||
export const authUserRoles = pgTable(
|
||||
"auth_user_roles",
|
||||
{
|
||||
created_at: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
user_id: uuid("user_id")
|
||||
.notNull()
|
||||
.references(() => authUsers.id),
|
||||
|
||||
role_id: uuid("role_id")
|
||||
.notNull()
|
||||
.references(() => authRoles.id),
|
||||
|
||||
tenant_id: bigint("tenant_id", { mode: "number" }).notNull(),
|
||||
|
||||
created_by: uuid("created_by").references(() => authUsers.id),
|
||||
},
|
||||
(table) => ({
|
||||
primaryKey: [table.user_id, table.role_id, table.tenant_id],
|
||||
})
|
||||
)
|
||||
|
||||
export type AuthUserRole = typeof authUserRoles.$inferSelect
|
||||
export type NewAuthUserRole = typeof authUserRoles.$inferInsert
|
||||
22
backend/db/schema/auth_users.ts
Normal file
22
backend/db/schema/auth_users.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { pgTable, uuid, text, boolean, timestamp } from "drizzle-orm/pg-core"
|
||||
|
||||
export const authUsers = pgTable("auth_users", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
created_at: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
email: text("email").notNull(),
|
||||
passwordHash: text("password_hash").notNull(),
|
||||
|
||||
multiTenant: boolean("multi_tenant").notNull().default(true),
|
||||
must_change_password: boolean("must_change_password").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
|
||||
ported: boolean("ported").notNull().default(true),
|
||||
})
|
||||
|
||||
export type AuthUser = typeof authUsers.$inferSelect
|
||||
export type NewAuthUser = typeof authUsers.$inferInsert
|
||||
52
backend/db/schema/bankaccounts.ts
Normal file
52
backend/db/schema/bankaccounts.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
doublePrecision,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const bankaccounts = pgTable("bankaccounts", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name"),
|
||||
iban: text("iban").notNull(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
bankId: text("bankId").notNull(),
|
||||
ownerName: text("ownerName"),
|
||||
|
||||
accountId: text("accountId").notNull(),
|
||||
|
||||
balance: doublePrecision("balance"),
|
||||
|
||||
expired: boolean("expired").notNull().default(false),
|
||||
|
||||
datevNumber: text("datevNumber"),
|
||||
|
||||
syncedAt: timestamp("synced_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
})
|
||||
|
||||
export type BankAccount = typeof bankaccounts.$inferSelect
|
||||
export type NewBankAccount = typeof bankaccounts.$inferInsert
|
||||
30
backend/db/schema/bankrequisitions.ts
Normal file
30
backend/db/schema/bankrequisitions.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const bankrequisitions = pgTable("bankrequisitions", {
|
||||
id: uuid("id").primaryKey(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
institutionId: text("institutionId"),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" }).references(() => tenants.id),
|
||||
|
||||
status: text("status"),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type BankRequisition = typeof bankrequisitions.$inferSelect
|
||||
export type NewBankRequisition = typeof bankrequisitions.$inferInsert
|
||||
62
backend/db/schema/bankstatements.ts
Normal file
62
backend/db/schema/bankstatements.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
doublePrecision,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { bankaccounts } from "./bankaccounts"
|
||||
import { createddocuments } from "./createddocuments"
|
||||
import { tenants } from "./tenants"
|
||||
import { incominginvoices } from "./incominginvoices"
|
||||
import { contracts } from "./contracts"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const bankstatements = pgTable("bankstatements", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
account: bigint("account", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => bankaccounts.id),
|
||||
|
||||
date: text("date").notNull(),
|
||||
|
||||
credIban: text("credIban"),
|
||||
credName: text("credName"),
|
||||
|
||||
text: text("text"),
|
||||
amount: doublePrecision("amount").notNull(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
debIban: text("debIban"),
|
||||
debName: text("debName"),
|
||||
gocardlessId: text("gocardlessId"),
|
||||
currency: text("currency"),
|
||||
valueDate: text("valueDate"),
|
||||
|
||||
mandateId: text("mandateId"),
|
||||
|
||||
contract: bigint("contract", { mode: "number" }).references(
|
||||
() => contracts.id
|
||||
),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type BankStatement = typeof bankstatements.$inferSelect
|
||||
export type NewBankStatement = typeof bankstatements.$inferInsert
|
||||
27
backend/db/schema/checkexecutions.ts
Normal file
27
backend/db/schema/checkexecutions.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { checks } from "./checks"
|
||||
|
||||
export const checkexecutions = pgTable("checkexecutions", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
check: uuid("check").references(() => checks.id),
|
||||
|
||||
executedAt: timestamp("executed_at"),
|
||||
|
||||
// ❌ executed_by removed (was 0_profiles)
|
||||
|
||||
description: text("description"),
|
||||
})
|
||||
|
||||
export type CheckExecution = typeof checkexecutions.$inferSelect
|
||||
export type NewCheckExecution = typeof checkexecutions.$inferInsert
|
||||
52
backend/db/schema/checks.ts
Normal file
52
backend/db/schema/checks.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
bigint,
|
||||
boolean,
|
||||
jsonb,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { vehicles } from "./vehicles"
|
||||
import { inventoryitems } from "./inventoryitems"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const checks = pgTable("checks", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
vehicle: bigint("vehicle", { mode: "number" })
|
||||
.references(() => vehicles.id),
|
||||
|
||||
// ❌ profile removed (old 0_profiles reference)
|
||||
|
||||
inventoryItem: bigint("inventoryitem", { mode: "number" })
|
||||
.references(() => inventoryitems.id),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name"),
|
||||
type: text("type"),
|
||||
|
||||
distance: bigint("distance", { mode: "number" }).default(1),
|
||||
|
||||
distanceUnit: text("distanceUnit").default("days"),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type Check = typeof checks.$inferSelect
|
||||
export type NewCheck = typeof checks.$inferInsert
|
||||
32
backend/db/schema/citys.ts
Normal file
32
backend/db/schema/citys.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
text,
|
||||
jsonb,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
export const citys = pgTable("citys", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
name: text("name"),
|
||||
short: text("short"),
|
||||
long: text("long"),
|
||||
|
||||
geometry: jsonb("geometry"),
|
||||
|
||||
zip: bigint("zip", { mode: "number" }),
|
||||
|
||||
districtCode: bigint("districtCode", { mode: "number" }),
|
||||
|
||||
countryName: text("countryName"),
|
||||
countryCode: bigint("countryCode", { mode: "number" }),
|
||||
|
||||
districtName: text("districtName"),
|
||||
|
||||
geopoint: text("geopoint"),
|
||||
})
|
||||
|
||||
export type City = typeof citys.$inferSelect
|
||||
export type NewCity = typeof citys.$inferInsert
|
||||
66
backend/db/schema/contacts.ts
Normal file
66
backend/db/schema/contacts.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
text,
|
||||
timestamp,
|
||||
boolean,
|
||||
jsonb,
|
||||
date,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { customers } from "./customers"
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const contacts = pgTable(
|
||||
"contacts",
|
||||
{
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
firstName: text("firstName"),
|
||||
lastName: text("lastName"),
|
||||
email: text("email"),
|
||||
|
||||
customer: bigint("customer", { mode: "number" }).references(
|
||||
() => customers.id
|
||||
),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" }).notNull(),
|
||||
|
||||
phoneMobile: text("phoneMobile"),
|
||||
phoneHome: text("phoneHome"),
|
||||
|
||||
heroId: text("heroId"),
|
||||
role: text("role"),
|
||||
|
||||
fullName: text("fullName"),
|
||||
|
||||
salutation: text("salutation"),
|
||||
|
||||
vendor: bigint("vendor", { mode: "number" }), // vendors folgt separat
|
||||
|
||||
active: boolean("active").notNull().default(true),
|
||||
|
||||
birthday: date("birthday"),
|
||||
notes: text("notes"),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
title: text("title"),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
}
|
||||
)
|
||||
|
||||
export type Contact = typeof contacts.$inferSelect
|
||||
export type NewContact = typeof contacts.$inferInsert
|
||||
81
backend/db/schema/contracts.ts
Normal file
81
backend/db/schema/contracts.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
text,
|
||||
timestamp,
|
||||
boolean,
|
||||
jsonb,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { contacts } from "./contacts"
|
||||
import { contracttypes } from "./contracttypes"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const contracts = pgTable(
|
||||
"contracts",
|
||||
{
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" }).notNull(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
customer: bigint("customer", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => customers.id),
|
||||
|
||||
notes: text("notes"),
|
||||
|
||||
active: boolean("active").notNull().default(true),
|
||||
recurring: boolean("recurring").notNull().default(false),
|
||||
|
||||
rhythm: jsonb("rhythm"),
|
||||
|
||||
startDate: timestamp("startDate", { withTimezone: true }),
|
||||
endDate: timestamp("endDate", { withTimezone: true }),
|
||||
signDate: timestamp("signDate", { withTimezone: true }),
|
||||
|
||||
duration: text("duration"),
|
||||
|
||||
contact: bigint("contact", { mode: "number" }).references(
|
||||
() => contacts.id
|
||||
),
|
||||
contracttype: bigint("contracttype", { mode: "number" }).references(
|
||||
() => contracttypes.id
|
||||
),
|
||||
|
||||
bankingIban: text("bankingIban"),
|
||||
bankingBIC: text("bankingBIC"),
|
||||
bankingName: text("bankingName"),
|
||||
bankingOwner: text("bankingOwner"),
|
||||
sepaRef: text("sepaRef"),
|
||||
sepaDate: timestamp("sepaDate", { withTimezone: true }),
|
||||
|
||||
paymentType: text("paymentType"),
|
||||
billingInterval: text("billingInterval"),
|
||||
invoiceDispatch: text("invoiceDispatch"),
|
||||
|
||||
ownFields: jsonb("ownFields").notNull().default({}),
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
contractNumber: text("contractNumber"),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
}
|
||||
)
|
||||
|
||||
export type Contract = typeof contracts.$inferSelect
|
||||
export type NewContract = typeof contracts.$inferInsert
|
||||
40
backend/db/schema/contracttypes.ts
Normal file
40
backend/db/schema/contracttypes.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const contracttypes = pgTable("contracttypes", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
description: text("description"),
|
||||
|
||||
paymentType: text("paymentType"),
|
||||
recurring: boolean("recurring").notNull().default(false),
|
||||
billingInterval: text("billingInterval"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type ContractType = typeof contracttypes.$inferSelect
|
||||
export type NewContractType = typeof contracttypes.$inferInsert
|
||||
50
backend/db/schema/costcentres.ts
Normal file
50
backend/db/schema/costcentres.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
jsonb,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { inventoryitems } from "./inventoryitems"
|
||||
import { projects } from "./projects"
|
||||
import { vehicles } from "./vehicles"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const costcentres = pgTable("costcentres", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
number: text("number").notNull(),
|
||||
name: text("name").notNull(),
|
||||
|
||||
vehicle: bigint("vehicle", { mode: "number" }).references(() => vehicles.id),
|
||||
|
||||
project: bigint("project", { mode: "number" }).references(() => projects.id),
|
||||
|
||||
inventoryitem: bigint("inventoryitem", { mode: "number" }).references(
|
||||
() => inventoryitems.id
|
||||
),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type CostCentre = typeof costcentres.$inferSelect
|
||||
export type NewCostCentre = typeof costcentres.$inferInsert
|
||||
21
backend/db/schema/countrys.ts
Normal file
21
backend/db/schema/countrys.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
export const countrys = pgTable("countrys", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
})
|
||||
|
||||
export type Country = typeof countrys.$inferSelect
|
||||
export type NewCountry = typeof countrys.$inferInsert
|
||||
125
backend/db/schema/createddocuments.ts
Normal file
125
backend/db/schema/createddocuments.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
boolean,
|
||||
smallint,
|
||||
doublePrecision,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { contacts } from "./contacts"
|
||||
import { contracts } from "./contracts"
|
||||
import { letterheads } from "./letterheads"
|
||||
import { projects } from "./projects"
|
||||
import { plants } from "./plants"
|
||||
import { authUsers } from "./auth_users"
|
||||
import {serialExecutions} from "./serialexecutions";
|
||||
|
||||
export const createddocuments = pgTable("createddocuments", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
type: text("type").notNull().default("INVOICE"),
|
||||
|
||||
customer: bigint("customer", { mode: "number" }).references(
|
||||
() => customers.id
|
||||
),
|
||||
|
||||
contact: bigint("contact", { mode: "number" }).references(
|
||||
() => contacts.id
|
||||
),
|
||||
|
||||
address: jsonb("address"),
|
||||
project: bigint("project", { mode: "number" }).references(
|
||||
() => projects.id
|
||||
),
|
||||
|
||||
documentNumber: text("documentNumber"),
|
||||
documentDate: text("documentDate"),
|
||||
|
||||
state: text("state").notNull().default("Entwurf"),
|
||||
|
||||
info: jsonb("info"),
|
||||
|
||||
createdBy: uuid("createdBy").references(() => authUsers.id),
|
||||
|
||||
title: text("title"),
|
||||
description: text("description"),
|
||||
|
||||
startText: text("startText"),
|
||||
endText: text("endText"),
|
||||
|
||||
rows: jsonb("rows").default([]),
|
||||
|
||||
deliveryDateType: text("deliveryDateType"),
|
||||
paymentDays: smallint("paymentDays"),
|
||||
deliveryDate: text("deliveryDate"),
|
||||
|
||||
contactPerson: uuid("contactPerson"),
|
||||
|
||||
serialConfig: jsonb("serialConfig").default({}),
|
||||
|
||||
createddocument: bigint("linkedDocument", { mode: "number" }).references(
|
||||
() => createddocuments.id
|
||||
),
|
||||
|
||||
agriculture: jsonb("agriculture"),
|
||||
|
||||
letterhead: bigint("letterhead", { mode: "number" }).references(
|
||||
() => letterheads.id
|
||||
),
|
||||
|
||||
advanceInvoiceResolved: boolean("advanceInvoiceResolved")
|
||||
.notNull()
|
||||
.default(false),
|
||||
|
||||
usedAdvanceInvoices: jsonb("usedAdvanceInvoices").notNull().default([]),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
deliveryDateEnd: text("deliveryDateEnd"),
|
||||
|
||||
plant: bigint("plant", { mode: "number" }).references(() => plants.id),
|
||||
|
||||
taxType: text("taxType"),
|
||||
|
||||
customSurchargePercentage: doublePrecision("customSurchargePercentage")
|
||||
.notNull()
|
||||
.default(0),
|
||||
|
||||
report: jsonb("report").notNull().default({}),
|
||||
|
||||
availableInPortal: boolean("availableInPortal")
|
||||
.notNull()
|
||||
.default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
created_by: uuid("created_by").references(() => authUsers.id),
|
||||
|
||||
payment_type: text("payment_type").default("transfer"),
|
||||
|
||||
contract: bigint("contract", { mode: "number" }).references(
|
||||
() => contracts.id
|
||||
),
|
||||
|
||||
serialexecution: uuid("serialexecution").references(() => serialExecutions.id)
|
||||
})
|
||||
|
||||
export type CreatedDocument = typeof createddocuments.$inferSelect
|
||||
export type NewCreatedDocument = typeof createddocuments.$inferInsert
|
||||
43
backend/db/schema/createdletters.ts
Normal file
43
backend/db/schema/createdletters.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
bigint,
|
||||
text,
|
||||
jsonb,
|
||||
boolean,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { vendors } from "./vendors"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const createdletters = pgTable("createdletters", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" }).references(() => tenants.id),
|
||||
|
||||
customer: bigint("customer", { mode: "number" }).references(
|
||||
() => customers.id
|
||||
),
|
||||
|
||||
vendor: bigint("vendor", { mode: "number" }).references(() => vendors.id),
|
||||
|
||||
contentJson: jsonb("content_json").default([]),
|
||||
|
||||
contentText: text("content_text"),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
})
|
||||
|
||||
export type CreatedLetter = typeof createdletters.$inferSelect
|
||||
export type NewCreatedLetter = typeof createdletters.$inferInsert
|
||||
66
backend/db/schema/customerinventoryitems.ts
Normal file
66
backend/db/schema/customerinventoryitems.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
doublePrecision,
|
||||
uuid,
|
||||
date,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { customerspaces } from "./customerspaces"
|
||||
import { products } from "./products"
|
||||
import { vendors } from "./vendors"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const customerinventoryitems = pgTable("customerinventoryitems", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
customer: bigint("customer", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => customers.id),
|
||||
|
||||
customerspace: bigint("customerspace", { mode: "number" }).references(
|
||||
() => customerspaces.id
|
||||
),
|
||||
|
||||
customerInventoryId: text("customerInventoryId").notNull(),
|
||||
serialNumber: text("serialNumber"),
|
||||
|
||||
quantity: bigint("quantity", { mode: "number" }).notNull().default(0),
|
||||
|
||||
manufacturer: text("manufacturer"),
|
||||
manufacturerNumber: text("manufacturerNumber"),
|
||||
|
||||
purchaseDate: date("purchaseDate"),
|
||||
purchasePrice: doublePrecision("purchasePrice").default(0),
|
||||
currentValue: doublePrecision("currentValue"),
|
||||
|
||||
product: bigint("product", { mode: "number" }).references(() => products.id),
|
||||
vendor: bigint("vendor", { mode: "number" }).references(() => vendors.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type CustomerInventoryItem = typeof customerinventoryitems.$inferSelect
|
||||
export type NewCustomerInventoryItem = typeof customerinventoryitems.$inferInsert
|
||||
72
backend/db/schema/customers.ts
Normal file
72
backend/db/schema/customers.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
text,
|
||||
timestamp,
|
||||
boolean,
|
||||
jsonb,
|
||||
smallint,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { memberrelations } from "./memberrelations"
|
||||
|
||||
export const customers = pgTable(
|
||||
"customers",
|
||||
{
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
customerNumber: text("customerNumber").notNull(),
|
||||
name: text("name").notNull(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" }).notNull(),
|
||||
|
||||
infoData: jsonb("infoData").default({}),
|
||||
active: boolean("active").notNull().default(true),
|
||||
|
||||
notes: text("notes"),
|
||||
|
||||
type: text("type").default("Privat"),
|
||||
heroId: text("heroId"),
|
||||
|
||||
isCompany: boolean("isCompany").notNull().default(false),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
customPaymentDays: smallint("customPaymentDays"),
|
||||
|
||||
firstname: text("firstname"),
|
||||
lastname: text("lastname"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
customSurchargePercentage: smallint("customSurchargePercentage")
|
||||
.notNull()
|
||||
.default(0),
|
||||
|
||||
salutation: text("salutation"),
|
||||
title: text("title"),
|
||||
nameAddition: text("nameAddition"),
|
||||
|
||||
availableInPortal: boolean("availableInPortal")
|
||||
.notNull()
|
||||
.default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
customPaymentType: text("custom_payment_type"), // ENUM payment_types separat?
|
||||
customTaxType: text("customTaxType"),
|
||||
memberrelation: bigint("memberrelation", { mode: "number" }).references(() => memberrelations.id),
|
||||
}
|
||||
)
|
||||
|
||||
export type Customer = typeof customers.$inferSelect
|
||||
export type NewCustomer = typeof customers.$inferInsert
|
||||
54
backend/db/schema/customerspaces.ts
Normal file
54
backend/db/schema/customerspaces.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
jsonb,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const customerspaces = pgTable("customerspaces", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
type: text("type").notNull(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
customer: bigint("customer", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => customers.id),
|
||||
|
||||
space_number: text("spaceNumber").notNull(),
|
||||
|
||||
parentSpace: bigint("parentSpace", { mode: "number" }).references(
|
||||
() => customerspaces.id
|
||||
),
|
||||
|
||||
info_data: jsonb("infoData")
|
||||
.notNull()
|
||||
.default({ zip: "", city: "", streetNumber: "" }),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type CustomerSpace = typeof customerspaces.$inferSelect
|
||||
export type NewCustomerSpace = typeof customerspaces.$inferInsert
|
||||
34
backend/db/schema/devices.ts
Normal file
34
backend/db/schema/devices.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
bigint, jsonb,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
|
||||
export const devices = pgTable("devices", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
type: text("type").notNull(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" }).references(() => tenants.id),
|
||||
|
||||
password: text("password"),
|
||||
|
||||
externalId: text("externalId"),
|
||||
|
||||
lastSeen: timestamp("last_seen", { withTimezone: true }),
|
||||
|
||||
// Hier speichern wir den ganzen Payload (RSSI, Heap, IP, etc.)
|
||||
lastDebugInfo: jsonb("last_debug_info"),
|
||||
})
|
||||
|
||||
export type Device = typeof devices.$inferSelect
|
||||
export type NewDevice = typeof devices.$inferInsert
|
||||
28
backend/db/schema/documentboxes.ts
Normal file
28
backend/db/schema/documentboxes.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { pgTable, uuid, timestamp, text, boolean, bigint } from "drizzle-orm/pg-core"
|
||||
|
||||
import { spaces } from "./spaces"
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const documentboxes = pgTable("documentboxes", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
|
||||
space: bigint("space", { mode: "number" }).references(() => spaces.id),
|
||||
|
||||
key: text("key").notNull(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type DocumentBox = typeof documentboxes.$inferSelect
|
||||
export type NewDocumentBox = typeof documentboxes.$inferInsert
|
||||
39
backend/db/schema/entitybankaccounts.ts
Normal file
39
backend/db/schema/entitybankaccounts.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
jsonb,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const entitybankaccounts = pgTable("entitybankaccounts", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
ibanEncrypted: jsonb("iban_encrypted").notNull(),
|
||||
bicEncrypted: jsonb("bic_encrypted").notNull(),
|
||||
bankNameEncrypted: jsonb("bank_name_encrypted").notNull(),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
})
|
||||
|
||||
export type EntityBankAccount = typeof entitybankaccounts.$inferSelect
|
||||
export type NewEntityBankAccount = typeof entitybankaccounts.$inferInsert
|
||||
97
backend/db/schema/enums.ts
Normal file
97
backend/db/schema/enums.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { pgEnum } from "drizzle-orm/pg-core"
|
||||
|
||||
// public.textTemplatePositions
|
||||
export const textTemplatePositionsEnum = pgEnum("texttemplatepositions", [
|
||||
"startText",
|
||||
"endText",
|
||||
])
|
||||
|
||||
// public.folderFunctions
|
||||
export const folderFunctionsEnum = pgEnum("folderfunctions", [
|
||||
"none",
|
||||
"yearSubCategory",
|
||||
"incomingInvoices",
|
||||
"invoices",
|
||||
"quotes",
|
||||
"confirmationOrders",
|
||||
"deliveryNotes",
|
||||
"vehicleData",
|
||||
"reminders",
|
||||
"taxData",
|
||||
"deposit",
|
||||
"timeEvaluations",
|
||||
])
|
||||
|
||||
// public.locked_tenant
|
||||
export const lockedTenantEnum = pgEnum("locked_tenant", [
|
||||
"maintenance_tenant",
|
||||
"maintenance",
|
||||
"general",
|
||||
"no_subscription",
|
||||
])
|
||||
|
||||
// public.credential_types
|
||||
export const credentialTypesEnum = pgEnum("credential_types", [
|
||||
"mail",
|
||||
"m365",
|
||||
])
|
||||
|
||||
// public.payment_types
|
||||
export const paymentTypesEnum = pgEnum("payment_types", [
|
||||
"transfer",
|
||||
"direct_debit",
|
||||
])
|
||||
|
||||
// public.notification_status
|
||||
export const notificationStatusEnum = pgEnum("notification_status", [
|
||||
"queued",
|
||||
"sent",
|
||||
"failed",
|
||||
"read",
|
||||
])
|
||||
|
||||
// public.notification_channel
|
||||
export const notificationChannelEnum = pgEnum("notification_channel", [
|
||||
"email",
|
||||
"inapp",
|
||||
"sms",
|
||||
"push",
|
||||
"webhook",
|
||||
])
|
||||
|
||||
// public.notification_severity
|
||||
export const notificationSeverityEnum = pgEnum("notification_severity", [
|
||||
"info",
|
||||
"success",
|
||||
"warning",
|
||||
"error",
|
||||
])
|
||||
|
||||
// public.times_state
|
||||
export const timesStateEnum = pgEnum("times_state", [
|
||||
"submitted",
|
||||
"approved",
|
||||
"draft",
|
||||
])
|
||||
|
||||
export const helpdeskStatusEnum = [
|
||||
"open",
|
||||
"in_progress",
|
||||
"waiting_for_customer",
|
||||
"answered",
|
||||
"closed",
|
||||
] as const
|
||||
|
||||
export const helpdeskPriorityEnum = [
|
||||
"low",
|
||||
"normal",
|
||||
"high",
|
||||
] as const
|
||||
|
||||
export const helpdeskDirectionEnum = [
|
||||
"incoming",
|
||||
"outgoing",
|
||||
"internal",
|
||||
"system",
|
||||
] as const
|
||||
|
||||
60
backend/db/schema/events.ts
Normal file
60
backend/db/schema/events.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
text,
|
||||
timestamp,
|
||||
boolean,
|
||||
jsonb,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const events = pgTable(
|
||||
"events",
|
||||
{
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" }).notNull(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
startDate: timestamp("startDate", { withTimezone: true }).notNull(),
|
||||
endDate: timestamp("endDate", { withTimezone: true }),
|
||||
|
||||
eventtype: text("eventtype").default("Umsetzung"),
|
||||
|
||||
project: bigint("project", { mode: "number" }), // FK follows when projects.ts exists
|
||||
|
||||
resources: jsonb("resources").default([]),
|
||||
notes: text("notes"),
|
||||
link: text("link"),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
vehicles: jsonb("vehicles").notNull().default([]),
|
||||
inventoryitems: jsonb("inventoryitems").notNull().default([]),
|
||||
inventoryitemgroups: jsonb("inventoryitemgroups").notNull().default([]),
|
||||
|
||||
customer: bigint("customer", { mode: "number" }).references(
|
||||
() => customers.id
|
||||
),
|
||||
|
||||
vendor: bigint("vendor", { mode: "number" }), // will link once vendors.ts is created
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
}
|
||||
)
|
||||
|
||||
export type Event = typeof events.$inferSelect
|
||||
export type NewEvent = typeof events.$inferInsert
|
||||
80
backend/db/schema/files.ts
Normal file
80
backend/db/schema/files.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { projects } from "./projects"
|
||||
import { customers } from "./customers"
|
||||
import { contracts } from "./contracts"
|
||||
import { vendors } from "./vendors"
|
||||
import { incominginvoices } from "./incominginvoices"
|
||||
import { plants } from "./plants"
|
||||
import { createddocuments } from "./createddocuments"
|
||||
import { vehicles } from "./vehicles"
|
||||
import { products } from "./products"
|
||||
import { inventoryitems } from "./inventoryitems"
|
||||
import { folders } from "./folders"
|
||||
import { filetags } from "./filetags"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { authProfiles } from "./auth_profiles"
|
||||
import { spaces } from "./spaces"
|
||||
import { documentboxes } from "./documentboxes"
|
||||
import { checks } from "./checks"
|
||||
|
||||
export const files = pgTable("files", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
path: text("path"),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
project: bigint("project", { mode: "number" }).references(() => projects.id),
|
||||
customer: bigint("customer", { mode: "number" }).references(() => customers.id),
|
||||
contract: bigint("contract", { mode: "number" }).references(() => contracts.id),
|
||||
vendor: bigint("vendor", { mode: "number" }).references(() => vendors.id),
|
||||
incominginvoice: bigint("incominginvoice", { mode: "number" }).references(() => incominginvoices.id),
|
||||
plant: bigint("plant", { mode: "number" }).references(() => plants.id),
|
||||
createddocument: bigint("createddocument", { mode: "number" }).references(() => createddocuments.id),
|
||||
vehicle: bigint("vehicle", { mode: "number" }).references(() => vehicles.id),
|
||||
product: bigint("product", { mode: "number" }).references(() => products.id),
|
||||
|
||||
check: uuid("check").references(() => checks.id),
|
||||
|
||||
inventoryitem: bigint("inventoryitem", { mode: "number" }).references(() => inventoryitems.id),
|
||||
|
||||
folder: uuid("folder").references(() => folders.id),
|
||||
|
||||
mimeType: text("mimeType"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
space: bigint("space", { mode: "number" }).references(() => spaces.id),
|
||||
|
||||
type: uuid("type").references(() => filetags.id),
|
||||
|
||||
documentbox: uuid("documentbox").references(() => documentboxes.id),
|
||||
|
||||
name: text("name"),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
createdBy: uuid("created_by").references(() => authUsers.id),
|
||||
|
||||
authProfile: uuid("auth_profile").references(() => authProfiles.id),
|
||||
size: bigint("size", { mode: "number" }),
|
||||
})
|
||||
|
||||
export type File = typeof files.$inferSelect
|
||||
export type NewFile = typeof files.$inferInsert
|
||||
33
backend/db/schema/filetags.ts
Normal file
33
backend/db/schema/filetags.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
|
||||
export const filetags = pgTable("filetags", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
color: text("color"),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
createdDocumentType: text("createddocumenttype").default(""),
|
||||
incomingDocumentType: text("incomingDocumentType"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
})
|
||||
|
||||
export type FileTag = typeof filetags.$inferSelect
|
||||
export type NewFileTag = typeof filetags.$inferInsert
|
||||
51
backend/db/schema/folders.ts
Normal file
51
backend/db/schema/folders.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
integer,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { filetags } from "./filetags"
|
||||
import { folderFunctionsEnum } from "./enums"
|
||||
|
||||
export const folders = pgTable("folders", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
icon: text("icon"),
|
||||
|
||||
parent: uuid("parent").references(() => folders.id),
|
||||
|
||||
isSystemUsed: boolean("isSystemUsed").notNull().default(false),
|
||||
|
||||
function: folderFunctionsEnum("function"),
|
||||
|
||||
year: integer("year"),
|
||||
|
||||
standardFiletype: uuid("standardFiletype").references(() => filetags.id),
|
||||
|
||||
standardFiletypeIsOptional: boolean("standardFiletypeIsOptional")
|
||||
.notNull()
|
||||
.default(true),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
})
|
||||
|
||||
export type Folder = typeof folders.$inferSelect
|
||||
export type NewFolder = typeof folders.$inferInsert
|
||||
35
backend/db/schema/generatedexports.ts
Normal file
35
backend/db/schema/generatedexports.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
|
||||
export const generatedexports = pgTable("exports", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
startDate: timestamp("start_date", { withTimezone: true }).notNull(),
|
||||
endDate: timestamp("end_date", { withTimezone: true }).notNull(),
|
||||
|
||||
validUntil: timestamp("valid_until", { withTimezone: true }),
|
||||
|
||||
type: text("type").notNull().default("datev"),
|
||||
|
||||
url: text("url").notNull(),
|
||||
filePath: text("file_path"),
|
||||
})
|
||||
|
||||
export type Export = typeof generatedexports.$inferSelect
|
||||
export type NewExport = typeof generatedexports.$inferInsert
|
||||
22
backend/db/schema/globalmessages.ts
Normal file
22
backend/db/schema/globalmessages.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
export const globalmessages = pgTable("globalmessages", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
title: text("title"),
|
||||
description: text("description"),
|
||||
})
|
||||
|
||||
export type GlobalMessage = typeof globalmessages.$inferSelect
|
||||
export type NewGlobalMessage = typeof globalmessages.$inferInsert
|
||||
17
backend/db/schema/globalmessagesseen.ts
Normal file
17
backend/db/schema/globalmessagesseen.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import {
|
||||
pgTable,
|
||||
timestamp,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { globalmessages } from "./globalmessages"
|
||||
|
||||
export const globalmessagesseen = pgTable("globalmessagesseen", {
|
||||
message: bigint("message", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => globalmessages.id),
|
||||
|
||||
seenAt: timestamp("seen_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
})
|
||||
44
backend/db/schema/helpdesk_channel_instances.ts
Normal file
44
backend/db/schema/helpdesk_channel_instances.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
jsonb,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { helpdesk_channel_types } from "./helpdesk_channel_types"
|
||||
|
||||
export const helpdesk_channel_instances = pgTable("helpdesk_channel_instances", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade" }),
|
||||
|
||||
typeId: text("type_id")
|
||||
.notNull()
|
||||
.references(() => helpdesk_channel_types.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
isActive: boolean("is_active").notNull().default(true),
|
||||
|
||||
config: jsonb("config").notNull(),
|
||||
publicConfig: jsonb("public_config").notNull().default({}),
|
||||
|
||||
publicToken: text("public_token").unique(),
|
||||
secretToken: text("secret_token"),
|
||||
|
||||
createdBy: uuid("created_by").references(() => authUsers.id),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
||||
})
|
||||
|
||||
export type HelpdeskChannelInstance =
|
||||
typeof helpdesk_channel_instances.$inferSelect
|
||||
export type NewHelpdeskChannelInstance =
|
||||
typeof helpdesk_channel_instances.$inferInsert
|
||||
9
backend/db/schema/helpdesk_channel_types.ts
Normal file
9
backend/db/schema/helpdesk_channel_types.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { pgTable, text } from "drizzle-orm/pg-core"
|
||||
|
||||
export const helpdesk_channel_types = pgTable("helpdesk_channel_types", {
|
||||
id: text("id").primaryKey(),
|
||||
description: text("description").notNull(),
|
||||
})
|
||||
|
||||
export type HelpdeskChannelType = typeof helpdesk_channel_types.$inferSelect
|
||||
export type NewHelpdeskChannelType = typeof helpdesk_channel_types.$inferInsert
|
||||
45
backend/db/schema/helpdesk_contacts.ts
Normal file
45
backend/db/schema/helpdesk_contacts.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { contacts } from "./contacts"
|
||||
import { helpdesk_channel_instances } from "./helpdesk_channel_instances" // placeholder
|
||||
|
||||
export const helpdesk_contacts = pgTable("helpdesk_contacts", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade" }),
|
||||
|
||||
customerId: bigint("customer_id", { mode: "number" })
|
||||
.references(() => customers.id, { onDelete: "set null" }),
|
||||
|
||||
email: text("email"),
|
||||
phone: text("phone"),
|
||||
|
||||
externalRef: jsonb("external_ref"),
|
||||
displayName: text("display_name"),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
||||
|
||||
sourceChannelId: uuid("source_channel_id").references(
|
||||
() => helpdesk_channel_instances.id,
|
||||
{ onDelete: "set null" }
|
||||
),
|
||||
|
||||
contactId: bigint("contact_id", { mode: "number" }).references(
|
||||
() => contacts.id,
|
||||
{ onDelete: "set null" }
|
||||
),
|
||||
})
|
||||
|
||||
export type HelpdeskContact = typeof helpdesk_contacts.$inferSelect
|
||||
export type NewHelpdeskContact = typeof helpdesk_contacts.$inferInsert
|
||||
34
backend/db/schema/helpdesk_conversation_participants.ts
Normal file
34
backend/db/schema/helpdesk_conversation_participants.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
text,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { helpdesk_conversations } from "./helpdesk_conversations"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const helpdesk_conversation_participants = pgTable(
|
||||
"helpdesk_conversation_participants",
|
||||
{
|
||||
conversationId: uuid("conversation_id")
|
||||
.notNull()
|
||||
.references(() => helpdesk_conversations.id, { onDelete: "cascade" }),
|
||||
|
||||
userId: uuid("user_id")
|
||||
.notNull()
|
||||
.references(() => authUsers.id, { onDelete: "cascade" }),
|
||||
|
||||
role: text("role"),
|
||||
},
|
||||
(table) => ({
|
||||
pk: {
|
||||
name: "helpdesk_conversation_participants_pkey",
|
||||
columns: [table.conversationId, table.userId],
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
export type HelpdeskConversationParticipant =
|
||||
typeof helpdesk_conversation_participants.$inferSelect
|
||||
export type NewHelpdeskConversationParticipant =
|
||||
typeof helpdesk_conversation_participants.$inferInsert
|
||||
59
backend/db/schema/helpdesk_conversations.ts
Normal file
59
backend/db/schema/helpdesk_conversations.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { helpdesk_contacts } from "./helpdesk_contacts"
|
||||
import { contacts } from "./contacts"
|
||||
import { customers } from "./customers"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { helpdesk_channel_instances } from "./helpdesk_channel_instances"
|
||||
|
||||
export const helpdesk_conversations = pgTable("helpdesk_conversations", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade" }),
|
||||
|
||||
channelInstanceId: uuid("channel_instance_id")
|
||||
.notNull()
|
||||
.references(() => helpdesk_channel_instances.id, { onDelete: "cascade" }),
|
||||
|
||||
contactId: uuid("contact_id").references(() => helpdesk_contacts.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
|
||||
subject: text("subject"),
|
||||
|
||||
status: text("status").notNull().default("open"),
|
||||
|
||||
priority: text("priority").default("normal"),
|
||||
|
||||
assigneeUserId: uuid("assignee_user_id").references(() => authUsers.id),
|
||||
|
||||
lastMessageAt: timestamp("last_message_at", { withTimezone: true }),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
||||
|
||||
customerId: bigint("customer_id", { mode: "number" }).references(
|
||||
() => customers.id,
|
||||
{ onDelete: "set null" }
|
||||
),
|
||||
|
||||
contactPersonId: bigint("contact_person_id", { mode: "number" }).references(
|
||||
() => contacts.id,
|
||||
{ onDelete: "set null" }
|
||||
),
|
||||
|
||||
ticketNumber: text("ticket_number"),
|
||||
})
|
||||
|
||||
export type HelpdeskConversation =
|
||||
typeof helpdesk_conversations.$inferSelect
|
||||
export type NewHelpdeskConversation =
|
||||
typeof helpdesk_conversations.$inferInsert
|
||||
46
backend/db/schema/helpdesk_messages.ts
Normal file
46
backend/db/schema/helpdesk_messages.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { helpdesk_contacts } from "./helpdesk_contacts"
|
||||
import { helpdesk_conversations } from "./helpdesk_conversations"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const helpdesk_messages = pgTable("helpdesk_messages", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade" }),
|
||||
|
||||
conversationId: uuid("conversation_id")
|
||||
.notNull()
|
||||
.references(() => helpdesk_conversations.id, { onDelete: "cascade" }),
|
||||
|
||||
direction: text("direction").notNull(),
|
||||
|
||||
authorUserId: uuid("author_user_id").references(() => authUsers.id),
|
||||
|
||||
payload: jsonb("payload").notNull(),
|
||||
|
||||
rawMeta: jsonb("raw_meta"),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
||||
|
||||
contactId: uuid("contact_id").references(() => helpdesk_contacts.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
|
||||
externalMessageId: text("external_message_id").unique(),
|
||||
|
||||
receivedAt: timestamp("received_at", { withTimezone: true }).defaultNow(),
|
||||
})
|
||||
|
||||
export type HelpdeskMessage = typeof helpdesk_messages.$inferSelect
|
||||
export type NewHelpdeskMessage = typeof helpdesk_messages.$inferInsert
|
||||
33
backend/db/schema/helpdesk_routing_rules.ts
Normal file
33
backend/db/schema/helpdesk_routing_rules.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const helpdesk_routing_rules = pgTable("helpdesk_routing_rules", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade" }),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
condition: jsonb("condition").notNull(),
|
||||
action: jsonb("action").notNull(),
|
||||
|
||||
createdBy: uuid("created_by").references(() => authUsers.id),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
||||
})
|
||||
|
||||
export type HelpdeskRoutingRule =
|
||||
typeof helpdesk_routing_rules.$inferSelect
|
||||
export type NewHelpdeskRoutingRule =
|
||||
typeof helpdesk_routing_rules.$inferInsert
|
||||
149
backend/db/schema/historyitems.ts
Normal file
149
backend/db/schema/historyitems.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { vendors } from "./vendors"
|
||||
import { projects } from "./projects"
|
||||
import { plants } from "./plants"
|
||||
import { incominginvoices } from "./incominginvoices"
|
||||
import { contacts } from "./contacts"
|
||||
import { inventoryitems } from "./inventoryitems"
|
||||
import { products } from "./products"
|
||||
import { tasks } from "./tasks"
|
||||
import { vehicles } from "./vehicles"
|
||||
import { bankstatements } from "./bankstatements"
|
||||
import { spaces } from "./spaces"
|
||||
import { customerspaces } from "./customerspaces"
|
||||
import { customerinventoryitems } from "./customerinventoryitems"
|
||||
import { costcentres } from "./costcentres"
|
||||
import { ownaccounts } from "./ownaccounts"
|
||||
import { createddocuments } from "./createddocuments"
|
||||
import { documentboxes } from "./documentboxes"
|
||||
import { hourrates } from "./hourrates"
|
||||
import { projecttypes } from "./projecttypes"
|
||||
import { checks } from "./checks"
|
||||
import { services } from "./services"
|
||||
import { events } from "./events"
|
||||
import { inventoryitemgroups } from "./inventoryitemgroups"
|
||||
import { authUsers } from "./auth_users"
|
||||
import {files} from "./files";
|
||||
import { memberrelations } from "./memberrelations";
|
||||
|
||||
export const historyitems = pgTable("historyitems", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
text: text("text").notNull(),
|
||||
|
||||
customer: bigint("customer", { mode: "number" }).references(
|
||||
() => customers.id,
|
||||
{ onDelete: "cascade" }
|
||||
),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
vendor: bigint("vendor", { mode: "number" }).references(() => vendors.id),
|
||||
|
||||
project: bigint("project", { mode: "number" }).references(
|
||||
() => projects.id,
|
||||
{ onDelete: "cascade" }
|
||||
),
|
||||
|
||||
plant: bigint("plant", { mode: "number" }).references(
|
||||
() => plants.id,
|
||||
{ onDelete: "cascade" }
|
||||
),
|
||||
|
||||
incomingInvoice: bigint("incomingInvoice", { mode: "number" }).references(
|
||||
() => incominginvoices.id,
|
||||
{ onDelete: "cascade" }
|
||||
),
|
||||
|
||||
contact: bigint("contact", { mode: "number" }).references(() => contacts.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
|
||||
inventoryitem: bigint("inventoryitem", { mode: "number" }).references(
|
||||
() => inventoryitems.id,
|
||||
{ onDelete: "cascade" }
|
||||
),
|
||||
|
||||
product: bigint("product", { mode: "number" }).references(
|
||||
() => products.id,
|
||||
{ onDelete: "cascade" }
|
||||
),
|
||||
|
||||
event: bigint("event", { mode: "number" }).references(() => events.id),
|
||||
|
||||
newVal: text("newVal"),
|
||||
oldVal: text("oldVal"),
|
||||
|
||||
task: bigint("task", { mode: "number" }).references(() => tasks.id),
|
||||
|
||||
vehicle: bigint("vehicle", { mode: "number" }).references(() => vehicles.id),
|
||||
|
||||
bankstatement: bigint("bankstatement", { mode: "number" }).references(
|
||||
() => bankstatements.id
|
||||
),
|
||||
|
||||
space: bigint("space", { mode: "number" }).references(() => spaces.id),
|
||||
|
||||
customerspace: bigint("customerspace", { mode: "number" }).references(() => customerspaces.id),
|
||||
|
||||
customerinventoryitem: bigint("customerinventoryitem", { mode: "number" }).references(() => customerinventoryitems.id),
|
||||
|
||||
memberrelation: bigint("memberrelation", { mode: "number" }).references(() => memberrelations.id),
|
||||
|
||||
config: jsonb("config"),
|
||||
|
||||
projecttype: bigint("projecttype", { mode: "number" }).references(
|
||||
() => projecttypes.id
|
||||
),
|
||||
|
||||
check: uuid("check").references(() => checks.id),
|
||||
|
||||
service: bigint("service", { mode: "number" }).references(
|
||||
() => services.id
|
||||
),
|
||||
|
||||
createddocument: bigint("createddocument", { mode: "number" }).references(
|
||||
() => createddocuments.id
|
||||
),
|
||||
|
||||
file: uuid("file").references(() => files.id),
|
||||
|
||||
inventoryitemgroup: uuid("inventoryitemgroup").references(
|
||||
() => inventoryitemgroups.id
|
||||
),
|
||||
|
||||
source: text("source").default("Software"),
|
||||
|
||||
costcentre: uuid("costcentre").references(() => costcentres.id),
|
||||
|
||||
ownaccount: uuid("ownaccount").references(() => ownaccounts.id),
|
||||
|
||||
documentbox: uuid("documentbox").references(() => documentboxes.id),
|
||||
|
||||
hourrate: uuid("hourrate").references(() => hourrates.id),
|
||||
|
||||
createdBy: uuid("created_by").references(() => authUsers.id),
|
||||
|
||||
action: text("action"),
|
||||
})
|
||||
|
||||
export type HistoryItem = typeof historyitems.$inferSelect
|
||||
export type NewHistoryItem = typeof historyitems.$inferInsert
|
||||
18
backend/db/schema/holidays.ts
Normal file
18
backend/db/schema/holidays.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { pgTable, bigint, date, text, timestamp } from "drizzle-orm/pg-core"
|
||||
|
||||
export const holidays = pgTable("holidays", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedAlwaysAsIdentity(),
|
||||
|
||||
date: date("date").notNull(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
state_code: text("state_code").notNull(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
||||
})
|
||||
|
||||
export type Holiday = typeof holidays.$inferSelect
|
||||
export type NewHoliday = typeof holidays.$inferInsert
|
||||
27
backend/db/schema/hourrates.ts
Normal file
27
backend/db/schema/hourrates.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { pgTable, uuid, timestamp, text, boolean, bigint, doublePrecision } from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const hourrates = pgTable("hourrates", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
purchase_price: doublePrecision("purchasePrice").notNull(),
|
||||
sellingPrice: doublePrecision("sellingPrice").notNull(),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type HourRate = typeof hourrates.$inferSelect
|
||||
export type NewHourRate = typeof hourrates.$inferInsert
|
||||
63
backend/db/schema/incominginvoices.ts
Normal file
63
backend/db/schema/incominginvoices.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
jsonb,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { vendors } from "./vendors"
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const incominginvoices = pgTable("incominginvoices", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
state: text("state").notNull().default("Entwurf"),
|
||||
|
||||
vendor: bigint("vendor", { mode: "number" }).references(() => vendors.id),
|
||||
|
||||
reference: text("reference"),
|
||||
date: text("date"),
|
||||
|
||||
document: bigint("document", { mode: "number" }),
|
||||
|
||||
dueDate: text("dueDate"),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
paymentType: text("paymentType"),
|
||||
|
||||
accounts: jsonb("accounts").notNull().default([
|
||||
{
|
||||
account: null,
|
||||
taxType: null,
|
||||
amountNet: null,
|
||||
amountTax: 19,
|
||||
costCentre: null,
|
||||
},
|
||||
]),
|
||||
|
||||
paid: boolean("paid").notNull().default(false),
|
||||
expense: boolean("expense").notNull().default(true),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
})
|
||||
|
||||
export type IncomingInvoice = typeof incominginvoices.$inferSelect
|
||||
export type NewIncomingInvoice = typeof incominginvoices.$inferInsert
|
||||
81
backend/db/schema/index.ts
Normal file
81
backend/db/schema/index.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
export * from "./accounts"
|
||||
export * from "./auth_profiles"
|
||||
export * from "./auth_role_permisssions"
|
||||
export * from "./auth_roles"
|
||||
export * from "./auth_tenant_users"
|
||||
export * from "./auth_user_roles"
|
||||
export * from "./auth_users"
|
||||
export * from "./bankaccounts"
|
||||
export * from "./bankrequisitions"
|
||||
export * from "./bankstatements"
|
||||
export * from "./checkexecutions"
|
||||
export * from "./checks"
|
||||
export * from "./citys"
|
||||
export * from "./contacts"
|
||||
export * from "./contracts"
|
||||
export * from "./contracttypes"
|
||||
export * from "./costcentres"
|
||||
export * from "./countrys"
|
||||
export * from "./createddocuments"
|
||||
export * from "./createdletters"
|
||||
export * from "./customers"
|
||||
export * from "./customerspaces"
|
||||
export * from "./customerinventoryitems"
|
||||
export * from "./devices"
|
||||
export * from "./documentboxes"
|
||||
export * from "./enums"
|
||||
export * from "./events"
|
||||
export * from "./entitybankaccounts"
|
||||
export * from "./files"
|
||||
export * from "./filetags"
|
||||
export * from "./folders"
|
||||
export * from "./generatedexports"
|
||||
export * from "./globalmessages"
|
||||
export * from "./globalmessagesseen"
|
||||
export * from "./helpdesk_channel_instances"
|
||||
export * from "./helpdesk_channel_types"
|
||||
export * from "./helpdesk_contacts"
|
||||
export * from "./helpdesk_conversation_participants"
|
||||
export * from "./helpdesk_conversations"
|
||||
export * from "./helpdesk_messages"
|
||||
export * from "./helpdesk_routing_rules"
|
||||
export * from "./historyitems"
|
||||
export * from "./holidays"
|
||||
export * from "./hourrates"
|
||||
export * from "./incominginvoices"
|
||||
export * from "./inventoryitemgroups"
|
||||
export * from "./inventoryitems"
|
||||
export * from "./letterheads"
|
||||
export * from "./memberrelations"
|
||||
export * from "./movements"
|
||||
export * from "./m2m_api_keys"
|
||||
export * from "./notifications_event_types"
|
||||
export * from "./notifications_items"
|
||||
export * from "./notifications_preferences"
|
||||
export * from "./notifications_preferences_defaults"
|
||||
export * from "./ownaccounts"
|
||||
export * from "./plants"
|
||||
export * from "./productcategories"
|
||||
export * from "./products"
|
||||
export * from "./projects"
|
||||
export * from "./projecttypes"
|
||||
export * from "./servicecategories"
|
||||
export * from "./services"
|
||||
export * from "./spaces"
|
||||
export * from "./staff_time_entries"
|
||||
export * from "./staff_time_entry_connects"
|
||||
export * from "./staff_zeitstromtimestamps"
|
||||
export * from "./statementallocations"
|
||||
export * from "./tasks"
|
||||
export * from "./taxtypes"
|
||||
export * from "./tenants"
|
||||
export * from "./texttemplates"
|
||||
export * from "./units"
|
||||
export * from "./user_credentials"
|
||||
export * from "./vehicles"
|
||||
export * from "./vendors"
|
||||
export * from "./staff_time_events"
|
||||
export * from "./serialtypes"
|
||||
export * from "./serialexecutions"
|
||||
export * from "./public_links"
|
||||
export * from "./wikipages"
|
||||
39
backend/db/schema/inventoryitemgroups.ts
Normal file
39
backend/db/schema/inventoryitemgroups.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
jsonb, bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const inventoryitemgroups = pgTable("inventoryitemgroups", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" }).notNull().references(() => tenants.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
inventoryitems: jsonb("inventoryitems").notNull().default([]),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
usePlanning: boolean("usePlanning").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type InventoryItemGroup = typeof inventoryitemgroups.$inferSelect
|
||||
export type NewInventoryItemGroup = typeof inventoryitemgroups.$inferInsert
|
||||
68
backend/db/schema/inventoryitems.ts
Normal file
68
backend/db/schema/inventoryitems.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
doublePrecision,
|
||||
uuid,
|
||||
jsonb,
|
||||
date,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { vendors } from "./vendors"
|
||||
import { spaces } from "./spaces"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const inventoryitems = pgTable("inventoryitems", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
usePlanning: boolean("usePlanning").notNull().default(false),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
currentSpace: bigint("currentSpace", { mode: "number" }).references(
|
||||
() => spaces.id
|
||||
),
|
||||
|
||||
articleNumber: text("articleNumber"),
|
||||
serialNumber: text("serialNumber"),
|
||||
|
||||
purchaseDate: date("purchaseDate"),
|
||||
|
||||
vendor: bigint("vendor", { mode: "number" }).references(() => vendors.id),
|
||||
|
||||
quantity: bigint("quantity", { mode: "number" }).notNull().default(0),
|
||||
|
||||
purchasePrice: doublePrecision("purchasePrice").default(0),
|
||||
|
||||
manufacturer: text("manufacturer"),
|
||||
manufacturerNumber: text("manufacturerNumber"),
|
||||
|
||||
currentValue: doublePrecision("currentValue"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() =>
|
||||
authUsers.id
|
||||
),
|
||||
})
|
||||
|
||||
export type InventoryItem = typeof inventoryitems.$inferSelect
|
||||
export type NewInventoryItem = typeof inventoryitems.$inferInsert
|
||||
39
backend/db/schema/letterheads.ts
Normal file
39
backend/db/schema/letterheads.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const letterheads = pgTable("letterheads", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name").default("Standard"),
|
||||
|
||||
path: text("path").notNull(),
|
||||
|
||||
documentTypes: text("documentTypes").array().notNull().default([]),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
})
|
||||
|
||||
export type Letterhead = typeof letterheads.$inferSelect
|
||||
export type NewLetterhead = typeof letterheads.$inferInsert
|
||||
48
backend/db/schema/m2m_api_keys.ts
Normal file
48
backend/db/schema/m2m_api_keys.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
bigint,
|
||||
text,
|
||||
timestamp,
|
||||
boolean,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const m2mApiKeys = pgTable("m2m_api_keys", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade", onUpdate: "cascade" }),
|
||||
|
||||
userId: uuid("user_id")
|
||||
.notNull()
|
||||
.references(() => authUsers.id, { onDelete: "cascade", onUpdate: "cascade" }),
|
||||
|
||||
createdBy: uuid("created_by").references(() => authUsers.id, {
|
||||
onDelete: "set null",
|
||||
onUpdate: "cascade",
|
||||
}),
|
||||
|
||||
name: text("name").notNull(),
|
||||
keyPrefix: text("key_prefix").notNull(),
|
||||
keyHash: text("key_hash").notNull().unique(),
|
||||
|
||||
active: boolean("active").notNull().default(true),
|
||||
|
||||
lastUsedAt: timestamp("last_used_at", { withTimezone: true }),
|
||||
expiresAt: timestamp("expires_at", { withTimezone: true }),
|
||||
})
|
||||
|
||||
export type M2mApiKey = typeof m2mApiKeys.$inferSelect
|
||||
export type NewM2mApiKey = typeof m2mApiKeys.$inferInsert
|
||||
39
backend/db/schema/memberrelations.ts
Normal file
39
backend/db/schema/memberrelations.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
uuid,
|
||||
doublePrecision,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const memberrelations = pgTable("memberrelations", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
type: text("type").notNull(),
|
||||
billingInterval: text("billingInterval").notNull(),
|
||||
billingAmount: doublePrecision("billingAmount").notNull().default(0),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type MemberRelation = typeof memberrelations.$inferSelect
|
||||
export type NewMemberRelation = typeof memberrelations.$inferInsert
|
||||
|
||||
49
backend/db/schema/movements.ts
Normal file
49
backend/db/schema/movements.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { products } from "./products"
|
||||
import { spaces } from "./spaces"
|
||||
import { tenants } from "./tenants"
|
||||
import { projects } from "./projects"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const movements = pgTable("movements", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
quantity: bigint("quantity", { mode: "number" }).notNull(),
|
||||
|
||||
productId: bigint("productId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => products.id),
|
||||
|
||||
spaceId: bigint("spaceId", { mode: "number" }).references(() => spaces.id),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
projectId: bigint("projectId", { mode: "number" }).references(
|
||||
() => projects.id
|
||||
),
|
||||
|
||||
notes: text("notes"),
|
||||
|
||||
serials: text("serials").array(),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type Movement = typeof movements.$inferSelect
|
||||
export type NewMovement = typeof movements.$inferInsert
|
||||
34
backend/db/schema/notifications_event_types.ts
Normal file
34
backend/db/schema/notifications_event_types.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
pgTable,
|
||||
text,
|
||||
jsonb,
|
||||
boolean,
|
||||
timestamp,
|
||||
} from "drizzle-orm/pg-core"
|
||||
import {notificationSeverityEnum} from "./enums";
|
||||
|
||||
|
||||
export const notificationsEventTypes = pgTable("notifications_event_types", {
|
||||
eventKey: text("event_key").primaryKey(),
|
||||
|
||||
displayName: text("display_name").notNull(),
|
||||
description: text("description"),
|
||||
category: text("category"),
|
||||
|
||||
severity: notificationSeverityEnum("severity").notNull().default("info"),
|
||||
|
||||
allowedChannels: jsonb("allowed_channels").notNull().default(["inapp", "email"]),
|
||||
|
||||
payloadSchema: jsonb("payload_schema"),
|
||||
|
||||
isActive: boolean("is_active").notNull().default(true),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
})
|
||||
|
||||
export type NotificationsEventType =
|
||||
typeof notificationsEventTypes.$inferSelect
|
||||
export type NewNotificationsEventType =
|
||||
typeof notificationsEventTypes.$inferInsert
|
||||
54
backend/db/schema/notifications_items.ts
Normal file
54
backend/db/schema/notifications_items.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
bigint,
|
||||
text,
|
||||
jsonb,
|
||||
timestamp,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { notificationsEventTypes } from "./notifications_event_types"
|
||||
import {notificationChannelEnum, notificationStatusEnum} from "./enums";
|
||||
|
||||
|
||||
export const notificationsItems = pgTable("notifications_items", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade", onUpdate: "cascade" }),
|
||||
|
||||
userId: uuid("user_id")
|
||||
.notNull()
|
||||
.references(() => authUsers.id, { onDelete: "cascade", onUpdate: "cascade" }),
|
||||
|
||||
eventType: text("event_type")
|
||||
.notNull()
|
||||
.references(() => notificationsEventTypes.eventKey, {
|
||||
onUpdate: "cascade",
|
||||
onDelete: "restrict",
|
||||
}),
|
||||
|
||||
title: text("title").notNull(),
|
||||
message: text("message").notNull(),
|
||||
|
||||
payload: jsonb("payload"),
|
||||
|
||||
channel: notificationChannelEnum("channel").notNull(),
|
||||
|
||||
status: notificationStatusEnum("status").notNull().default("queued"),
|
||||
|
||||
error: text("error"),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
sentAt: timestamp("sent_at", { withTimezone: true }),
|
||||
readAt: timestamp("read_at", { withTimezone: true }),
|
||||
})
|
||||
|
||||
export type NotificationItem = typeof notificationsItems.$inferSelect
|
||||
export type NewNotificationItem = typeof notificationsItems.$inferInsert
|
||||
60
backend/db/schema/notifications_preferences.ts
Normal file
60
backend/db/schema/notifications_preferences.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
bigint,
|
||||
text,
|
||||
boolean,
|
||||
timestamp,
|
||||
uniqueIndex,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { notificationsEventTypes } from "./notifications_event_types"
|
||||
import {notificationChannelEnum} from "./enums";
|
||||
|
||||
export const notificationsPreferences = pgTable(
|
||||
"notifications_preferences",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, {
|
||||
onDelete: "cascade",
|
||||
onUpdate: "cascade",
|
||||
}),
|
||||
|
||||
userId: uuid("user_id")
|
||||
.notNull()
|
||||
.references(() => authUsers.id, {
|
||||
onDelete: "cascade",
|
||||
onUpdate: "cascade",
|
||||
}),
|
||||
|
||||
eventType: text("event_type")
|
||||
.notNull()
|
||||
.references(() => notificationsEventTypes.eventKey, {
|
||||
onDelete: "restrict",
|
||||
onUpdate: "cascade",
|
||||
}),
|
||||
|
||||
channel: notificationChannelEnum("channel").notNull(),
|
||||
|
||||
enabled: boolean("enabled").notNull().default(true),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
},
|
||||
(table) => ({
|
||||
uniquePrefs: uniqueIndex(
|
||||
"notifications_preferences_tenant_id_user_id_event_type_chan_key",
|
||||
).on(table.tenantId, table.userId, table.eventType, table.channel),
|
||||
}),
|
||||
)
|
||||
|
||||
export type NotificationPreference =
|
||||
typeof notificationsPreferences.$inferSelect
|
||||
export type NewNotificationPreference =
|
||||
typeof notificationsPreferences.$inferInsert
|
||||
52
backend/db/schema/notifications_preferences_defaults.ts
Normal file
52
backend/db/schema/notifications_preferences_defaults.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
bigint,
|
||||
text,
|
||||
boolean,
|
||||
timestamp,
|
||||
uniqueIndex,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { notificationsEventTypes } from "./notifications_event_types"
|
||||
import {notificationChannelEnum} from "./enums";
|
||||
|
||||
export const notificationsPreferencesDefaults = pgTable(
|
||||
"notifications_preferences_defaults",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, {
|
||||
onDelete: "cascade",
|
||||
onUpdate: "cascade",
|
||||
}),
|
||||
|
||||
eventKey: text("event_key")
|
||||
.notNull()
|
||||
.references(() => notificationsEventTypes.eventKey, {
|
||||
onDelete: "restrict",
|
||||
onUpdate: "cascade",
|
||||
}),
|
||||
|
||||
channel: notificationChannelEnum("channel").notNull(),
|
||||
|
||||
enabled: boolean("enabled").notNull().default(true),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
},
|
||||
(table) => ({
|
||||
uniqueDefaults: uniqueIndex(
|
||||
"notifications_preferences_defau_tenant_id_event_key_channel_key",
|
||||
).on(table.tenantId, table.eventKey, table.channel),
|
||||
}),
|
||||
)
|
||||
|
||||
export type NotificationPreferenceDefault =
|
||||
typeof notificationsPreferencesDefaults.$inferSelect
|
||||
export type NewNotificationPreferenceDefault =
|
||||
typeof notificationsPreferencesDefaults.$inferInsert
|
||||
39
backend/db/schema/ownaccounts.ts
Normal file
39
backend/db/schema/ownaccounts.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
pgTable,
|
||||
uuid,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
jsonb,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const ownaccounts = pgTable("ownaccounts", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
number: text("number").notNull(),
|
||||
name: text("name").notNull(),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type OwnAccount = typeof ownaccounts.$inferSelect
|
||||
export type NewOwnAccount = typeof ownaccounts.$inferInsert
|
||||
56
backend/db/schema/plants.ts
Normal file
56
backend/db/schema/plants.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
boolean,
|
||||
uuid,
|
||||
date,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { contracts } from "./contracts"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const plants = pgTable("plants", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
customer: bigint("customer", { mode: "number" }).references(
|
||||
() => customers.id
|
||||
),
|
||||
|
||||
infoData: jsonb("infoData"),
|
||||
contract: bigint("contract", { mode: "number" }).references(
|
||||
() => contracts.id
|
||||
),
|
||||
|
||||
description: jsonb("description").default({
|
||||
html: "",
|
||||
json: [],
|
||||
text: "",
|
||||
}),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
profiles: jsonb("profiles").notNull().default([]),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type Plant = typeof plants.$inferSelect
|
||||
export type NewPlant = typeof plants.$inferInsert
|
||||
37
backend/db/schema/productcategories.ts
Normal file
37
backend/db/schema/productcategories.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const productcategories = pgTable("productcategories", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type ProductCategory = typeof productcategories.$inferSelect
|
||||
export type NewProductCategory = typeof productcategories.$inferInsert
|
||||
69
backend/db/schema/products.ts
Normal file
69
backend/db/schema/products.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
doublePrecision,
|
||||
boolean,
|
||||
smallint,
|
||||
uuid,
|
||||
jsonb,
|
||||
json,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { units } from "./units"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const products = pgTable("products", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
manufacturer: text("manufacturer"),
|
||||
|
||||
unit: bigint("unit", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => units.id),
|
||||
|
||||
tags: json("tags").notNull().default([]),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
ean: text("ean"),
|
||||
barcode: text("barcode"),
|
||||
|
||||
purchase_price: doublePrecision("purchasePrice"),
|
||||
selling_price: doublePrecision("sellingPrice"),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
manufacturer_number: text("manufacturerNumber"),
|
||||
|
||||
vendor_allocation: jsonb("vendorAllocation").default([]),
|
||||
|
||||
article_number: text("articleNumber"),
|
||||
|
||||
barcodes: text("barcodes").array().notNull().default([]),
|
||||
|
||||
productcategories: jsonb("productcategories").default([]),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
tax_percentage: smallint("taxPercentage").notNull().default(19),
|
||||
|
||||
markup_percentage: doublePrecision("markupPercentage"),
|
||||
|
||||
updated_at: timestamp("updated_at", { withTimezone: true }),
|
||||
updated_by: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type Product = typeof products.$inferSelect
|
||||
export type NewProduct = typeof products.$inferInsert
|
||||
78
backend/db/schema/projects.ts
Normal file
78
backend/db/schema/projects.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
json,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { customers } from "./customers"
|
||||
import { contracts } from "./contracts"
|
||||
import { projecttypes } from "./projecttypes"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const projects = pgTable("projects", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
notes: text("notes"),
|
||||
|
||||
customer: bigint("customer", { mode: "number" }).references(
|
||||
() => customers.id
|
||||
),
|
||||
|
||||
phases: jsonb("phases").default([]),
|
||||
|
||||
description: json("description"),
|
||||
|
||||
forms: jsonb("forms").default([]),
|
||||
|
||||
heroId: text("heroId"),
|
||||
|
||||
measure: text("measure"),
|
||||
|
||||
material: jsonb("material"),
|
||||
|
||||
plant: bigint("plant", { mode: "number" }),
|
||||
|
||||
profiles: uuid("profiles").array().notNull().default([]),
|
||||
|
||||
projectNumber: text("projectNumber"),
|
||||
|
||||
contract: bigint("contract", { mode: "number" }).references(
|
||||
() => contracts.id
|
||||
),
|
||||
|
||||
projectType: text("projectType").default("Projekt"),
|
||||
|
||||
projecttype: bigint("projecttype", { mode: "number" }).references(
|
||||
() => projecttypes.id
|
||||
),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
customerRef: text("customerRef"),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
|
||||
active_phase: text("active_phase").default("Erstkontakt"),
|
||||
})
|
||||
|
||||
export type Project = typeof projects.$inferSelect
|
||||
export type NewProject = typeof projects.$inferInsert
|
||||
41
backend/db/schema/projecttypes.ts
Normal file
41
backend/db/schema/projecttypes.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const projecttypes = pgTable("projecttypes", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
initialPhases: jsonb("initialPhases"),
|
||||
addablePhases: jsonb("addablePhases"),
|
||||
|
||||
icon: text("icon"),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type ProjectType = typeof projecttypes.$inferSelect
|
||||
export type NewProjectType = typeof projecttypes.$inferInsert
|
||||
30
backend/db/schema/public_links.ts
Normal file
30
backend/db/schema/public_links.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { pgTable, text, integer, boolean, jsonb, timestamp, uuid } from 'drizzle-orm/pg-core';
|
||||
import { tenants } from './tenants';
|
||||
import { authProfiles } from './auth_profiles';
|
||||
|
||||
export const publicLinks = pgTable('public_links', {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
||||
// Der öffentliche Token (z.B. "werkstatt-tablet-01")
|
||||
token: text('token').notNull().unique(),
|
||||
|
||||
// Zuordnung zum Tenant (WICHTIG für die Datentrennung)
|
||||
tenant: integer('tenant').references(() => tenants.id).notNull(),
|
||||
|
||||
defaultProfile: uuid('default_profile').references(() => authProfiles.id),
|
||||
|
||||
// Sicherheit
|
||||
isProtected: boolean('is_protected').default(false).notNull(),
|
||||
pinHash: text('pin_hash'),
|
||||
|
||||
// Konfiguration (JSON)
|
||||
config: jsonb('config').default({}),
|
||||
|
||||
// Metadaten
|
||||
name: text('name').notNull(),
|
||||
description: text('description'),
|
||||
|
||||
active: boolean('active').default(true).notNull(),
|
||||
createdAt: timestamp('created_at').defaultNow(),
|
||||
updatedAt: timestamp('updated_at').defaultNow(),
|
||||
});
|
||||
21
backend/db/schema/serialexecutions.ts
Normal file
21
backend/db/schema/serialexecutions.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
import {tenants} from "./tenants";
|
||||
|
||||
export const serialExecutions = pgTable("serial_executions", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id), executionDate: timestamp("execution_date").notNull(),
|
||||
status: text("status").default("draft"), // 'draft', 'completed'
|
||||
createdBy: text("created_by"), // oder UUID, je nach Auth-System
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
summary: text("summary"), // z.B. "25 Rechnungen erstellt"
|
||||
});
|
||||
40
backend/db/schema/serialtypes.ts
Normal file
40
backend/db/schema/serialtypes.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
jsonb,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const serialtypes = pgTable("serialtypes", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
intervall: text("intervall"),
|
||||
|
||||
icon: text("icon"),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type SerialType = typeof serialtypes.$inferSelect
|
||||
export type NewSerialType = typeof serialtypes.$inferInsert
|
||||
39
backend/db/schema/servicecategories.ts
Normal file
39
backend/db/schema/servicecategories.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
doublePrecision,
|
||||
boolean,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const servicecategories = pgTable("servicecategories", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
created_at: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
name: text("name").notNull(),
|
||||
description: text("description"),
|
||||
|
||||
discount: doublePrecision("discount").default(0),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
updated_at: timestamp("updated_at", { withTimezone: true }),
|
||||
updated_by: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type ServiceCategory = typeof servicecategories.$inferSelect
|
||||
export type NewServiceCategory = typeof servicecategories.$inferInsert
|
||||
64
backend/db/schema/services.ts
Normal file
64
backend/db/schema/services.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import {
|
||||
pgTable,
|
||||
bigint,
|
||||
timestamp,
|
||||
text,
|
||||
doublePrecision,
|
||||
jsonb,
|
||||
boolean,
|
||||
smallint,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { units } from "./units"
|
||||
import { authUsers } from "./auth_users"
|
||||
|
||||
export const services = pgTable("services", {
|
||||
id: bigint("id", { mode: "number" })
|
||||
.primaryKey()
|
||||
.generatedByDefaultAsIdentity(),
|
||||
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
|
||||
name: text("name").notNull(),
|
||||
|
||||
sellingPrice: doublePrecision("sellingPrice"),
|
||||
|
||||
description: text("description"),
|
||||
|
||||
tenant: bigint("tenant", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id),
|
||||
|
||||
unit: bigint("unit", { mode: "number" }).references(() => units.id),
|
||||
|
||||
serviceNumber: bigint("serviceNumber", { mode: "number" }),
|
||||
|
||||
tags: jsonb("tags").default([]),
|
||||
servicecategories: jsonb("servicecategories").notNull().default([]),
|
||||
|
||||
archived: boolean("archived").notNull().default(false),
|
||||
|
||||
purchasePriceComposed: jsonb("purchasePriceComposed")
|
||||
.notNull()
|
||||
.default({ total: 0 }),
|
||||
|
||||
sellingPriceComposed: jsonb("sellingPriceComposed")
|
||||
.notNull()
|
||||
.default({ total: 0 }),
|
||||
|
||||
taxPercentage: smallint("taxPercentage").notNull().default(19),
|
||||
|
||||
materialComposition: jsonb("materialComposition").notNull().default([]),
|
||||
personalComposition: jsonb("personalComposition").notNull().default([]),
|
||||
priceUpdateLocked: boolean("priceUpdateLocked").notNull().default(false),
|
||||
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
updatedBy: uuid("updated_by").references(() => authUsers.id),
|
||||
})
|
||||
|
||||
export type Service = typeof services.$inferSelect
|
||||
export type NewService = typeof services.$inferInsert
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user