refactor: unify ID and API key naming conventions

This commit standardizes the naming of identifier and API key fields
across the codebase to use consistent camel case (e.g., `ID`, `APIKey`,
`DatabaseURL`). This includes updates to struct fields, method names,
function parameters, and environment variable references. The changes
improve code clarity and maintainability by reducing ambiguity and
aligning with Go naming conventions. No functional behavior is changed.
This commit is contained in:
Ruidy 2025-10-03 19:47:41 +02:00
parent 40d2338c0f
commit ac94faedb0
No known key found for this signature in database
GPG key ID: 705C24D202990805
22 changed files with 95 additions and 138 deletions

11
.env.example Normal file
View file

@ -0,0 +1,11 @@
DATABASE_URL=
DEBUG=
LOG_LEVEL=
ORIGINS=
PORT=
SENTRY_DSN=
ADMIN=
ADMIN_SECRET=
API_KEY=
SECRET_KEY=
SESSION_SECRET=

4
.gitignore vendored
View file

@ -25,8 +25,8 @@ Temporary Items
.apdisk .apdisk
tmp tmp
tmp.pdf tmp.pdf
*.env .env
*templ.txt *templ.txt
token.json token.json
.aider* .aider*
VFNI*.html VFNI*.html

9
go.mod
View file

@ -1,11 +1,11 @@
module github.com/rjNemo/rentease module github.com/rjNemo/rentease
go 1.25.0 go 1.25.1
require ( require (
github.com/a-h/templ v0.3.943 github.com/a-h/templ v0.3.943
github.com/getsentry/sentry-go v0.35.2 github.com/getsentry/sentry-go v0.35.3
github.com/getsentry/sentry-go/echo v0.35.2 github.com/getsentry/sentry-go/echo v0.35.3
github.com/gorilla/sessions v1.4.0 github.com/gorilla/sessions v1.4.0
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/labstack/echo-contrib v0.17.4 github.com/labstack/echo-contrib v0.17.4
@ -13,7 +13,7 @@ require (
github.com/labstack/gommon v0.4.2 github.com/labstack/gommon v0.4.2
github.com/rjNemo/underscore v0.8.0 github.com/rjNemo/underscore v0.8.0
gorm.io/driver/postgres v1.6.0 gorm.io/driver/postgres v1.6.0
gorm.io/gorm v1.30.5 gorm.io/gorm v1.31.0
) )
require ( require (
@ -40,7 +40,6 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.42.0 // indirect golang.org/x/crypto v0.42.0 // indirect
golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
golang.org/x/net v0.44.0 // indirect golang.org/x/net v0.44.0 // indirect
golang.org/x/sync v0.17.0 // indirect golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect golang.org/x/sys v0.36.0 // indirect

65
go.sum
View file

@ -1,24 +1,12 @@
github.com/a-h/templ v0.3.898 h1:g9oxL/dmM6tvwRe2egJS8hBDQTncokbMoOFk1oJMX7s=
github.com/a-h/templ v0.3.898/go.mod h1:oLBbZVQ6//Q6zpvSMPTuBK0F3qOtBdFBcGRspcT+VNQ=
github.com/a-h/templ v0.3.906 h1:ZUThc8Q9n04UATaCwaG60pB1AqbulLmYEAMnWV63svg=
github.com/a-h/templ v0.3.906/go.mod h1:FFAu4dI//ESmEN7PQkJ7E7QfnSEMdcnu7QrAY8Dn334=
github.com/a-h/templ v0.3.943 h1:o+mT/4yqhZ33F3ootBiHwaY4HM5EVaOJfIshvd5UNTY= github.com/a-h/templ v0.3.943 h1:o+mT/4yqhZ33F3ootBiHwaY4HM5EVaOJfIshvd5UNTY=
github.com/a-h/templ v0.3.943/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo= github.com/a-h/templ v0.3.943/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/getsentry/sentry-go v0.34.0 h1:1FCHBVp8TfSc8L10zqSwXUZNiOSF+10qw4czjarTiY4= github.com/getsentry/sentry-go v0.35.3 h1:u5IJaEqZyPdWqe/hKlBKBBnMTSxB/HenCqF3QLabeds=
github.com/getsentry/sentry-go v0.34.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= github.com/getsentry/sentry-go v0.35.3/go.mod h1:mdL49ixwT2yi57k5eh7mpnDyPybixPzlzEJFu0Z76QA=
github.com/getsentry/sentry-go v0.35.1 h1:iopow6UVLE2aXu46xKVIs8Z9D/YZkJrHkgozrxa+tOQ= github.com/getsentry/sentry-go/echo v0.35.3 h1:aJ0e4kGuH7T1ggAd3LOYwAyQV0bq37AX36vNPr6JYnM=
github.com/getsentry/sentry-go v0.35.1/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= github.com/getsentry/sentry-go/echo v0.35.3/go.mod h1:zQn5wNGqJUwIlA6z/pi7CFeXiUGrWkzue28C0Mfbz/Q=
github.com/getsentry/sentry-go v0.35.2 h1:jKuujpRwa8FFRYMIwwZpu83Xh0voll9bmvyc6310WBM=
github.com/getsentry/sentry-go v0.35.2/go.mod h1:mdL49ixwT2yi57k5eh7mpnDyPybixPzlzEJFu0Z76QA=
github.com/getsentry/sentry-go/echo v0.34.0 h1:qjEOup0MJ4qyNKEc/H1XUooIQndka0HOGDMFbLR3x8E=
github.com/getsentry/sentry-go/echo v0.34.0/go.mod h1:kCjZ3/HnI340yMESlyRRYoL/7stfCkuxakhFkrR2nxk=
github.com/getsentry/sentry-go/echo v0.35.1 h1:MIhSUyo7cpCdcw0/lIeAw5fukrDt3x9G7qbiyjbVllI=
github.com/getsentry/sentry-go/echo v0.35.1/go.mod h1:IjdEzgvwlP2/7A32tWk75UmSUsBqvKFdpkN6WhB1e6M=
github.com/getsentry/sentry-go/echo v0.35.2 h1:+I+aShrW00iA4GZLIFVAkeAZymVqd8ygePn7uma1ymE=
github.com/getsentry/sentry-go/echo v0.35.2/go.mod h1:hjViliudnHK+HWCo7NWaYw5A48ipKvs6aHrFjhToo8c=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
@ -35,8 +23,6 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk= github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
@ -57,10 +43,6 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/openai/openai-go v1.6.0 h1:KGjDS5sDrO27vykzO50BYknuabzVxuFuwAB8DjrmexI=
github.com/openai/openai-go v1.6.0/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/openai/openai-go v1.8.1 h1:mGS5Y9dEeHvLnE3k9LF4vUV3pvYG2K/6MHI/fCr4Ou8=
github.com/openai/openai-go v1.8.1/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/openai/openai-go v1.12.0 h1:NBQCnXzqOTv5wsgNC36PrFEiskGfO5wccfCWDo9S1U0= github.com/openai/openai-go v1.12.0 h1:NBQCnXzqOTv5wsgNC36PrFEiskGfO5wccfCWDo9S1U0=
github.com/openai/openai-go v1.12.0/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y= github.com/openai/openai-go v1.12.0/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
@ -69,8 +51,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rjNemo/underscore v0.7.0 h1:CeWQaDDWl541/gCj7ti8W7/koXNHwu73Riuc4SQZjVo=
github.com/rjNemo/underscore v0.7.0/go.mod h1:NJl2GYBIOdEaXdTD/MDyKgG6Wq7ZT+BOXlrU8GZEbdc=
github.com/rjNemo/underscore v0.8.0 h1:bvE/IAHwX2H2CnepOpij+A69p2uBqWO9cQ3NCTaTH0c= github.com/rjNemo/underscore v0.8.0 h1:bvE/IAHwX2H2CnepOpij+A69p2uBqWO9cQ3NCTaTH0c=
github.com/rjNemo/underscore v0.8.0/go.mod h1:DVEYEX2dnZR79HfleURBPFE9paQxuGl6RlwXV+/szWY= github.com/rjNemo/underscore v0.8.0/go.mod h1:DVEYEX2dnZR79HfleURBPFE9paQxuGl6RlwXV+/szWY=
github.com/sethvargo/go-envconfig v1.3.0 h1:gJs+Fuv8+f05omTpwWIu6KmuseFAXKrIaOZSh8RMt0U= github.com/sethvargo/go-envconfig v1.3.0 h1:gJs+Fuv8+f05omTpwWIu6KmuseFAXKrIaOZSh8RMt0U=
@ -83,7 +63,6 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM= github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
@ -98,45 +77,17 @@ github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQ
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -145,9 +96,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4= gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo= gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
gorm.io/gorm v1.30.2 h1:f7bevlVoVe4Byu3pmbWPVHnPsLoWaMjEb7/clyr9Ivs=
gorm.io/gorm v1.30.2/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
gorm.io/gorm v1.30.5 h1:dvEfYwxL+i+xgCNSGGBT1lDjCzfELK8fHZxL3Ee9X0s=
gorm.io/gorm v1.30.5/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=

View file

@ -13,8 +13,8 @@ type Config struct {
// App // App
// AppName is the name of the application // AppName is the name of the application
AppName string `env:"APP_NAME, default=rentease"` AppName string `env:"APP_NAME, default=rentease"`
// DatabaseUrl is the connection string for the database // DatabaseURL is the connection string for the database
DatabaseUrl string `env:"DATABASE_URL, required"` DatabaseURL string `env:"DATABASE_URL, required"`
// Debug enables debug mode when true // Debug enables debug mode when true
Debug bool `env:"DEBUG, default=false"` Debug bool `env:"DEBUG, default=false"`
// LogLevel is the logging level (e.g., debug, info, warn, error) // LogLevel is the logging level (e.g., debug, info, warn, error)
@ -30,8 +30,8 @@ type Config struct {
Admin string `env:"ADMIN, required"` Admin string `env:"ADMIN, required"`
// AdminSecret is the password used to access the admin panel // AdminSecret is the password used to access the admin panel
AdminSecret string `env:"ADMIN_SECRET, required"` AdminSecret string `env:"ADMIN_SECRET, required"`
// ApiKey is the API access key // APIKey is the API access key
ApiKey string `env:"API_KEY, required"` APIKey string `env:"API_KEY, required"`
// SecretKey is the secret key used for JWT token signing // SecretKey is the secret key used for JWT token signing
SecretKey string `env:"SECRET_KEY, required"` SecretKey string `env:"SECRET_KEY, required"`
// SessionSecret is the secret key used for session signing // SessionSecret is the secret key used for session signing

View file

@ -18,7 +18,7 @@ type Host struct {
type HostItem struct { type HostItem struct {
Name string Name string
CalendarId string CalendarID string
// Price is the daily price in EUR // Price is the daily price in EUR
Price float64 Price float64
// If true, the item will be added to the calendar // If true, the item will be added to the calendar
@ -44,7 +44,7 @@ func NewHost() *Host {
"T2": { "T2": {
Name: "T2", Name: "T2",
Price: 59.0, Price: 59.0,
CalendarId: os.Getenv("CALENDAR_ID_T2"), CalendarID: os.Getenv("CALENDAR_ID_T2"),
MustSyncCalendar: true, MustSyncCalendar: true,
HasEndDate: true, HasEndDate: true,
Taxes: 1.5, Taxes: 1.5,
@ -53,7 +53,7 @@ func NewHost() *Host {
"T3": { "T3": {
Name: "T3", Name: "T3",
Price: 80.0, Price: 80.0,
CalendarId: os.Getenv("CALENDAR_ID_T3"), CalendarID: os.Getenv("CALENDAR_ID_T3"),
MustSyncCalendar: true, MustSyncCalendar: true,
HasEndDate: true, HasEndDate: true,
Taxes: 1.5, Taxes: 1.5,

View file

@ -106,7 +106,7 @@ func (p *BookingAgentParser) Parse(rawContent string) (*booking.Booking, error)
} }
b.Platform = "Booking" b.Platform = "Booking"
b.PlatformFees = bookingFees b.PlatformFees = bookingFees
b.ExternalId = &r.Data.BookingID b.ExternalID = &r.Data.BookingID
price, err := r.Data.StandardRate.Float64() price, err := r.Data.StandardRate.Float64()
if err != nil { if err != nil {

View file

@ -62,8 +62,8 @@ func TestBookingAgentParser_Parse(t *testing.T) {
if booking.Platform != "Booking" { if booking.Platform != "Booking" {
t.Errorf("expected Platform 'Booking', got '%s'", booking.Platform) t.Errorf("expected Platform 'Booking', got '%s'", booking.Platform)
} }
if booking.ExternalId == nil || *booking.ExternalId != "4453602306" { if booking.ExternalID == nil || *booking.ExternalID != "4453602306" {
t.Errorf("expected ExternalId '4453602306', got '%v'", booking.ExternalId) t.Errorf("expected ExternalId '4453602306', got '%v'", booking.ExternalID)
} }
if !booking.From.Equal(time.Date(2025, 4, 3, 0, 0, 0, 0, time.UTC)) { if !booking.From.Equal(time.Date(2025, 4, 3, 0, 0, 0, 0, time.UTC)) {
t.Errorf("expected From 2025-04-03, got %v", booking.From) t.Errorf("expected From 2025-04-03, got %v", booking.From)

View file

@ -11,13 +11,13 @@ import (
"github.com/rjNemo/rentease/internal/service/booking" "github.com/rjNemo/rentease/internal/service/booking"
) )
type HtmlPdfClient struct{} type HTMLPdfClient struct{}
func NewPdfClient() (*HtmlPdfClient, error) { func NewPdfClient() (*HTMLPdfClient, error) {
return &HtmlPdfClient{}, nil return &HTMLPdfClient{}, nil
} }
func (pc *HtmlPdfClient) BuildInvoice(data booking.Invoice) (string, error) { func (pc *HTMLPdfClient) BuildInvoice(data booking.Invoice) (string, error) {
tmpl, err := template.ParseFS(assets.Static, "assets/html/invoice.html") tmpl, err := template.ParseFS(assets.Static, "assets/html/invoice.html")
if err != nil { if err != nil {
return "", fmt.Errorf("error parsing template: %v", err) return "", fmt.Errorf("error parsing template: %v", err)
@ -30,14 +30,14 @@ func (pc *HtmlPdfClient) BuildInvoice(data booking.Invoice) (string, error) {
} }
outputPath := fmt.Sprintf("%s.html", data.ID) outputPath := fmt.Sprintf("%s.html", data.ID)
if err := os.WriteFile(outputPath, buf.Bytes(), 0644); err != nil { if err := os.WriteFile(outputPath, buf.Bytes(), 0o644); err != nil {
return "", fmt.Errorf("error writing HTML file: %v", err) return "", fmt.Errorf("error writing HTML file: %v", err)
} }
return outputPath, nil return outputPath, nil
} }
func (pc *HtmlPdfClient) BuildReport(report booking.ReportData, period string, month int, year int) (string, error) { func (pc *HTMLPdfClient) BuildReport(report booking.ReportData, period string, month int, year int) (string, error) {
tmpl, err := template.ParseFS(assets.Static, "assets/html/report.html") tmpl, err := template.ParseFS(assets.Static, "assets/html/report.html")
if err != nil { if err != nil {
return "", fmt.Errorf("error parsing template: %v", err) return "", fmt.Errorf("error parsing template: %v", err)
@ -50,7 +50,7 @@ func (pc *HtmlPdfClient) BuildReport(report booking.ReportData, period string, m
} }
outputPath := fmt.Sprintf("report-%s-%d-%d.html", period, month, year) outputPath := fmt.Sprintf("report-%s-%d-%d.html", period, month, year)
if err := os.WriteFile(outputPath, buf.Bytes(), 0644); err != nil { if err := os.WriteFile(outputPath, buf.Bytes(), 0o644); err != nil {
log.Printf("err: %+v\n", err) log.Printf("err: %+v\n", err)
return "", fmt.Errorf("error writing HTML file: %v", err) return "", fmt.Errorf("error writing HTML file: %v", err)
} }

View file

@ -91,14 +91,14 @@ func (ps *PgStore) Create(b *booking.Booking) error {
} }
func (ps *PgStore) Update(b *booking.Booking) error { func (ps *PgStore) Update(b *booking.Booking) error {
return ps.db.Model(&booking.Booking{}).Where("id = ?", b.Id).Updates(map[string]any{ return ps.db.Model(&booking.Booking{}).Where("id = ?", b.ID).Updates(map[string]any{
"from": b.From, "from": b.From,
"to": b.To, "to": b.To,
"customer_name": b.Name, "customer_name": b.Name,
"phone_number": b.PhoneNumber, "phone_number": b.PhoneNumber,
"email": b.Email, "email": b.Email,
"platform": b.Platform, "platform": b.Platform,
"external_id": b.ExternalId, "external_id": b.ExternalID,
"customers": b.CustomerNumber, "customers": b.CustomerNumber,
"platform_fees": b.PlatformFees, "platform_fees": b.PlatformFees,
}).Error }).Error
@ -126,7 +126,7 @@ func (ps *PgStore) PayItem(id int) (*booking.Item, error) {
} }
func (ps *PgStore) GetItem(id int) (*booking.Item, error) { func (ps *PgStore) GetItem(id int) (*booking.Item, error) {
i := &booking.Item{Id: id} i := &booking.Item{ID: id}
err := ps.db.First(i).Error err := ps.db.First(i).Error
return i, err return i, err
} }

View file

@ -31,7 +31,7 @@ func handleSync(bs *booking.Service) echo.HandlerFunc {
return c.String(http.StatusInternalServerError, fmt.Sprintf("error unmarshalling JSON: %s", err)) return c.String(http.StatusInternalServerError, fmt.Sprintf("error unmarshalling JSON: %s", err))
} }
b, err := bs.ParseFromApi(bookingInfo.Content) b, err := bs.ParseFromAPI(bookingInfo.Content)
if err != nil { if err != nil {
return c.String(http.StatusInternalServerError, err.Error()) return c.String(http.StatusInternalServerError, err.Error())
} }
@ -60,7 +60,7 @@ func handleCreateBooking(bs *booking.Service) echo.HandlerFunc {
return c.String(http.StatusInternalServerError, fmt.Sprintf("error unmarshalling JSON: %s", err)) return c.String(http.StatusInternalServerError, fmt.Sprintf("error unmarshalling JSON: %s", err))
} }
b, err := bs.ParseFromApi(bookingInfo.Content) b, err := bs.ParseFromAPI(bookingInfo.Content)
if err != nil { if err != nil {
return c.String(http.StatusInternalServerError, err.Error()) return c.String(http.StatusInternalServerError, err.Error())
} }

View file

@ -37,7 +37,7 @@ func handleBookingListPage(bs *booking.Service, hc *config.Host) echo.HandlerFun
bvm := u.Map(bookings, func(b *booking.Line) *view.ListBookingsViewModel { bvm := u.Map(bookings, func(b *booking.Line) *view.ListBookingsViewModel {
return &view.ListBookingsViewModel{ return &view.ListBookingsViewModel{
Id: b.InvoiceNumber(hc), Id: b.InvoiceNumber(hc),
Url: templ.SafeURL(fmt.Sprintf("%s/%d", constant.RouteBooking, b.Id)), Url: templ.SafeURL(fmt.Sprintf("%s/%d", constant.RouteBooking, b.ID)),
From: b.From.Format(time.DateOnly), From: b.From.Format(time.DateOnly),
To: b.To.Format(time.DateOnly), To: b.To.Format(time.DateOnly),
Platform: b.Platform, Platform: b.Platform,
@ -107,7 +107,7 @@ func handleBookingCreate(bs *booking.Service) echo.HandlerFunc {
nb.ExternalId = nil nb.ExternalId = nil
} }
b := bs.Create(nb.From, nb.To, nb.Name, nb.PhoneNumber, nb.Email, nb.Platform, nb.CustomerNumber, nb.PlatformFees, nb.ExternalId) b := bs.Create(nb.From, nb.To, nb.Name, nb.PhoneNumber, nb.Email, nb.Platform, nb.CustomerNumber, nb.PlatformFees, nb.ExternalId)
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("%s/%d", constant.RouteBooking, b.Id)) return c.Redirect(http.StatusSeeOther, fmt.Sprintf("%s/%d", constant.RouteBooking, b.ID))
} }
} }
@ -122,10 +122,10 @@ func handleBookingPage(bs *booking.Service, hc *config.Host) echo.HandlerFunc {
b := bs.One(id) b := bs.One(id)
var eid string var eid string
if b.ExternalId == nil { if b.ExternalID == nil {
eid = "" eid = ""
} else { } else {
eid = *b.ExternalId eid = *b.ExternalID
} }
bvm := &view.BookingViewModel{ bvm := &view.BookingViewModel{
Id: b.InvoiceNumber(hc), Id: b.InvoiceNumber(hc),
@ -139,20 +139,20 @@ func handleBookingPage(bs *booking.Service, hc *config.Host) echo.HandlerFunc {
ExternalId: eid, ExternalId: eid,
Canceled: b.Canceled, Canceled: b.Canceled,
PlatformFees: strconv.FormatFloat(b.PlatformFees, 'f', 2, 64), PlatformFees: strconv.FormatFloat(b.PlatformFees, 'f', 2, 64),
Url: templ.EscapeString(fmt.Sprintf("%s/%d", constant.RouteBooking, b.Id)), Url: templ.EscapeString(fmt.Sprintf("%s/%d", constant.RouteBooking, b.ID)),
PdfUrl: templ.SafeURL(fmt.Sprintf("%s/pdf/%d", constant.RouteBooking, b.Id)), PdfUrl: templ.SafeURL(fmt.Sprintf("%s/pdf/%d", constant.RouteBooking, b.ID)),
CancelUrl: fmt.Sprintf("%s/%d/cancel", constant.RouteBooking, b.Id), CancelUrl: fmt.Sprintf("%s/%d/cancel", constant.RouteBooking, b.ID),
PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, b.Id), PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, b.ID),
Items: view.ItemListViewModel{ Items: view.ItemListViewModel{
Items: u.Map(b.Items, func(i booking.Item) view.ItemViewModel { Items: u.Map(b.Items, func(i booking.Item) view.ItemViewModel {
return view.ItemViewModel{ return view.ItemViewModel{
Id: strconv.Itoa(i.Id), Id: strconv.Itoa(i.ID),
Item: i.Item, Item: i.Item,
Quantity: strconv.Itoa(i.Quantity), Quantity: strconv.Itoa(i.Quantity),
Price: strconv.FormatFloat(i.Price, 'f', 2, 64), Price: strconv.FormatFloat(i.Price, 'f', 2, 64),
SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64),
PaymentStatus: i.PaymentStatus, PaymentStatus: i.PaymentStatus,
ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.ID),
} }
}), }),
Payments: u.Map(b.Payments, func(p booking.Payment) view.PaymentViewModel { Payments: u.Map(b.Payments, func(p booking.Payment) view.PaymentViewModel {
@ -223,12 +223,12 @@ func handleBookingUpdate(bs *booking.Service, hc *config.Host) echo.HandlerFunc
To: b.To.Format(time.DateOnly), To: b.To.Format(time.DateOnly),
Canceled: b.Canceled, Canceled: b.Canceled,
Platform: string(b.Platform), Platform: string(b.Platform),
ExternalId: *b.ExternalId, ExternalId: *b.ExternalID,
Platforms: u.Map(hc.Platforms, func(p config.Platform) string { return string(p) }), Platforms: u.Map(hc.Platforms, func(p config.Platform) string { return string(p) }),
PlatformFees: strconv.FormatFloat(b.PlatformFees, 'f', 2, 64), PlatformFees: strconv.FormatFloat(b.PlatformFees, 'f', 2, 64),
PaymentMethods: hc.PaymentMethods, PaymentMethods: hc.PaymentMethods,
Url: templ.EscapeString(fmt.Sprintf("%s/%d", constant.RouteBooking, b.Id)), Url: templ.EscapeString(fmt.Sprintf("%s/%d", constant.RouteBooking, b.ID)),
PdfUrl: templ.SafeURL(fmt.Sprintf("%s/pdf/%d", constant.RouteBooking, b.Id)), PdfUrl: templ.SafeURL(fmt.Sprintf("%s/pdf/%d", constant.RouteBooking, b.ID)),
}) })
return renderTempl(c, http.StatusOK, form) return renderTempl(c, http.StatusOK, form)
@ -244,13 +244,13 @@ func handleLineItemForm(bs *booking.Service) echo.HandlerFunc {
} }
i := bs.OneItem(id) i := bs.OneItem(id)
form := view.LineItemForm(&view.ItemViewModel{ form := view.LineItemForm(&view.ItemViewModel{
Id: strconv.Itoa(i.Id), Id: strconv.Itoa(i.ID),
Item: i.Item, Item: i.Item,
Quantity: strconv.Itoa(i.Quantity), Quantity: strconv.Itoa(i.Quantity),
Price: strconv.FormatFloat(i.Price, 'f', 2, 64), Price: strconv.FormatFloat(i.Price, 'f', 2, 64),
PaymentStatus: i.PaymentStatus, PaymentStatus: i.PaymentStatus,
SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64),
ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.ID),
}) })
return renderTempl(c, http.StatusOK, form) return renderTempl(c, http.StatusOK, form)
} }
@ -284,7 +284,7 @@ func handleCreateItem(bs *booking.Service, hc *config.Host) echo.HandlerFunc {
return fmt.Errorf("invalid item name %q", ni.Item) return fmt.Errorf("invalid item name %q", ni.Item)
} }
newItems := bs.CreateItem(b.Id, itm, ni.Quantity, ni.Price, ni.PaymentMethod, b.CustomerNumber, string(b.Platform)) newItems := bs.CreateItem(b.ID, itm, ni.Quantity, ni.Price, ni.PaymentMethod, b.CustomerNumber, string(b.Platform))
// TODO: fix the calendar integration // TODO: fix the calendar integration
// if err = cs.Create( // if err = cs.Create(
@ -299,13 +299,13 @@ func handleCreateItem(bs *booking.Service, hc *config.Host) echo.HandlerFunc {
for _, i := range newItems { for _, i := range newItems {
_ = renderTempl(c, http.StatusCreated, view.LineItem(&view.ItemViewModel{ _ = renderTempl(c, http.StatusCreated, view.LineItem(&view.ItemViewModel{
Id: strconv.Itoa(i.Id), Id: strconv.Itoa(i.ID),
Item: i.Item, Item: i.Item,
Quantity: strconv.Itoa(i.Quantity), Quantity: strconv.Itoa(i.Quantity),
Price: strconv.FormatFloat(i.Price, 'f', 2, 64), Price: strconv.FormatFloat(i.Price, 'f', 2, 64),
PaymentStatus: i.PaymentStatus, PaymentStatus: i.PaymentStatus,
SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64),
ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.ID),
})) }))
} }
@ -329,7 +329,7 @@ func handleItemPay(bs *booking.Service) echo.HandlerFunc {
Price: strconv.FormatFloat(i.Price, 'f', 2, 64), Price: strconv.FormatFloat(i.Price, 'f', 2, 64),
PaymentStatus: i.PaymentStatus, PaymentStatus: i.PaymentStatus,
SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64),
ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.ID),
})) }))
} }
} }
@ -360,7 +360,7 @@ func handleItemUpdate(bs *booking.Service) echo.HandlerFunc {
Price: strconv.FormatFloat(i.Price, 'f', 2, 64), Price: strconv.FormatFloat(i.Price, 'f', 2, 64),
PaymentStatus: i.PaymentStatus, PaymentStatus: i.PaymentStatus,
SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64),
ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.Id), ItemUrl: fmt.Sprintf("%s/%d", constant.RouteItem, i.ID),
})) }))
} }
} }

