forked from Kispi/Core
feat(core): add wage functionality to the employer portal
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
97785d17ad
commit
019d0ae566
14 changed files with 554 additions and 238 deletions
|
@ -15,7 +15,7 @@ require (
|
|||
atomicgo.dev/schedule v0.0.2 // indirect
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.298 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.299 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.18.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.27 // indirect
|
||||
|
@ -83,7 +83,7 @@ require (
|
|||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.130.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
google.golang.org/grpc v1.56.2 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
lukechampine.com/uint128 v1.3.0 // indirect
|
||||
|
@ -93,7 +93,7 @@ require (
|
|||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.6.0 // indirect
|
||||
modernc.org/opt v0.1.3 // indirect
|
||||
modernc.org/sqlite v1.23.1 // indirect
|
||||
modernc.org/sqlite v1.24.0 // indirect
|
||||
modernc.org/strutil v1.1.3 // indirect
|
||||
modernc.org/token v1.1.0 // indirect
|
||||
)
|
||||
|
|
|
@ -185,7 +185,6 @@ cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOV
|
|||
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
|
||||
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
|
||||
cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI=
|
||||
cloud.google.com/go/compute v1.20.0 h1:cUOcywWuowO9It2i1KX1lIb0HH7gLv6nENKuZGnlcSo=
|
||||
cloud.google.com/go/compute v1.20.0/go.mod h1:kn5BhC++qUWR/AM3Dn21myV7QbgqejW04cAOrtppaQI=
|
||||
cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
|
||||
cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
|
||||
|
@ -790,10 +789,8 @@ github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4
|
|||
github.com/aws/aws-sdk-go v1.44.156/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go v1.44.245/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go v1.44.284/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go v1.44.294 h1:3x7GaEth+pDU9HwFcAU0awZlEix5CEdyIZvV08SlHa8=
|
||||
github.com/aws/aws-sdk-go v1.44.294/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go v1.44.298 h1:5qTxdubgV7PptZJmp/2qDwD2JL187ePL7VOxsSh1i3g=
|
||||
github.com/aws/aws-sdk-go v1.44.298/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go v1.44.299 h1:HVD9lU4CAFHGxleMJp95FV/sRhtg7P4miHD1v88JAQk=
|
||||
github.com/aws/aws-sdk-go v1.44.299/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
|
||||
github.com/aws/aws-sdk-go-v2 v1.18.1 h1:+tefE750oAb7ZQGzla6bLkOwfcQCEtC5y2RqoqCeqKo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
||||
|
@ -1303,7 +1300,6 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
|
|||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
|
@ -1453,7 +1449,6 @@ github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38
|
|||
github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
||||
github.com/googleapis/gax-go/v2 v2.9.1/go.mod h1:4FG3gMrVZlyMp5itSYKMU9z/lBE7+SbnUOvzH2HqbEY=
|
||||
github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw=
|
||||
github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
|
||||
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
|
@ -1937,8 +1932,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pocketbase/dbx v1.10.0 h1:58VIT7r6T+BnVbYVosvGBsPjQEic3/VFRYGT823vWSQ=
|
||||
github.com/pocketbase/dbx v1.10.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
|
||||
github.com/pocketbase/pocketbase v0.16.6 h1:zE+9SPXlhimZpuiD4KrmY+cp4b2lyL8gLAbkjj5YqFY=
|
||||
github.com/pocketbase/pocketbase v0.16.6/go.mod h1:xXXL26RVy0vGxDHOffoaeEv7CvZSJHivnfAeygmEfD8=
|
||||
github.com/pocketbase/pocketbase v0.16.8 h1:uILzBla2DNMFGZFRu0cStIv3AVjYgicOQs2F1AeXpGw=
|
||||
github.com/pocketbase/pocketbase v0.16.8/go.mod h1:vmajDvROzq//BiQ4RoNqHmjHf5i8RMgK665zQ14oo/g=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
|
@ -2351,7 +2344,6 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw
|
|||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
|
@ -2387,8 +2379,6 @@ golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeap
|
|||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.8.0 h1:agUcRXV/+w6L9ryntYYsF2x9fQTMd4T8fiiYXAVW6Jg=
|
||||
golang.org/x/image v0.8.0/go.mod h1:PwLxp3opCYg4WR2WO9P0L6ESnsD6bLTWcw8zanLMVFM=
|
||||
golang.org/x/image v0.9.0 h1:QrzfX26snvCM20hIhBwuHI/ThTg18b/+kcKdXHvnR+g=
|
||||
golang.org/x/image v0.9.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
@ -2423,8 +2413,6 @@ golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -2521,7 +2509,6 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
|
@ -2558,7 +2545,6 @@ golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I
|
|||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
|
||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||
golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs=
|
||||
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
|
@ -2739,7 +2725,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -2756,7 +2741,6 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
|
@ -2776,7 +2760,6 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
|
@ -2886,8 +2869,6 @@ golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
|||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
|
||||
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
|
||||
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -2978,8 +2959,6 @@ google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2
|
|||
google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
|
||||
google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
|
||||
google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750=
|
||||
google.golang.org/api v0.129.0 h1:2XbdjjNfFPXQyufzQVwPf1RRnHH8Den2pfNE2jw7L8w=
|
||||
google.golang.org/api v0.129.0/go.mod h1:dFjiXlanKwWE3612X97llhsoI36FAoIiRj3aTl5b/zE=
|
||||
google.golang.org/api v0.130.0 h1:A50ujooa1h9iizvfzA4rrJr2B7uRmWexwbekQ2+5FPQ=
|
||||
google.golang.org/api v0.130.0/go.mod h1:J/LCJMYSDFvAVREGCbrESb53n4++NMBDetSHGL5I5RY=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
|
@ -3140,8 +3119,8 @@ google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOl
|
|||
google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY=
|
||||
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao=
|
||||
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
|
||||
|
@ -3152,10 +3131,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.
|
|||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529 h1:DEH99RbiLZhMxrpEJCZ0A+wdTe0EOgou/poSLx9vWf4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 h1:2FZP5XuJY9zQyGM5N0rtovnoXjiMUEIUMvw0m9wlpLc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
|
@ -3204,8 +3181,6 @@ google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwS
|
|||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||
google.golang.org/grpc v1.56.0/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ=
|
||||
google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI=
|
||||
google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
|
@ -3389,8 +3364,8 @@ modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
|||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4=
|
||||
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
|
||||
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||
modernc.org/sqlite v1.24.0 h1:EsClRIWHGhLTCX44p+Ri/JLD+vFGo0QGjasg2/F9TlI=
|
||||
modernc.org/sqlite v1.24.0/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"cliffbreak.de/hgoe-sas-server/pkg/middlewares"
|
||||
"cliffbreak.de/hgoe-sas-server/pkg/utils"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
|
||||
|
@ -15,6 +21,18 @@ func main() {
|
|||
|
||||
app.OnBeforeServe().Add(middlewares.ServeSPA(utils.GetEnv("WEBAPP", "./webapp")))
|
||||
|
||||
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||
e.Router.AddRoute(echo.Route{
|
||||
Method: http.MethodGet,
|
||||
Path: "/api/time",
|
||||
Handler: func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, time.Now().Format(time.RFC3339))
|
||||
},
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := app.Start(); err != nil {
|
||||
pterm.Fatal.Println(err)
|
||||
}
|
||||
|
|
|
@ -1,63 +1,4 @@
|
|||
[
|
||||
{
|
||||
"id": "t4gewf713jqhz3i",
|
||||
"name": "settings",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"id": "z7pmr7wm",
|
||||
"name": "minWage",
|
||||
"type": "number",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"min": 0,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "7wzv9qum",
|
||||
"name": "incomeTax",
|
||||
"type": "number",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"min": 0,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "dawtvakx",
|
||||
"name": "maxWageFactor",
|
||||
"type": "number",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"min": 0,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ftzmu1na",
|
||||
"name": "radioUrl",
|
||||
"type": "url",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"exceptDomains": [],
|
||||
"onlyDomains": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"id": "w85pgrtrmovf916",
|
||||
"name": "transactions",
|
||||
|
@ -294,54 +235,6 @@
|
|||
"query": "SELECT\n a.id AS id,\n a.accountNumber AS accountNumber,\n (a.firstName || ' ' || a.lastName) AS name,\n a.grade AS grade,\n a.lastCheckIn AS lastCheckIn,\n SUM(t.amount) AS balance\nFROM\n accounts AS a\nLEFT JOIN\n transactions AS t\nON\n a.id = t.account\nGROUP BY\n a.id\nORDER BY\n a.grade, a.lastName"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "s854d2w72fvyl54",
|
||||
"name": "companies",
|
||||
"type": "auth",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"id": "h5ogbj93",
|
||||
"name": "accountNumber",
|
||||
"type": "text",
|
||||
"system": false,
|
||||
"required": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cvcgnf4x",
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"listRule": "",
|
||||
"viewRule": null,
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"options": {
|
||||
"allowEmailAuth": true,
|
||||
"allowOAuth2Auth": true,
|
||||
"allowUsernameAuth": true,
|
||||
"exceptEmailDomains": null,
|
||||
"manageRule": null,
|
||||
"minPasswordLength": 8,
|
||||
"onlyEmailDomains": null,
|
||||
"requireEmail": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "5msnfxat1sc2c1r",
|
||||
"name": "companyTransactions",
|
||||
|
@ -393,5 +286,150 @@
|
|||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"id": "s854d2w72fvyl54",
|
||||
"name": "companies",
|
||||
"type": "auth",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"id": "h5ogbj93",
|
||||
"name": "accountNumber",
|
||||
"type": "text",
|
||||
"system": false,
|
||||
"required": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cvcgnf4x",
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ujqd3vik",
|
||||
"name": "earlyShiftPayed",
|
||||
"type": "date",
|
||||
"system": false,
|
||||
"required": false,
|
||||
"options": {
|
||||
"min": "",
|
||||
"max": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "t1kakf3f",
|
||||
"name": "lateShiftPayed",
|
||||
"type": "date",
|
||||
"system": false,
|
||||
"required": false,
|
||||
"options": {
|
||||
"min": "",
|
||||
"max": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE INDEX `idx_eX1Vqqz` ON `companies` (`accountNumber`)"
|
||||
],
|
||||
"listRule": "",
|
||||
"viewRule": null,
|
||||
"createRule": null,
|
||||
"updateRule": "(@request.data.id = null && @request.data.username = null && @request.data.email = null && @request.data.accountNumber = null && @request.data.created = null && @request.data.updated = null && @request.data.name = null && @request.data.emailVisibility = null && @request.data.verified = null) && @request.data.id = @request.auth.id",
|
||||
"deleteRule": null,
|
||||
"options": {
|
||||
"allowEmailAuth": true,
|
||||
"allowOAuth2Auth": true,
|
||||
"allowUsernameAuth": true,
|
||||
"exceptEmailDomains": null,
|
||||
"manageRule": null,
|
||||
"minPasswordLength": 8,
|
||||
"onlyEmailDomains": null,
|
||||
"requireEmail": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "t4gewf713jqhz3i",
|
||||
"name": "settings",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"id": "z7pmr7wm",
|
||||
"name": "minWage",
|
||||
"type": "number",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"min": 0,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "7wzv9qum",
|
||||
"name": "incomeTax",
|
||||
"type": "number",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"min": 0,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "3pgjcfai",
|
||||
"name": "incomeTaxRecipient",
|
||||
"type": "relation",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"collectionId": "s854d2w72fvyl54",
|
||||
"cascadeDelete": false,
|
||||
"minSelect": null,
|
||||
"maxSelect": 1,
|
||||
"displayFields": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "dawtvakx",
|
||||
"name": "maxWageFactor",
|
||||
"type": "number",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"min": 0,
|
||||
"max": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ftzmu1na",
|
||||
"name": "radioUrl",
|
||||
"type": "url",
|
||||
"system": false,
|
||||
"required": true,
|
||||
"options": {
|
||||
"exceptDomains": [],
|
||||
"onlyDomains": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"options": {}
|
||||
}
|
||||
]
|
|
@ -66,11 +66,11 @@
|
|||
<span
|
||||
v-if="header.type === TableHeaderType.BUTTON_CHANGE_ACCOUNT_NUMBER"
|
||||
class="btn-ghost btn-sm btn p-1"
|
||||
@click="$emit('changeAccountNumber', entry.id)"
|
||||
>
|
||||
<div
|
||||
class="tooltip normal-case"
|
||||
data-tip="Kontonummer ändern"
|
||||
@click="$emit('changeAccountNumber', entry.id)"
|
||||
>
|
||||
<CreditCardIcon class="h-6 w-6" />
|
||||
</div>
|
||||
|
|
61
webapp/src/components/molecules/MoleculeVerifyModal.vue
Normal file
61
webapp/src/components/molecules/MoleculeVerifyModal.vue
Normal file
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<AtomModal
|
||||
:id="id"
|
||||
ref="modal"
|
||||
:title="title"
|
||||
>
|
||||
<div class="flex flex-col gap-4">
|
||||
<slot />
|
||||
</div>
|
||||
<template #action>
|
||||
<button
|
||||
class="btn gap-2"
|
||||
:for="id"
|
||||
@click="modal?.close()"
|
||||
>
|
||||
<XCircleIcon class="h-6 w-6" />
|
||||
Abbrechen
|
||||
</button>
|
||||
<button
|
||||
class="btn gap-2"
|
||||
@click="$emit('confirm')"
|
||||
>
|
||||
<CheckCircleIcon class="h-6 w-6" />
|
||||
Bestätigen
|
||||
</button>
|
||||
</template>
|
||||
</AtomModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { CheckCircleIcon, XCircleIcon } from '@heroicons/vue/24/outline';
|
||||
import AtomModal from '../atoms/AtomModal.vue';
|
||||
|
||||
const modal = ref<InstanceType<typeof AtomModal>>();
|
||||
|
||||
defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
show: () => modal.value?.show(),
|
||||
close: () => modal.value?.close(),
|
||||
isOpen: () => modal.value?.isOpen(),
|
||||
});
|
||||
|
||||
defineEmits<{
|
||||
confirm: [],
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
|
@ -1,4 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="account || company"
|
||||
class="hero-content flex-col pt-0 text-center lg:p-6"
|
||||
|
@ -11,7 +12,16 @@
|
|||
Kontoinhaber: {{ `${account.firstName} ${account.lastName}` }}
|
||||
</h3>
|
||||
<h3
|
||||
v-if="company"
|
||||
v-if="company && company.id == settings?.incomeTaxRecipient"
|
||||
class="mt-10 text-5xl font-bold"
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<AtomLogo class="h-14 w-14" />
|
||||
{{ company.name }}
|
||||
</div>
|
||||
</h3>
|
||||
<h3
|
||||
v-else-if="company"
|
||||
class="mt-10 text-5xl font-bold"
|
||||
>
|
||||
Firma: {{ company.name }}
|
||||
|
@ -59,7 +69,10 @@
|
|||
Auszahlen
|
||||
</button>
|
||||
</div>
|
||||
<AtomHeroText v-else>
|
||||
<AtomHeroText
|
||||
v-else
|
||||
class="h-full"
|
||||
>
|
||||
Bitte Karte scannen...
|
||||
<div
|
||||
v-if="error"
|
||||
|
@ -77,6 +90,7 @@
|
|||
<span>Transaktion nicht möglich. Konto ist nicht ausreichend gedeckt.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -84,7 +98,7 @@ import { onMounted, onUnmounted, ref } from 'vue';
|
|||
import { useRouter } from 'vue-router';
|
||||
import { onKeyStroke, promiseTimeout } from '@vueuse/core';
|
||||
import { RecordSubscription, UnsubscribeFunc } from 'pocketbase';
|
||||
import { AccountsResponse, CompaniesResponse, TransactionsResponse } from '../../types/pocketbase.types';
|
||||
import { AccountsResponse, CompaniesResponse, SettingsResponse, TransactionsResponse } from '../../types/pocketbase.types';
|
||||
import { AccountService } from '../../services/account.service';
|
||||
import { AccountType, BankService, TransactionType } from '../../services/bank.service';
|
||||
import { CompanyService } from '../../services/company.service';
|
||||
|
@ -93,6 +107,8 @@ import { ChevronDownIcon, ChevronUpIcon, XCircleIcon } from '@heroicons/vue/24/o
|
|||
import AtomHeroText from '../atoms/AtomHeroText.vue';
|
||||
import MoleculeInputModal from '../molecules/MoleculeInputModal.vue';
|
||||
import MoleculeTransactionTable from '../molecules/MoleculeTransactionTable.vue';
|
||||
import { SettingsService } from '../../services/settings.service';
|
||||
import AtomLogo from '../atoms/AtomLogo.vue';
|
||||
|
||||
const router = useRouter();
|
||||
const subscription = ref<UnsubscribeFunc>();
|
||||
|
@ -107,6 +123,7 @@ const accountId = ref<string>('');
|
|||
const inputBuffer = ref<string>('');
|
||||
const error = ref('');
|
||||
const depositError = ref(false);
|
||||
const settings = ref<SettingsResponse>();
|
||||
|
||||
if(router.currentRoute.value.query.accountNumber) {
|
||||
accountId.value = router.currentRoute.value.query.accountNumber as string;
|
||||
|
@ -228,6 +245,7 @@ function handleRealtimeUpdates(transactionSubscription: RecordSubscription<Trans
|
|||
onMounted(async () => {
|
||||
subscription.value = await BankService.subscribeToTransactionChanges(handleRealtimeUpdates);
|
||||
companySubscription.value = await BankService.subscribeToCompanyTransactionChanges(handleRealtimeUpdates);
|
||||
settings.value = await SettingsService.getSettings();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
|
|
@ -42,12 +42,81 @@
|
|||
Abmelden
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-2xl">500,00 Batzen</h2>
|
||||
<!-- <div class="flex items-center justify-between">
|
||||
<h2 class="text-2xl">Kontostand: {{ CurrencyService.toString(getBalance()) }}</h2>
|
||||
<button class="btn-primary btn-disabled btn w-48">
|
||||
<BanknotesIcon class="h-6 w-6" />
|
||||
Transaktionen
|
||||
</button>
|
||||
</div> -->
|
||||
<div class="stats shadow">
|
||||
<div class="stat place-items-center">
|
||||
<div class="stat-title">Kontostand</div>
|
||||
<div class="stat-value">{{ CurrencyService.toString(getBalance(), false) }}</div>
|
||||
<div class="stat-desc">Batzen</div>
|
||||
</div>
|
||||
<div class="stat place-items-center">
|
||||
<div class="stat-title">Arbeitnehmer</div>
|
||||
<div class="stat-value">{{ accounts.filter(account => (account.shift != Shifts.EARLY && account.shift != Shifts.LATE)).length }}</div>
|
||||
<div class="stat-desc">ohne Schicht</div>
|
||||
</div>
|
||||
<div class="stat place-items-center">
|
||||
<div class="stat-title">Arbeitnehmer</div>
|
||||
<div class="stat-value">{{ accounts.filter(account => account.shift == Shifts.EARLY).length }}</div>
|
||||
<div class="stat-desc">in Frühschicht</div>
|
||||
</div>
|
||||
<div class="stat place-items-center">
|
||||
<div class="stat-title">Arbeitnehmer</div>
|
||||
<div class="stat-value">{{ accounts.filter(account => account.shift == Shifts.LATE).length }}</div>
|
||||
<div class="stat-desc">in Spätschicht</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-center gap-4">
|
||||
<button
|
||||
class="btn-primary btn"
|
||||
:class="{'btn-disabled': (getBalance() < getTotalCostsByShifts(Shifts.EARLY) || DateService.isToday(new Date(company.earlyShiftPayed)))}"
|
||||
@click="wageType = Shifts.EARLY; verifyModal?.show()"
|
||||
>
|
||||
<SunIcon class="h-6 w-6" />
|
||||
Frühschicht bezahlen ({{ CurrencyService.toString(getTotalCostsByShifts(Shifts.EARLY)) }})
|
||||
</button>
|
||||
<button
|
||||
class="btn-primary btn"
|
||||
:class="{'btn-disabled': (getBalance() < getTotalCostsByShifts(Shifts.LATE) || DateService.isToday(new Date(company.lateShiftPayed)))}"
|
||||
@click="wageType = Shifts.LATE; verifyModal?.show()"
|
||||
>
|
||||
<MoonIcon class="h-6 w-6" />
|
||||
Spätschicht bezahlen ({{ CurrencyService.toString(getTotalCostsByShifts(Shifts.LATE)) }})
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div
|
||||
v-if="DateService.isToday(new Date(company.earlyShiftPayed))"
|
||||
class="alert alert-info"
|
||||
>
|
||||
<InformationCircleIcon class="h-6 w-6" />
|
||||
Die Frühschicht wurde heute bereits bezahlt.
|
||||
</div>
|
||||
<div
|
||||
v-if="DateService.isToday(new Date(company.lateShiftPayed))"
|
||||
class="alert alert-info"
|
||||
>
|
||||
<InformationCircleIcon class="h-6 w-6" />
|
||||
Die Spätschicht wurde heute bereits bezahlt.
|
||||
</div>
|
||||
<div
|
||||
v-if="getBalance() < getTotalCostsByShifts(Shifts.EARLY)"
|
||||
class="alert alert-warning"
|
||||
>
|
||||
<ExclamationTriangleIcon class="h-6 w-6" />
|
||||
Konto nicht ausreichend gedeckt um die Frühschicht zu bezahlen.
|
||||
</div>
|
||||
<div
|
||||
v-if="getBalance() < getTotalCostsByShifts(Shifts.LATE)"
|
||||
class="alert alert-warning"
|
||||
>
|
||||
<ExclamationTriangleIcon class="h-6 w-6" />
|
||||
Konto nicht ausreichend gedeckt um die Spätschicht zu bezahlen.
|
||||
</div>
|
||||
</div>
|
||||
<MoleculeDataTable
|
||||
|
@ -58,19 +127,64 @@
|
|||
@select-wage="selectWage"
|
||||
/>
|
||||
</div>
|
||||
<MoleculeVerifyModal
|
||||
id="verify-modal"
|
||||
ref="verifyModal"
|
||||
title="Lohnauszahlung bestätigen"
|
||||
@confirm="async () => {
|
||||
verifyModal?.close();
|
||||
if(wageType) {
|
||||
await CompanyService.payWage(wageType);
|
||||
}
|
||||
wageType = undefined;
|
||||
init();
|
||||
}"
|
||||
>
|
||||
<div class="flex flex-col gap-1">
|
||||
<p>Lohn wirklich für die {{ wageType == Shifts.EARLY ? 'Frühschicht' : 'Spätschicht' }} auszahlen?</p>
|
||||
<p>
|
||||
Das Konto wird mit <b>{{
|
||||
CurrencyService.toString(
|
||||
wageType == Shifts.EARLY ?
|
||||
getTotalCostsByShifts(Shifts.EARLY) : getTotalCostsByShifts(Shifts.LATE)
|
||||
)
|
||||
}}</b> belastet.<br />
|
||||
Dies beinhaltet die Lohnsteuer von {{ settings?.incomeTax }}% ({{
|
||||
CurrencyService.toString(
|
||||
wageType == Shifts.EARLY ?
|
||||
getTotalCostsByShifts(Shifts.EARLY) * (settings?.incomeTax ?? 0) / 100 :
|
||||
getTotalCostsByShifts(Shifts.LATE) * (settings?.incomeTax ?? 0) / 100
|
||||
)
|
||||
}}).
|
||||
</p>
|
||||
<p><b>Hinweis:</b> Diese Aktion kann nur 1x am Tag ausgeführt werden.</p>
|
||||
</div>
|
||||
</MoleculeVerifyModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { RecordSubscription, UnsubscribeFunc } from 'pocketbase';
|
||||
import { AccountsResponse, CompaniesResponse } from '../../types/pocketbase.types';
|
||||
import { AccountsResponse, CompaniesResponse, SettingsResponse, TransactionsResponse } from '../../types/pocketbase.types';
|
||||
import { AccountService } from '../../services/account.service';
|
||||
import { BankService } from '../../services/bank.service';
|
||||
import { CompanyService } from '../../services/company.service';
|
||||
import { CurrencyService } from '../../services/currency.service';
|
||||
import { DateService } from '../../services/date.service';
|
||||
import { SettingsService } from '../../services/settings.service';
|
||||
import { Shifts } from '../../enums/shift.enum';
|
||||
import { ArrowLeftOnRectangleIcon, BanknotesIcon } from '@heroicons/vue/24/outline';
|
||||
import { ArrowLeftOnRectangleIcon,
|
||||
BanknotesIcon,
|
||||
ExclamationTriangleIcon,
|
||||
InformationCircleIcon,
|
||||
MoonIcon,
|
||||
SunIcon,
|
||||
} from '@heroicons/vue/24/outline';
|
||||
import AtomInput from '../atoms/AtomInput.vue';
|
||||
import MoleculeDataTable, { TableHeaderType } from '../molecules/MoleculeDataTable.vue';
|
||||
import MoleculeLoginModal from '../molecules/MoleculeLoginModal.vue';
|
||||
import MoleculeVerifyModal from '../molecules/MoleculeVerifyModal.vue';
|
||||
|
||||
const loginModal = ref<InstanceType<typeof MoleculeLoginModal>>();
|
||||
const searchQuery = ref('');
|
||||
|
@ -80,9 +194,13 @@ const initCompanies = ref<CompaniesResponse[]>([]);
|
|||
const selectedCompany = ref<CompaniesResponse>();
|
||||
const company = ref<CompaniesResponse>();
|
||||
const accounts = ref<AccountsResponse[]>([]);
|
||||
const transactions = ref<TransactionsResponse[]>([]);
|
||||
const isAuthenticated = ref(false);
|
||||
const accountsSubscription = ref<UnsubscribeFunc>();
|
||||
const settings = ref<SettingsResponse>();
|
||||
const error = ref('');
|
||||
const verifyModal = ref<InstanceType<typeof MoleculeVerifyModal>>();
|
||||
const wageType = ref<Shifts|undefined>();
|
||||
|
||||
const companyTableHeaders = [
|
||||
{
|
||||
|
@ -137,6 +255,7 @@ function search(value: string): void {
|
|||
|
||||
onMounted(async () => {
|
||||
isAuthenticated.value = CompanyService.isAuthenticated();
|
||||
settings.value = await SettingsService.getSettings();
|
||||
if(isAuthenticated.value) {
|
||||
init();
|
||||
} else {
|
||||
|
@ -147,6 +266,7 @@ onMounted(async () => {
|
|||
async function init() {
|
||||
company.value = await CompanyService.getCompany();
|
||||
accounts.value = await AccountService.getAccountsByCompanyId(company.value.id);
|
||||
transactions.value = await BankService.getCompanyTransactions(company.value.id);
|
||||
accountsSubscription.value = await AccountService.subscribeToAccountChanges(async (data: RecordSubscription<AccountsResponse>) => {
|
||||
if(data.action === 'update') {
|
||||
accounts.value = accounts.value.map((account) => {
|
||||
|
@ -159,6 +279,16 @@ async function init() {
|
|||
});
|
||||
}
|
||||
|
||||
function getBalance(): number {
|
||||
return transactions.value?.reduce((acc, transaction) => acc + transaction.amount, 0) ?? 0;
|
||||
}
|
||||
|
||||
function getTotalCostsByShifts(shift: Shifts): number {
|
||||
return accounts.value?.filter(
|
||||
(account) => account.shift === shift).reduce((acc, account) => acc + account.wageFactor * (settings.value?.minWage ?? 0), 0,
|
||||
) ?? 0;
|
||||
}
|
||||
|
||||
function showLoginDialog(id: string): void {
|
||||
selectedCompany.value = companies.value.find((company) => company.id === id);
|
||||
loginModal.value?.show();
|
||||
|
|
|
@ -27,6 +27,13 @@
|
|||
class="w-2/4"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex place-items-center justify-between">
|
||||
<span>Steuer-Empfänger-ID</span>
|
||||
<AtomInput
|
||||
v-model="incomeTaxRecipient"
|
||||
class="!w-2/4"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<span>Radio URL</span>
|
||||
<AtomInput v-model="radioUrl" />
|
||||
|
@ -196,6 +203,7 @@ const errorModal = ref<InstanceType<typeof MoleculeErrorModal>>();
|
|||
const minWage = ref<number>();
|
||||
const incomeTax = ref<number>();
|
||||
const maxWageFactor = ref<number>();
|
||||
const incomeTaxRecipient = ref<string>();
|
||||
const radioUrl = ref<string>();
|
||||
const settings = ref<SettingsResponse>();
|
||||
const settingsSaveSuccess = ref<boolean>(false);
|
||||
|
@ -289,15 +297,17 @@ onMounted(async () => {
|
|||
minWage.value = settings.value.minWage / 100;
|
||||
incomeTax.value = settings.value.incomeTax;
|
||||
maxWageFactor.value = settings.value.maxWageFactor;
|
||||
incomeTaxRecipient.value = settings.value.incomeTaxRecipient;
|
||||
radioUrl.value = settings.value.radioUrl;
|
||||
});
|
||||
|
||||
async function saveSettings() {
|
||||
if(minWage.value && incomeTax.value && maxWageFactor.value && radioUrl.value) {
|
||||
if(minWage.value && incomeTax.value && maxWageFactor.value && incomeTaxRecipient.value && radioUrl.value) {
|
||||
settings.value = await SettingsService.setSettings({
|
||||
minWage: minWage.value,
|
||||
incomeTax: incomeTax.value,
|
||||
maxWageFactor: maxWageFactor.value,
|
||||
incomeTaxRecipient: incomeTaxRecipient.value,
|
||||
radioUrl: radioUrl.value,
|
||||
});
|
||||
settingsSaveSuccess.value = true;
|
||||
|
|
|
@ -19,7 +19,7 @@ export class BankService {
|
|||
}
|
||||
public static async addTransaction(accountId: string,
|
||||
amount: number,
|
||||
type: TransactionType,
|
||||
type: TransactionType | string,
|
||||
accountType: AccountType = AccountType.ACCOUNT,
|
||||
): Promise<TransactionsResponse> {
|
||||
let label = '';
|
||||
|
@ -36,11 +36,13 @@ export class BankService {
|
|||
case TransactionType.OPEN_ACCOUNT:
|
||||
label = OPEN_ACCOUNT_LABEL;
|
||||
break;
|
||||
default:
|
||||
label = type;
|
||||
}
|
||||
if(accountType === AccountType.COMPANY) {
|
||||
return COMPANY_COLLECTION.create({ account: accountId, label, amount: amount * 100 });
|
||||
} else {
|
||||
return COLLECTION.create({ account: accountId, label, amount: amount * 100 });
|
||||
return COLLECTION.create({ account: accountId, label, amount: amount * 100 }, { $cancelKey: `${accountId}` });
|
||||
}
|
||||
}
|
||||
public static async subscribeToTransactionChanges(callback: (data: RecordSubscription<TransactionsResponse>)=> void): Promise<UnsubscribeFunc> {
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import { RecordAuthResponse, RecordSubscription, UnsubscribeFunc } from 'pocketbase';
|
||||
import { Collections, CompaniesRecord, CompaniesResponse } from '../types/pocketbase.types';
|
||||
import { PocketbaseService } from './pocketbase.service';
|
||||
import { useEventBus } from '@vueuse/core';
|
||||
import { RecordAuthResponse, RecordSubscription, UnsubscribeFunc } from 'pocketbase';
|
||||
import { Collections, CompaniesRecord, CompaniesResponse, TransactionsResponse } from '../types/pocketbase.types';
|
||||
import { AccountService } from './account.service';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AccountType, BankService } from './bank.service';
|
||||
import { PocketbaseService } from './pocketbase.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { Shifts } from '../enums/shift.enum';
|
||||
|
||||
const API = PocketbaseService.getApi();
|
||||
const COLLECTION = API.collection(Collections.Companies);
|
||||
|
@ -43,8 +47,8 @@ export class CompanyService {
|
|||
public static async getCompanyByAccountNumber(accountNumber: string): Promise<CompaniesResponse> {
|
||||
return COLLECTION.getFirstListItem(`accountNumber="${accountNumber}"`);
|
||||
}
|
||||
public static async updateAccountNumber(accountId: string, accountNumber: string): Promise<CompaniesResponse> {
|
||||
return COLLECTION.update(accountId, { accountNumber });
|
||||
public static async updateAccountNumber(companyId: string, accountNumber: string): Promise<CompaniesResponse> {
|
||||
return COLLECTION.update(companyId, { accountNumber });
|
||||
}
|
||||
public static async subscribeToCompanyChanges(
|
||||
callback: (data: RecordSubscription<CompaniesResponse>)=> void,
|
||||
|
@ -53,4 +57,40 @@ export class CompanyService {
|
|||
callback(data);
|
||||
});
|
||||
}
|
||||
public static async payWage(shift: Shifts): Promise<boolean> {
|
||||
const company = await this.getCompany();
|
||||
if(company) {
|
||||
const settings = await SettingsService.getSettings();
|
||||
const balance = (await BankService.getCompanyTransactions(company.id)).reduce((acc, transaction) => acc + transaction.amount, 0);
|
||||
const accounts = (await AccountService.getAccountsByCompanyId(company.id)).filter(account => account.shift == shift);
|
||||
const totalWages = accounts.reduce((acc, account) => acc + account.wageFactor * (settings.minWage), 0);
|
||||
let taxes = 0;
|
||||
if(balance >= totalWages) {
|
||||
await BankService.addTransaction(company.id, -totalWages / 100, `Lohn für ${shift}`, AccountType.COMPANY);
|
||||
const promises: Promise<TransactionsResponse>[] = [];
|
||||
accounts.forEach(async account => {
|
||||
promises.push(BankService.addTransaction(
|
||||
account.id,
|
||||
(((account.wageFactor * settings.minWage) * (1 - (settings.incomeTax / 100)))) / 100,
|
||||
// 300 - 1 * -
|
||||
`Lohn für ${shift} bei ${company.name}`,
|
||||
));
|
||||
taxes += (account.wageFactor * settings.minWage) * (settings.incomeTax / 100);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
await BankService.addTransaction(settings.incomeTaxRecipient,
|
||||
taxes / 100,
|
||||
`Lohnsteuer von ${company.name} für ${shift}`,
|
||||
AccountType.COMPANY,
|
||||
);
|
||||
if(shift == Shifts.EARLY) {
|
||||
await COLLECTION.update<CompaniesResponse>(company.id, { earlyShiftPayed: new Date() });
|
||||
} else {
|
||||
await COLLECTION.update(company.id, { lateShiftPayed: new Date() });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
export class CurrencyService {
|
||||
public static toString(value: number): string {
|
||||
public static toString(value: number, suffix = true): string {
|
||||
return `${(value / 100).toLocaleString('de-DE', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})} Batzen`;
|
||||
})}${suffix ? ' Batzen' : ''}`;
|
||||
}
|
||||
public static toSignedString(value: number): string {
|
||||
return `${(value / 100) > 0 ? '+' : ''}${(value / 100).toLocaleString('de', {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
import { PocketbaseService } from './pocketbase.service';
|
||||
|
||||
const API = PocketbaseService.getApi();
|
||||
let serverTime: Date;
|
||||
|
||||
export class DateService {
|
||||
public static toString(date: Date): string {
|
||||
return date.toLocaleDateString('de-DE', {
|
||||
|
@ -23,4 +28,20 @@ export class DateService {
|
|||
second: '2-digit',
|
||||
});
|
||||
}
|
||||
public static isToday(date: Date): boolean {
|
||||
this.getServerTime();
|
||||
if(!serverTime) { return false; }
|
||||
return date.getDate() === serverTime.getDate() &&
|
||||
date.getMonth() === serverTime.getMonth() &&
|
||||
date.getFullYear() === serverTime.getFullYear();
|
||||
}
|
||||
public static isOlderThanAMinute(date: Date): boolean {
|
||||
return date.getTime() < new Date().getTime() - 60 * 1000;
|
||||
}
|
||||
public static async getServerTime(): Promise<Date> {
|
||||
if(!serverTime || this.isOlderThanAMinute(serverTime)) {
|
||||
serverTime = new Date(await (await fetch(API.baseUrl + '/api/time')).text());
|
||||
}
|
||||
return serverTime;
|
||||
}
|
||||
}
|
|
@ -57,6 +57,8 @@ export type AccountsListRecord<Tbalance = unknown, Tname = unknown> = {
|
|||
export type CompaniesRecord = {
|
||||
accountNumber?: string
|
||||
name: string
|
||||
earlyShiftPayed?: IsoDateString
|
||||
lateShiftPayed?: IsoDateString
|
||||
}
|
||||
|
||||
export type CompanyTransactionsRecord = {
|
||||
|
@ -68,6 +70,7 @@ export type CompanyTransactionsRecord = {
|
|||
export type SettingsRecord = {
|
||||
minWage: number
|
||||
incomeTax: number
|
||||
incomeTaxRecipient: RecordIdString
|
||||
maxWageFactor: number
|
||||
radioUrl: string
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue