diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b07b4af --- /dev/null +++ b/.env.example @@ -0,0 +1,11 @@ +DATABASE_URL= +DEBUG= +LOG_LEVEL= +ORIGINS= +PORT= +SENTRY_DSN= +ADMIN= +ADMIN_SECRET= +API_KEY= +SECRET_KEY= +SESSION_SECRET= diff --git a/.gitignore b/.gitignore index b541175..ea18ce3 100644 --- a/.gitignore +++ b/.gitignore @@ -25,8 +25,8 @@ Temporary Items .apdisk tmp tmp.pdf -*.env +.env *templ.txt token.json .aider* -VFNI*.html \ No newline at end of file +VFNI*.html diff --git a/go.mod b/go.mod index fc92e15..9903582 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/rjNemo/rentease -go 1.25.0 +go 1.25.1 require ( github.com/a-h/templ v0.3.943 - github.com/getsentry/sentry-go v0.35.2 - github.com/getsentry/sentry-go/echo v0.35.2 + github.com/getsentry/sentry-go v0.35.3 + github.com/getsentry/sentry-go/echo v0.35.3 github.com/gorilla/sessions v1.4.0 github.com/joho/godotenv v1.5.1 github.com/labstack/echo-contrib v0.17.4 @@ -13,7 +13,7 @@ require ( github.com/labstack/gommon v0.4.2 github.com/rjNemo/underscore v0.8.0 gorm.io/driver/postgres v1.6.0 - gorm.io/gorm v1.30.5 + gorm.io/gorm v1.31.0 ) require ( @@ -40,7 +40,6 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // 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/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect diff --git a/go.sum b/go.sum index 33ac292..1326c7f 100644 --- a/go.sum +++ b/go.sum @@ -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/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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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.34.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= -github.com/getsentry/sentry-go v0.35.1 h1:iopow6UVLE2aXu46xKVIs8Z9D/YZkJrHkgozrxa+tOQ= -github.com/getsentry/sentry-go v0.35.1/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= -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/getsentry/sentry-go v0.35.3 h1:u5IJaEqZyPdWqe/hKlBKBBnMTSxB/HenCqF3QLabeds= +github.com/getsentry/sentry-go v0.35.3/go.mod h1:mdL49ixwT2yi57k5eh7mpnDyPybixPzlzEJFu0Z76QA= +github.com/getsentry/sentry-go/echo v0.35.3 h1:aJ0e4kGuH7T1ggAd3LOYwAyQV0bq37AX36vNPr6JYnM= +github.com/getsentry/sentry-go/echo v0.35.3/go.mod h1:zQn5wNGqJUwIlA6z/pi7CFeXiUGrWkzue28C0Mfbz/Q= 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/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/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= 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/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= 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-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/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/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/go.mod h1:DVEYEX2dnZR79HfleURBPFE9paQxuGl6RlwXV+/szWY= 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.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= 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.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM= 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= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 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/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/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/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 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/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/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/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= 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= 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/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= -gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= -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= +gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY= +gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= diff --git a/internal/config/config.go b/internal/config/config.go index e63b3a7..5dde253 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -13,8 +13,8 @@ type Config struct { // App // AppName is the name of the application AppName string `env:"APP_NAME, default=rentease"` - // DatabaseUrl is the connection string for the database - DatabaseUrl string `env:"DATABASE_URL, required"` + // DatabaseURL is the connection string for the database + DatabaseURL string `env:"DATABASE_URL, required"` // Debug enables debug mode when true Debug bool `env:"DEBUG, default=false"` // LogLevel is the logging level (e.g., debug, info, warn, error) @@ -30,8 +30,8 @@ type Config struct { Admin string `env:"ADMIN, required"` // AdminSecret is the password used to access the admin panel AdminSecret string `env:"ADMIN_SECRET, required"` - // ApiKey is the API access key - ApiKey string `env:"API_KEY, required"` + // APIKey is the API access key + APIKey string `env:"API_KEY, required"` // SecretKey is the secret key used for JWT token signing SecretKey string `env:"SECRET_KEY, required"` // SessionSecret is the secret key used for session signing diff --git a/internal/config/host.go b/internal/config/host.go index 0ea6cd0..3477cf4 100644 --- a/internal/config/host.go +++ b/internal/config/host.go @@ -18,7 +18,7 @@ type Host struct { type HostItem struct { Name string - CalendarId string + CalendarID string // Price is the daily price in EUR Price float64 // If true, the item will be added to the calendar @@ -44,7 +44,7 @@ func NewHost() *Host { "T2": { Name: "T2", Price: 59.0, - CalendarId: os.Getenv("CALENDAR_ID_T2"), + CalendarID: os.Getenv("CALENDAR_ID_T2"), MustSyncCalendar: true, HasEndDate: true, Taxes: 1.5, @@ -53,7 +53,7 @@ func NewHost() *Host { "T3": { Name: "T3", Price: 80.0, - CalendarId: os.Getenv("CALENDAR_ID_T3"), + CalendarID: os.Getenv("CALENDAR_ID_T3"), MustSyncCalendar: true, HasEndDate: true, Taxes: 1.5, diff --git a/internal/driver/parser/client.go b/internal/driver/parser/client.go index da95697..ca3e299 100644 --- a/internal/driver/parser/client.go +++ b/internal/driver/parser/client.go @@ -106,7 +106,7 @@ func (p *BookingAgentParser) Parse(rawContent string) (*booking.Booking, error) } b.Platform = "Booking" b.PlatformFees = bookingFees - b.ExternalId = &r.Data.BookingID + b.ExternalID = &r.Data.BookingID price, err := r.Data.StandardRate.Float64() if err != nil { diff --git a/internal/driver/parser/parser_test.go b/internal/driver/parser/parser_test.go index a4467c8..88036b7 100644 --- a/internal/driver/parser/parser_test.go +++ b/internal/driver/parser/parser_test.go @@ -62,8 +62,8 @@ func TestBookingAgentParser_Parse(t *testing.T) { if booking.Platform != "Booking" { t.Errorf("expected Platform 'Booking', got '%s'", booking.Platform) } - if booking.ExternalId == nil || *booking.ExternalId != "4453602306" { - t.Errorf("expected ExternalId '4453602306', got '%v'", booking.ExternalId) + if booking.ExternalID == nil || *booking.ExternalID != "4453602306" { + t.Errorf("expected ExternalId '4453602306', got '%v'", booking.ExternalID) } 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) diff --git a/internal/driver/pdf/html.go b/internal/driver/pdf/html.go index 893b872..7ad3cc5 100644 --- a/internal/driver/pdf/html.go +++ b/internal/driver/pdf/html.go @@ -11,13 +11,13 @@ import ( "github.com/rjNemo/rentease/internal/service/booking" ) -type HtmlPdfClient struct{} +type HTMLPdfClient struct{} -func NewPdfClient() (*HtmlPdfClient, error) { - return &HtmlPdfClient{}, nil +func NewPdfClient() (*HTMLPdfClient, error) { + 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") if err != nil { 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) - 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 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") if err != nil { 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) - 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) return "", fmt.Errorf("error writing HTML file: %v", err) } diff --git a/internal/repository/booking/pg_store.go b/internal/repository/booking/pg_store.go index 2ee35bb..22818d8 100644 --- a/internal/repository/booking/pg_store.go +++ b/internal/repository/booking/pg_store.go @@ -91,14 +91,14 @@ func (ps *PgStore) Create(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, "to": b.To, "customer_name": b.Name, "phone_number": b.PhoneNumber, "email": b.Email, "platform": b.Platform, - "external_id": b.ExternalId, + "external_id": b.ExternalID, "customers": b.CustomerNumber, "platform_fees": b.PlatformFees, }).Error @@ -126,7 +126,7 @@ func (ps *PgStore) PayItem(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 return i, err } diff --git a/internal/server/handle_api_sync.go b/internal/server/handle_api_sync.go index 8225ea4..4ab979a 100644 --- a/internal/server/handle_api_sync.go +++ b/internal/server/handle_api_sync.go @@ -31,7 +31,7 @@ func handleSync(bs *booking.Service) echo.HandlerFunc { 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 { 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)) } - b, err := bs.ParseFromApi(bookingInfo.Content) + b, err := bs.ParseFromAPI(bookingInfo.Content) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } diff --git a/internal/server/handle_bookings.go b/internal/server/handle_bookings.go index 1d4b07f..a9fa5d5 100644 --- a/internal/server/handle_bookings.go +++ b/internal/server/handle_bookings.go @@ -37,7 +37,7 @@ func handleBookingListPage(bs *booking.Service, hc *config.Host) echo.HandlerFun bvm := u.Map(bookings, func(b *booking.Line) *view.ListBookingsViewModel { return &view.ListBookingsViewModel{ 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), To: b.To.Format(time.DateOnly), Platform: b.Platform, @@ -107,7 +107,7 @@ func handleBookingCreate(bs *booking.Service) echo.HandlerFunc { nb.ExternalId = nil } 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) var eid string - if b.ExternalId == nil { + if b.ExternalID == nil { eid = "" } else { - eid = *b.ExternalId + eid = *b.ExternalID } bvm := &view.BookingViewModel{ Id: b.InvoiceNumber(hc), @@ -139,20 +139,20 @@ func handleBookingPage(bs *booking.Service, hc *config.Host) echo.HandlerFunc { ExternalId: eid, Canceled: b.Canceled, PlatformFees: strconv.FormatFloat(b.PlatformFees, 'f', 2, 64), - Url: templ.EscapeString(fmt.Sprintf("%s/%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), - PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, 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)), + CancelUrl: fmt.Sprintf("%s/%d/cancel", constant.RouteBooking, b.ID), + PaymentUrl: fmt.Sprintf("%s/%d", constant.RoutePayment, b.ID), Items: view.ItemListViewModel{ Items: u.Map(b.Items, func(i booking.Item) view.ItemViewModel { return view.ItemViewModel{ - Id: strconv.Itoa(i.Id), + Id: strconv.Itoa(i.ID), Item: i.Item, Quantity: strconv.Itoa(i.Quantity), Price: strconv.FormatFloat(i.Price, 'f', 2, 64), SubTotal: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), 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 { @@ -223,12 +223,12 @@ func handleBookingUpdate(bs *booking.Service, hc *config.Host) echo.HandlerFunc To: b.To.Format(time.DateOnly), Canceled: b.Canceled, Platform: string(b.Platform), - ExternalId: *b.ExternalId, + ExternalId: *b.ExternalID, Platforms: u.Map(hc.Platforms, func(p config.Platform) string { return string(p) }), PlatformFees: strconv.FormatFloat(b.PlatformFees, 'f', 2, 64), PaymentMethods: hc.PaymentMethods, - Url: templ.EscapeString(fmt.Sprintf("%s/%d", constant.RouteBooking, b.Id)), - PdfUrl: templ.SafeURL(fmt.Sprintf("%s/pdf/%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)), }) return renderTempl(c, http.StatusOK, form) @@ -244,13 +244,13 @@ func handleLineItemForm(bs *booking.Service) echo.HandlerFunc { } i := bs.OneItem(id) form := view.LineItemForm(&view.ItemViewModel{ - Id: strconv.Itoa(i.Id), + Id: strconv.Itoa(i.ID), Item: i.Item, Quantity: strconv.Itoa(i.Quantity), Price: strconv.FormatFloat(i.Price, 'f', 2, 64), PaymentStatus: i.PaymentStatus, 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) } @@ -284,7 +284,7 @@ func handleCreateItem(bs *booking.Service, hc *config.Host) echo.HandlerFunc { 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 // if err = cs.Create( @@ -299,13 +299,13 @@ func handleCreateItem(bs *booking.Service, hc *config.Host) echo.HandlerFunc { for _, i := range newItems { _ = renderTempl(c, http.StatusCreated, view.LineItem(&view.ItemViewModel{ - Id: strconv.Itoa(i.Id), + Id: strconv.Itoa(i.ID), Item: i.Item, Quantity: strconv.Itoa(i.Quantity), Price: strconv.FormatFloat(i.Price, 'f', 2, 64), PaymentStatus: i.PaymentStatus, 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), PaymentStatus: i.PaymentStatus, 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), PaymentStatus: i.PaymentStatus, 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), })) } } diff --git a/internal/server/handle_payments.go b/internal/server/handle_payments.go index 6d36245..cfaad51 100644 --- a/internal/server/handle_payments.go +++ b/internal/server/handle_payments.go @@ -33,7 +33,7 @@ func handleCreatePayment(bs *booking.Service) echo.HandlerFunc { 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 { return err } diff --git a/internal/server/handle_reports.go b/internal/server/handle_reports.go index 385b152..996e907 100644 --- a/internal/server/handle_reports.go +++ b/internal/server/handle_reports.go @@ -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 { return &view.ReportLine{ 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), CustomerName: l.CustomerName, From: l.From.Format(time.DateOnly), diff --git a/internal/server/routes.go b/internal/server/routes.go index 4f57291..8bb055d 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -14,7 +14,7 @@ func (s Server) MountHandlers() { api.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{ KeyLookup: "header:api-key", 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)) diff --git a/internal/service/auth/service.go b/internal/service/auth/service.go index 44cf0b2..b91e6ee 100644 --- a/internal/service/auth/service.go +++ b/internal/service/auth/service.go @@ -39,7 +39,7 @@ func (as *Service) ValidCredentials(email, password string) bool { 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 } diff --git a/internal/service/booking/item.go b/internal/service/booking/item.go index 8149bae..ed977ef 100644 --- a/internal/service/booking/item.go +++ b/internal/service/booking/item.go @@ -6,9 +6,9 @@ import ( "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{ - BookingId: bookingId, + BookingID: bookingID, Item: item.Name, Quantity: quantity, Price: price, @@ -21,7 +21,7 @@ func (bs Service) CreateItem(bookingId int, item config.HostItem, quantity int, if item.Taxes != 0.0 && platform == "Booking" { ti := &Item{ - BookingId: bookingId, + BookingID: bookingID, Item: "Taxes", Quantity: quantity * customerNumber, Price: item.Taxes, diff --git a/internal/service/booking/line.go b/internal/service/booking/line.go index f686c43..e8c190b 100644 --- a/internal/service/booking/line.go +++ b/internal/service/booking/line.go @@ -13,14 +13,14 @@ type Line struct { To time.Time CustomerName string Platform string - Id int + ID int Total float64 PlatformFees float64 Canceled bool } 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 { diff --git a/internal/service/booking/models.go b/internal/service/booking/models.go index 0524afe..bf9b87e 100644 --- a/internal/service/booking/models.go +++ b/internal/service/booking/models.go @@ -19,10 +19,10 @@ type Booking struct { PhoneNumber string Email string Platform config.Platform - ExternalId *string `gorm:"uniqueIndex:booking_external_id"` + ExternalID *string `gorm:"uniqueIndex:booking_external_id"` Items []Item Payments []Payment `gorm:"foreignKey:BookingID"` - Id int + ID int CustomerNumber int `gorm:"column:customers"` PlatformFees float64 `gorm:"type:decimal(10,2)"` Canceled bool `gorm:"default:false"` @@ -30,7 +30,7 @@ type Booking struct { // NewBooking creates a new booking with the given parameters func NewBooking(from, to time.Time, name, phoneNumber, email, platform string, - customerNumber int, platformFees float64, externalId *string, + customerNumber int, platformFees float64, externalID *string, ) *Booking { return &Booking{ From: from, @@ -41,12 +41,12 @@ func NewBooking(from, to time.Time, name, phoneNumber, email, platform string, Email: email, Platform: config.Platform(platform), PlatformFees: platformFees, - ExternalId: externalId, + ExternalID: externalID, } } 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 { @@ -87,9 +87,9 @@ func (b Booking) ToInvoice(hc *config.Host) Invoice { } } -// WithId returns a copy of the booking with the given ID -func (b *Booking) WithId(id int) *Booking { - b.Id = id +// WithID returns a copy of the booking with the given ID +func (b *Booking) WithID(id int) *Booking { + b.ID = id return b } @@ -98,8 +98,8 @@ type Item struct { Item string PaymentMethod string PaymentStatus string `gorm:"default:Pending"` - Id int - BookingId int + ID int + BookingID int Quantity int Price float64 `gorm:"type:decimal(10,2)"` } diff --git a/internal/service/booking/service.go b/internal/service/booking/service.go index e8e2892..d0074d1 100644 --- a/internal/service/booking/service.go +++ b/internal/service/booking/service.go @@ -35,7 +35,7 @@ type PdfClient 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 { @@ -67,11 +67,11 @@ func (bs Service) Search(value string) []*Line { return bs.store.Search(value) } -// TODO: return the error 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 { - 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) if err != nil { 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 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 { - 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 { bs.logger.Info("failed to create booking", slog.Any("err", err)) } diff --git a/internal/service/booking/sync.go b/internal/service/booking/sync.go index 575982e..17fb721 100644 --- a/internal/service/booking/sync.go +++ b/internal/service/booking/sync.go @@ -4,17 +4,17 @@ import ( "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) if err != nil { return nil, err } 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 { - 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 diff --git a/main.go b/main.go index 21547ff..ed17a3b 100644 --- a/main.go +++ b/main.go @@ -52,7 +52,7 @@ func run(c context.Context) error { } // init database - db, err := database.New(appConfig.DatabaseUrl) + db, err := database.New(appConfig.DatabaseURL) if err != nil { return fmt.Errorf("error connecting to the database %w", err) } @@ -81,7 +81,7 @@ func run(c context.Context) error { appConfig.SessionSecret, appConfig.Admin, appConfig.AdminSecret, - appConfig.ApiKey, + appConfig.APIKey, ) if err != nil { return fmt.Errorf("error starting auth service %w", err)