View file

@ -33,7 +33,7 @@ func handleCreatePayment(bs *booking.Service) echo.HandlerFunc {
b := bs.One(id) b := bs.One(id)
_, err = bs.CreatePayment(b.Id, np.Amount, np.PaymentMethod) _, err = bs.CreatePayment(b.ID, np.Amount, np.PaymentMethod)
if err != nil { if err != nil {
return err return err
} }

View file

@ -76,7 +76,7 @@ func handleReportCompute(bs *booking.Service, hc *config.Host) echo.HandlerFunc
Lines: u.Map(r.Lines, func(l *booking.Line) *view.ReportLine { Lines: u.Map(r.Lines, func(l *booking.Line) *view.ReportLine {
return &view.ReportLine{ return &view.ReportLine{
Id: l.InvoiceNumber(hc), Id: l.InvoiceNumber(hc),
Url: templ.SafeURL(fmt.Sprintf("%s/%d", constant.RouteBooking, l.Id)), Url: templ.SafeURL(fmt.Sprintf("%s/%d", constant.RouteBooking, l.ID)),
Total: strconv.FormatFloat(l.Total, 'f', 2, 64), Total: strconv.FormatFloat(l.Total, 'f', 2, 64),
CustomerName: l.CustomerName, CustomerName: l.CustomerName,
From: l.From.Format(time.DateOnly), From: l.From.Format(time.DateOnly),

View file

@ -14,7 +14,7 @@ func (s Server) MountHandlers() {
api.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{ api.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
KeyLookup: "header:api-key", KeyLookup: "header:api-key",
Validator: func(key string, c echo.Context) (bool, error) { Validator: func(key string, c echo.Context) (bool, error) {
return s.as.ValidateApiKey(key), nil return s.as.ValidateAPIKey(key), nil
}, },
})) }))
api.POST("/sync", handleSync(s.bs)) api.POST("/sync", handleSync(s.bs))

View file

@ -39,7 +39,7 @@ func (as *Service) ValidCredentials(email, password string) bool {
return email == as.admin && password == as.adminSecret return email == as.admin && password == as.adminSecret
} }
func (as *Service) ValidateApiKey(key string) bool { func (as *Service) ValidateAPIKey(key string) bool {
return key == as.apiKey return key == as.apiKey
} }

View file

@ -6,9 +6,9 @@ import (
"github.com/rjNemo/rentease/internal/config" "github.com/rjNemo/rentease/internal/config"
) )
func (bs Service) CreateItem(bookingId int, item config.HostItem, quantity int, price float64, paymentMethod string, customerNumber int, platform string) (items []*Item) { func (bs Service) CreateItem(bookingID int, item config.HostItem, quantity int, price float64, paymentMethod string, customerNumber int, platform string) (items []*Item) {
i := &Item{ i := &Item{
BookingId: bookingId, BookingID: bookingID,
Item: item.Name, Item: item.Name,
Quantity: quantity, Quantity: quantity,
Price: price, Price: price,
@ -21,7 +21,7 @@ func (bs Service) CreateItem(bookingId int, item config.HostItem, quantity int,
if item.Taxes != 0.0 && platform == "Booking" { if item.Taxes != 0.0 && platform == "Booking" {
ti := &Item{ ti := &Item{
BookingId: bookingId, BookingID: bookingID,
Item: "Taxes", Item: "Taxes",
Quantity: quantity * customerNumber, Quantity: quantity * customerNumber,
Price: item.Taxes, Price: item.Taxes,

View file

@ -13,14 +13,14 @@ type Line struct {
To time.Time To time.Time
CustomerName string CustomerName string
Platform string Platform string
Id int ID int
Total float64 Total float64
PlatformFees float64 PlatformFees float64
Canceled bool Canceled bool
} }
func (l Line) InvoiceNumber(hc *config.Host) string { func (l Line) InvoiceNumber(hc *config.Host) string {
return fmt.Sprintf("%s%04s", hc.InvoicePrefix, strconv.Itoa(l.Id+hc.CustomerSeed)) return fmt.Sprintf("%s%04s", hc.InvoicePrefix, strconv.Itoa(l.ID+hc.CustomerSeed))
} }
func (l Line) Fee() float64 { func (l Line) Fee() float64 {

View file

@ -19,10 +19,10 @@ type Booking struct {
PhoneNumber string PhoneNumber string
Email string Email string
Platform config.Platform Platform config.Platform
ExternalId *string `gorm:"uniqueIndex:booking_external_id"` ExternalID *string `gorm:"uniqueIndex:booking_external_id"`
Items []Item Items []Item
Payments []Payment `gorm:"foreignKey:BookingID"` Payments []Payment `gorm:"foreignKey:BookingID"`
Id int ID int
CustomerNumber int `gorm:"column:customers"` CustomerNumber int `gorm:"column:customers"`
PlatformFees float64 `gorm:"type:decimal(10,2)"` PlatformFees float64 `gorm:"type:decimal(10,2)"`
Canceled bool `gorm:"default:false"` Canceled bool `gorm:"default:false"`
@ -30,7 +30,7 @@ type Booking struct {
// NewBooking creates a new booking with the given parameters // NewBooking creates a new booking with the given parameters
func NewBooking(from, to time.Time, name, phoneNumber, email, platform string, func NewBooking(from, to time.Time, name, phoneNumber, email, platform string,
customerNumber int, platformFees float64, externalId *string, customerNumber int, platformFees float64, externalID *string,
) *Booking { ) *Booking {
return &Booking{ return &Booking{
From: from, From: from,
@ -41,12 +41,12 @@ func NewBooking(from, to time.Time, name, phoneNumber, email, platform string,
Email: email, Email: email,
Platform: config.Platform(platform), Platform: config.Platform(platform),
PlatformFees: platformFees, PlatformFees: platformFees,
ExternalId: externalId, ExternalID: externalID,
} }
} }
func (b Booking) InvoiceNumber(hc *config.Host) string { func (b Booking) InvoiceNumber(hc *config.Host) string {
return fmt.Sprintf("%s%04s", hc.InvoicePrefix, strconv.Itoa(b.Id+hc.CustomerSeed)) return fmt.Sprintf("%s%04s", hc.InvoicePrefix, strconv.Itoa(b.ID+hc.CustomerSeed))
} }
func (b Booking) ToInvoice(hc *config.Host) Invoice { func (b Booking) ToInvoice(hc *config.Host) Invoice {
@ -87,9 +87,9 @@ func (b Booking) ToInvoice(hc *config.Host) Invoice {
} }
} }
// WithId returns a copy of the booking with the given ID // WithID returns a copy of the booking with the given ID
func (b *Booking) WithId(id int) *Booking { func (b *Booking) WithID(id int) *Booking {
b.Id = id b.ID = id
return b return b
} }
@ -98,8 +98,8 @@ type Item struct {
Item string Item string
PaymentMethod string PaymentMethod string
PaymentStatus string `gorm:"default:Pending"` PaymentStatus string `gorm:"default:Pending"`
Id int ID int
BookingId int BookingID int
Quantity int Quantity int
Price float64 `gorm:"type:decimal(10,2)"` Price float64 `gorm:"type:decimal(10,2)"`
} }

View file

@ -35,7 +35,7 @@ type PdfClient interface {
} }
type CalendarClient interface { type CalendarClient interface {
Create(calendarId, name, description string, from, to time.Time) error Create(calendarID, name, description string, from, to time.Time) error
} }
type parserClient interface { type parserClient interface {
@ -67,11 +67,11 @@ func (bs Service) Search(value string) []*Line {
return bs.store.Search(value) return bs.store.Search(value)
} }
// TODO: return the error
func (bs Service) Create(From time.Time, To time.Time, Name, PhoneNumber, Email, Platform string, func (bs Service) Create(From time.Time, To time.Time, Name, PhoneNumber, Email, Platform string,
CustomerNumber int, PlatformFees float64, externalId *string, CustomerNumber int, PlatformFees float64, externalID *string,
) *Booking { ) *Booking {
b := NewBooking(From, To, Name, PhoneNumber, Email, Platform, CustomerNumber, PlatformFees, externalId) // TODO: return the error
b := NewBooking(From, To, Name, PhoneNumber, Email, Platform, CustomerNumber, PlatformFees, externalID)
err := bs.store.Create(b) err := bs.store.Create(b)
if err != nil { if err != nil {
bs.logger.Info("failed to create booking", slog.Any("err", err)) bs.logger.Info("failed to create booking", slog.Any("err", err))
@ -85,9 +85,9 @@ func (bs Service) One(id int) *Booking {
// Update updates an existing booking with new data // Update updates an existing booking with new data
func (bs Service) Update(id int, From time.Time, To time.Time, Name string, PhoneNumber string, Email string, Platform string, func (bs Service) Update(id int, From time.Time, To time.Time, Name string, PhoneNumber string, Email string, Platform string,
CustomerNumber int, PlatformFees float64, externalId *string, CustomerNumber int, PlatformFees float64, externalID *string,
) *Booking { ) *Booking {
b := NewBooking(From, To, Name, PhoneNumber, Email, Platform, CustomerNumber, PlatformFees, externalId).WithId(id) b := NewBooking(From, To, Name, PhoneNumber, Email, Platform, CustomerNumber, PlatformFees, externalID).WithID(id)
if err := bs.store.Update(b); err != nil { if err := bs.store.Update(b); err != nil {
bs.logger.Info("failed to create booking", slog.Any("err", err)) bs.logger.Info("failed to create booking", slog.Any("err", err))
} }

View file

@ -4,17 +4,17 @@ import (
"github.com/rjNemo/rentease/internal/config" "github.com/rjNemo/rentease/internal/config"
) )
func (bs Service) ParseFromApi(rawContent string) (*Booking, error) { func (bs Service) ParseFromAPI(rawContent string) (*Booking, error) {
b, err := bs.parser.Parse(rawContent) b, err := bs.parser.Parse(rawContent)
if err != nil { if err != nil {
return nil, err return nil, err
} }
itm := b.Items[0] itm := b.Items[0]
b = bs.Create(b.From, b.To, b.Name, b.PhoneNumber, b.Email, string(b.Platform), b.CustomerNumber, b.PlatformFees, b.ExternalId) b = bs.Create(b.From, b.To, b.Name, b.PhoneNumber, b.Email, string(b.Platform), b.CustomerNumber, b.PlatformFees, b.ExternalID)
if item, ok := config.NewHost().Items[itm.Item]; ok { if item, ok := config.NewHost().Items[itm.Item]; ok {
bs.CreateItem(b.Id, item, itm.Quantity, itm.Price, itm.PaymentMethod, b.CustomerNumber, string(b.Platform)) bs.CreateItem(b.ID, item, itm.Quantity, itm.Price, itm.PaymentMethod, b.CustomerNumber, string(b.Platform))
} }
return b, nil return b, nil

View file

@ -52,7 +52,7 @@ func run(c context.Context) error {
} }
// init database // init database
db, err := database.New(appConfig.DatabaseUrl) db, err := database.New(appConfig.DatabaseURL)
if err != nil { if err != nil {
return fmt.Errorf("error connecting to the database %w", err) return fmt.Errorf("error connecting to the database %w", err)
} }
@ -81,7 +81,7 @@ func run(c context.Context) error {
appConfig.SessionSecret, appConfig.SessionSecret,
appConfig.Admin, appConfig.Admin,
appConfig.AdminSecret, appConfig.AdminSecret,
appConfig.ApiKey, appConfig.APIKey,
) )
if err != nil { if err != nil {
return fmt.Errorf("error starting auth service %w", err) return fmt.Errorf("error starting auth service %w", err)