From cb2d3cb423ae21c25ca350a2814f93101b45a8f8 Mon Sep 17 00:00:00 2001 From: Yassine R Date: Thu, 5 Oct 2023 22:06:54 +0200 Subject: [PATCH] feat(data): add soliguide & data-inclusion dataset --- .../dev/templates/backend.sealed-secret.yaml | 8 ++ .../templates/backend.sealed-secret.yaml | 8 ++ .../db/dumps/domifa_test.postgres.custom.gz | Bin 88132 -> 92310 bytes ...domifa_test.postgres.restore-data-only.sql | 30 ++++- ...st.postgres.truncate-restore-data-only.sql | 30 ++++- docker-compose.local.yml | 2 +- docker-compose.tests.yml | 2 +- packages/backend/.env.backend.dev.example.env | 6 + .../.env.backend.test.local.example.env | 5 + .../backend/.env.preset/local-dev.preset.env | 5 + .../1696369714284-auto-migration.ts | 47 +++++++ .../1603812391580-pr-env-create-database.ts | 49 +++++++ .../src/config/domifaConfig.service.ts | 15 ++- .../src/config/model/DomifaConfig.type.ts | 6 + .../src/config/model/DomifaEnv.type.ts | 4 + .../src/database/entities/monitoring/index.ts | 1 + .../OpenDataPlaceTable.typeorm.ts | 58 ++++++++ .../entities/open-data-place/index.ts | 2 + .../src/database/services/place/index.ts | 2 + .../place/open-data-place-repository.ts | 21 +++ .../src/open-data-places/cleanAddress.ts | 42 ++++++ .../DataInclusionPlace.interface.ts | 38 ++++++ .../interfaces/OpenDataPlace.interface.ts | 17 +++ .../interfaces/SoliguidePlace.interface.ts | 26 ++++ .../src/open-data-places/interfaces/index.ts | 4 + .../open-data-places/load-data-inclusion.ts | 125 ++++++++++++++++++ .../src/open-data-places/load-domifa.ts | 64 +++++++++ .../src/open-data-places/load-soliguide.ts | 114 ++++++++++++++++ packages/backend/src/run-app.ts | 11 ++ 29 files changed, 725 insertions(+), 17 deletions(-) create mode 100644 packages/backend/src/_migrations/1696369714284-auto-migration.ts create mode 100644 packages/backend/src/database/entities/open-data-place/OpenDataPlaceTable.typeorm.ts create mode 100644 packages/backend/src/database/entities/open-data-place/index.ts create mode 100644 packages/backend/src/database/services/place/index.ts create mode 100644 packages/backend/src/database/services/place/open-data-place-repository.ts create mode 100644 packages/backend/src/open-data-places/cleanAddress.ts create mode 100644 packages/backend/src/open-data-places/interfaces/DataInclusionPlace.interface.ts create mode 100644 packages/backend/src/open-data-places/interfaces/OpenDataPlace.interface.ts create mode 100644 packages/backend/src/open-data-places/interfaces/SoliguidePlace.interface.ts create mode 100644 packages/backend/src/open-data-places/interfaces/index.ts create mode 100644 packages/backend/src/open-data-places/load-data-inclusion.ts create mode 100644 packages/backend/src/open-data-places/load-domifa.ts create mode 100644 packages/backend/src/open-data-places/load-soliguide.ts diff --git a/.kontinuous/env/dev/templates/backend.sealed-secret.yaml b/.kontinuous/env/dev/templates/backend.sealed-secret.yaml index 254c50869f..f45f45b7c7 100644 --- a/.kontinuous/env/dev/templates/backend.sealed-secret.yaml +++ b/.kontinuous/env/dev/templates/backend.sealed-secret.yaml @@ -30,6 +30,14 @@ spec: AgBVXSFM2Y5dytUjYcyBFKVX+R3guA8uJFi4xVnLvcPBmQ4w74tYE7nRLDJKdvYLPHWcsb0gW+i7vBewxJrh/qiH/MTABB77l29d2JZ1/Xoz1yDvHoCZ/WJdKQaqs/vk8ZidkGk+E4ue0M7IRxm8AyptrW25d9AOarWB7AZwKPr7538OLW2PjSAIongqNq7sKXXY3j8gBOYCgIXH0pi+ZM9gCe9wacMLX3oWKJFkDsDAI+gin3y2ehlaBlDt2Ws9IqYsufkxYqimyri6d2r6JsmgMK1vqzxjqHaS1oxpzclSVQf+gvA28cq+QH71v9ToWh/J1E/poIZH/TSW71BcT84Mvo41ncDW7TthJ2ogal+VhWJaIzbMA2n19NQjGxzOFIlnK2W112P0dMaVGqa+22VzYqTbMFTBbsQGpzVZvkDY4x9qvxRoxyl0IqWNNJsHcjkXTUSFXdHMi7/faO/NHWuR4p3CHRP+sk7kfkDXaFy4qd3HF84S4TGJUXbDW6CDAT2ogz4IoZnZ1LR5xdlzwKyaC9rx1d3872klGjYSQHXnqgkPbW8B6akB1Umg72+SG5Lh5tCrk92phUPDNS2bsAHH3n1N5bhLEScTj/mG7v4uIi14AeR6AGRjN5uQpMkgjZh2duK65JWJND21b6t+sU0lh5ae2V2ZP/e1voZkgsyOSTeiQe4Mh0zmDsfV+1LUUgZnPmZmSB7TkcNKiFrE2koAUskE25vQwZX1p5hG9sMofk+PlXBJKBrTok7iNbkCcIQcYdcrCH6K9O6hfxbtz6W+0/bL6R2+aENZqg== DOMIFA_SECURITY_FILES_MAIN_SECRET: >- AgBqHaAAV9JVzE2098qr0OjOxDzCXRKYQy3hUtGEOfUDj7HCcwdABAzSIMXnYqPs5cWCjmJo+rStz7fwD1ZAXGccIIY4xHPWlRBptj8TG3MeOEs0H4Lu+ET4IZF+iuATLQHZG4mXwoMY5mYkzWrXtkgB9B9CrAYhCZLpFN6Wzw3M71+bAT9rA+OfgM0mXZyktoGu7IIMz99Gc2C3DDta56Ckcrww2PX2mcvN8xcoQCn7I4bL0yytra72xFhaml+cl+saIy31+xrmv58CrEtgrW/ieAlhJEj4isLjD65cxfiuEUSc3pFEOHEvbvkKaXtWeDTdpeyX5KHRc7OoX1Kg+JU8yNZJbVecCY17Jw2lrhAS4LnEZbT337eZXBVcVesaFNz2MJgo8kGxp4gHKg8MCvOMFvlEw6pbCqs/6iYOnovTUx7QtdQn4085rUei2WTyeAftjNNvQOd1EMg07PJQVAQG8owtsL0nILLEHu9NOZpRYPeLU0k/4DsKoBGJEEA9TmuH06EpcdwW6yLLB+3WuhOpbxyy8q6TWnqexyT2c/PjcHC+oBIs627YN7PtDQLPNjwCsf6MCczVLUb8iYm5W4TgEJR+asHoKA77MFdkpVMOvws5ZJvTyamCHCTB51T8H0bWWJDr26g1zL1zlm3xWv+26QsrDRCHoEmhr03wvfbviF8ufOg27E3tP1pKDaMV3ImjIkN/WxloXWHd9wKiva3rnySa7MCJNPSCU7Oyex/pfxNUQbap1cgLohxZjJVg3yngxrG3PMDvuFqhFOP3elu2gG/gJmF4IpSv+Xv+qDlhGSuuHfc3oDhGplSwBZTkd/F/gSN6oG6IXCAq1k3K9K7HEfvURhce5WSdrFdqPbKnng== + SOLIGUIDE_URL: >- + AgBjqoEVDHIenQhR1Q10krfJjmyJOcij0Oy4Ed3ZCAZwGH+qXETXG82wri5esiwYRKUw7GgL0+1mCzxagZL66jYBNhSvwSDSNVsyljlik1kw5otGDcYKwWCZcbtVhNJQ74ttI+NFAUVNchvyXRy808sxlNWB+7WEKKa8fmkllZnilmYjno5Dcb8OLCtuqGjYNgqKvp13wDGCEIQDQgMo8wv51/Wg/QMesLc0t4tSuJkNsbzUO8WMANSX3dudxdbN6rpoP3JAPz9tEeCfJkvuUGujFQyrW0crgDAYo7kUeG/vazhn/qjOfmMeTjwJHuBhR8XDGMSgGoRs7Tz35xHS4/XYCS/0djHPfESOILRHLBzsnSBdyL5TPGBlEQpZHXeb6eBo657huBKzxORm23WHOkxWPnv1Ca1ic1i+QQirN58C/a4b6TYw+yQEbYiSziHYx0s93XHItnfv9vt6ELe5B9fDKCA+X92fC/9qn65lCUxrv5oMkxJ68KMQx73di47qwk9bKUB22CI1HFTbHSU7wbcaEdggH6GVUA9OxHaDzQdbyJhlXoGz4HK8vGNDEWgSryQpPj/TwgwLXYMRGtQqojvmHgFJdVgiDp8ZqtMAIOro0DW6dC03HMVTMtMw4+3Rw9T3RnRt9/Stbk1bE/8pQnmjDSIttCjHVywZzw53qReGTj51E5tAL9UG6qGuTx6d4Muy6JG4vpJULj9aGj4PPs4JPokNPZ83MGlqYJPLuse5QDf9CQ== + SOLIGUIDE_TOKEN: >- + AgC/I1lroDK1ktRFrwBizUvbu67Bezqm82BefOrHL1Sy1H81sQPmvwrqE0gpBCNBeKF3qH3in5QQ6IVGy5RJwYTGUbur2tLX2buAoDF48IE/Gu8lWyj9Ki6FIsPTVO6qFJTY5Tfmd692XTueYql9CNG0pLsItX9zTBJLOTTz9ysvVBKM9utUpmP5ti1h/UW604L9QKljQBJpYdmsm22B8JJ3sQYnL9pH9Hj+xRVPZU90D5UTx7RjVcribuWMrIrhkPc4sKYzLlBqffZqtFHWJVbSbFiYTRCPKoMVJ4iCduQl61Lbu8Qj/9fSoutCwhY7uOUX2XB7MOti2z7d2suRgPkvKbgEJb+RkTF34jrfXw0zBo43rW5ylyMz94Cf6KvjOZf4dC6iMJzuHpzuuoQJsYe2nNPp3GuG/BCZOJkRACeu7dcwar98sPuFRiX4e5e9fJseOUOuPBUZiu2OVePFdoKoHcj3WGE1qOnSlulLvg7qWUxpdwHhuX5dkLN7mPFBARVHrloGwaO32hfQxDwqvfqjYQcVaM+puzGu6s4QNGJzyPfBfiTCcF4A3AQYPtkMFDoad8h0We93er0qLEKS8i8Sm54joSphMiQxoONxzNJpq2fuSg+RsoALxY+P8QM5PQBSnLO6wpTbsL8OsjNFzLHryoc5gBLInBdxZ0d2/AMWnFiMNFADWe8Ji45uTayYx6dcMcLkNG/C/aULcP1atY2QAY9kJLdAHa6zAj7Zzjammcj2eVH1CwH+QXSwyoGnKw/rHwFR7Cgoa5Eft0FZMi8NaQMbefaPJa6e/MGAkmtMc64NvUAjj4EzGG5B2LNp1mMex6qKQ/IaprPIN33WiCEvCLV2e7HMudvH/u0VwTaStkVY2DCs0+hNMj8xgoge1k/jAp1kJtPAE2V4MK62ucV5Md6hmyrFgkmwxUMM + DATA_INCLUSION_URL: >- + AgDFru2Ck/TPLbmRaPph/vXpl4+YWXQSZtJgKPecHZM8n3upSOhmbvvhoJQoKya4YRjDnfueVaOtH/ewtKDxABe+UzYRg6BiBYu/BYMLmWC6xb/Abky41zohEIqrqHG0UdXclBxpyE6nRPpn6e/ta/lzJROeSVqi5Si0CH21HAYCyHXY6nv63GRQ0SN29ksjSiazu0J1Kgi/j/GbIxY/UBv9nLFUl+7L72NLBREe7zVhXHpTyBj3FvK5nC4aKpgvw3zAh0iKpdeD0dnL9693NSaE3VbRvbowb1L94wAsM/3oBQ9Mp5OLvJZPnYWfUZe+kCCZ3nxczqNz9GRzqgrGCXB2QcgGgpwYoSmCf6vlDG9DMNuK8oJqx7BUEJ18NXnuAjbfuY0cNyVGzeuQ8cVFYOmRXHGb4QXUCYHmuAdBGh2ynplzouEJvH92r+h0aER0XIBOpksVQWqADYWYBqndma1Hc9b5vyeIj2JbJ1f0YsWWSw59B/a/XHx6fulhTiFFtdym+wzaR2+oRYIC4fE9846cMC+7Gel4y/VQHh+Mj0NCqQbp+PYSKjmh6p3Y0VhjsHlgtGmpZXpD1GX7++L5aNpqSSdzjdDU45jyOHeXIfklZjoHFo2WY+Rnl3n2Qgp65G1nuOY5MevEzUlO2k99VbRcjdezntCdJeXjYir91ACe62nrOCgDwb8VO0+CxUPl7FerfBOsI4BNMjBMiqwEAMGR7ch8QSaXUfwSJ/h9fs3E7WpLCEpOBiayHwupjclMtfa09xaEXZzPNWk= + DATA_INCLUSION_TOKEN: >- + AgCqI6pxFt65Xf1j8yo5l3RZ/1TPFErfgb7s6R6GS8odHmwcFYrf/tm5V3SrIk6i5I2n63HSOk4fJHGpZMyKnHjBKiYZrOYLG98jyce8lmnpDmAuYVs3M0egUmNGfWGGsfLKuf9nKyVWrdT2scgLPVJ5oQNKfJxBr87OZAnwQeDd25CSgQym0fujcGlKgv01YsIbPz43pYfpG9QvwuzvoWFv5WAphtJCNRvObIl0F42qVcl95X8psOTcybwZDZuWbDyI8O5ONTnSMbyiBujMl62DX3F/NsYqcJ8WEMsGUYFrz+ej4xue9rvx2n0+UCS3LrqgrglLKnTy3rzj2XJHCOQve+b96IQlri3PgUtzvWpvXpQ5IsWMm2m67+osgWFLocLeX2IpW1HsLbacQaB9koYjGNxIYIqR6Kxii8cxStKB1c4sAGHpLkF93sV80mw1NW3Sxhd2UW6y6/NtILgxhCZleDmDSUyz31pgAdeZ7UoEsKPf1zC1vTfRScoeheuOBRRccVq7BqjEv2MSodNYsfyOH6EUgH2gbEY5CiW4X3CQ8g7otYlJPDwyMdLocTNulCaHxB5+b9OvPGPAyvmA7ZLMQr5sNfKrF9TY6J9SdIWGhSmDI9cRCuQKfRBJWB+15507xh3lRncgHH8RsCWoHxuQQAfejEKfRYlfiO43TNcqn3hRJ6MWEpqsDaMSAfVLO7lws1F2sL0M6FqrWsuqurz4kcM4WG8XXp1c15GQa85Ou97qrsS2gy7OoCoHEsnysZf44VZPiZSNAv7KiG0V+TFGgTx34crPwY1mAG0M88dHbmvuDDGFhzhjswxdu7qdF/ZWxXrWzi9M4Oj3CIW9wrDMTx1cYoWxpRtAaamp7eCPx3zUMiyS3TRd8nKsv3IniwgrKqb5OxV6C+fiiGQPr9umNaYV template: metadata: annotations: diff --git a/.kontinuous/env/preprod/templates/backend.sealed-secret.yaml b/.kontinuous/env/preprod/templates/backend.sealed-secret.yaml index 417fbc427e..f92bd95d3f 100644 --- a/.kontinuous/env/preprod/templates/backend.sealed-secret.yaml +++ b/.kontinuous/env/preprod/templates/backend.sealed-secret.yaml @@ -31,6 +31,14 @@ spec: AgBVXSFM2Y5dytUjYcyBFKVX+R3guA8uJFi4xVnLvcPBmQ4w74tYE7nRLDJKdvYLPHWcsb0gW+i7vBewxJrh/qiH/MTABB77l29d2JZ1/Xoz1yDvHoCZ/WJdKQaqs/vk8ZidkGk+E4ue0M7IRxm8AyptrW25d9AOarWB7AZwKPr7538OLW2PjSAIongqNq7sKXXY3j8gBOYCgIXH0pi+ZM9gCe9wacMLX3oWKJFkDsDAI+gin3y2ehlaBlDt2Ws9IqYsufkxYqimyri6d2r6JsmgMK1vqzxjqHaS1oxpzclSVQf+gvA28cq+QH71v9ToWh/J1E/poIZH/TSW71BcT84Mvo41ncDW7TthJ2ogal+VhWJaIzbMA2n19NQjGxzOFIlnK2W112P0dMaVGqa+22VzYqTbMFTBbsQGpzVZvkDY4x9qvxRoxyl0IqWNNJsHcjkXTUSFXdHMi7/faO/NHWuR4p3CHRP+sk7kfkDXaFy4qd3HF84S4TGJUXbDW6CDAT2ogz4IoZnZ1LR5xdlzwKyaC9rx1d3872klGjYSQHXnqgkPbW8B6akB1Umg72+SG5Lh5tCrk92phUPDNS2bsAHH3n1N5bhLEScTj/mG7v4uIi14AeR6AGRjN5uQpMkgjZh2duK65JWJND21b6t+sU0lh5ae2V2ZP/e1voZkgsyOSTeiQe4Mh0zmDsfV+1LUUgZnPmZmSB7TkcNKiFrE2koAUskE25vQwZX1p5hG9sMofk+PlXBJKBrTok7iNbkCcIQcYdcrCH6K9O6hfxbtz6W+0/bL6R2+aENZqg== DOMIFA_SECURITY_FILES_MAIN_SECRET: >- AgBqHaAAV9JVzE2098qr0OjOxDzCXRKYQy3hUtGEOfUDj7HCcwdABAzSIMXnYqPs5cWCjmJo+rStz7fwD1ZAXGccIIY4xHPWlRBptj8TG3MeOEs0H4Lu+ET4IZF+iuATLQHZG4mXwoMY5mYkzWrXtkgB9B9CrAYhCZLpFN6Wzw3M71+bAT9rA+OfgM0mXZyktoGu7IIMz99Gc2C3DDta56Ckcrww2PX2mcvN8xcoQCn7I4bL0yytra72xFhaml+cl+saIy31+xrmv58CrEtgrW/ieAlhJEj4isLjD65cxfiuEUSc3pFEOHEvbvkKaXtWeDTdpeyX5KHRc7OoX1Kg+JU8yNZJbVecCY17Jw2lrhAS4LnEZbT337eZXBVcVesaFNz2MJgo8kGxp4gHKg8MCvOMFvlEw6pbCqs/6iYOnovTUx7QtdQn4085rUei2WTyeAftjNNvQOd1EMg07PJQVAQG8owtsL0nILLEHu9NOZpRYPeLU0k/4DsKoBGJEEA9TmuH06EpcdwW6yLLB+3WuhOpbxyy8q6TWnqexyT2c/PjcHC+oBIs627YN7PtDQLPNjwCsf6MCczVLUb8iYm5W4TgEJR+asHoKA77MFdkpVMOvws5ZJvTyamCHCTB51T8H0bWWJDr26g1zL1zlm3xWv+26QsrDRCHoEmhr03wvfbviF8ufOg27E3tP1pKDaMV3ImjIkN/WxloXWHd9wKiva3rnySa7MCJNPSCU7Oyex/pfxNUQbap1cgLohxZjJVg3yngxrG3PMDvuFqhFOP3elu2gG/gJmF4IpSv+Xv+qDlhGSuuHfc3oDhGplSwBZTkd/F/gSN6oG6IXCAq1k3K9K7HEfvURhce5WSdrFdqPbKnng== + SOLIGUIDE_URL: >- + AgA34xpvXS4vcwuzmoRl/Opn0kUGK0EDi9NgL/mfVs2uFGrQbwmTqt89P61aeivZi6ggeOMmwTOjo6QlxZBjLXknXfm6K1+LtFA/dIjUzXSQnQu9HZOADl1bQK4/vmihuO4CCfDhWQCgoVz3Z9y15eXVxmp3kZcK5/txQJYUzTv+tCH8VnhQp54Wzr/QeQ8jO5GFN5zoWnVGkNb0BdnEI33tfe219GTOWUMx4KlE0BjDpRsoV2f5tVb3QRAAKATBK5leKIVCXCByujJascIOLl+ly21qyr3/AGaRLJiOR48ORPusyfm9Na2SN2ALinUgo95WvMaYgqxUgLmPGn0BPiXmJ0Z+SlXK8Pduzo2MVDaBvbmerlaDoKJGQFJGEeIDmP6hBepLK+R38VoRKTEqpbkCjLOsjce2cWC2FXYKVJuXHDuhtrZxeenm4CPHDPcZQK9Kq5dFo4BOsaEEc36IWI9Z3JdBvjzv57I0bfLpAswPJt/knt9fUB+tZKgGgGYUD80amM6xcZJ3TvpNO2nTMdlterySJmVXzTVvQj9Rnm2ekZxMO5+Zm6RhavQ5+mqmzjYuG23DNsBlGunLuxAtZleepwGc3C6Hm2L3AxgQ0mgEOBjFeQG6pth2nBWNz2i5Wr7w9P2guGLU/wHLThG9IOwpHFXQ0Jzc3IWuyiYEF5kXo5Ad484qsBrK/fVz9SNu5kK48ghG+ZkqHpRUR5dud/0OxgrWEEZBkCM0rFB3JwAe57Kmlg== + SOLIGUIDE_TOKEN: >- + AgAEI+etZBXo8w59pLKHeh/WA8B1D/EDDCYELzJYyEI0GaxQ7gg/PX/53fmE6N+pweAI7NgGDVut6ywl0PlqYUv7ikrGGh/ndzDecrfJgpiUIjq1nOIeO4NVQ5Vq0Nua5bHiTJhn4Dpie0usmrWFxMnaAZxCIDvADi25d6mbn7mE/kCDX7dOVJxtpowEsdPs/ChBCvzDjzDoGE5ex0e8VXi/Jh2HmzEme2o4t2Xd1uoiZDg0b+zrP6pPYj7OJLTqqe3V9+tkTayVcPZQX+sj7hA/864bkwo4dUJz99vRtKkZStKLm1Da/IZd2h58RLXVpAv71qhNvxx9E6vnhiqWLr2w+KWHpF8lHvcN0rI3DHT6trN90DF2tTBt0dW40lHANPlOa6pMgZstXS+WGvGwxT/FGceD6cjDb3U5n0d5x2hsOiocGB2w7B/t1zX4fAWN12H6TnU8Ewlj/hW93/QJKcQK3vaCx3Uqs343WLoIOxhN7IGPrzdyZ7PhZV7LlGEbj0KPJM+da1EfUioFpznW1s/JDTh2cp709QQoc7R0/wBO6vczMahiOt/ArRllv6mrLTdiAI+/bSn+fkkZWPdkQH0CVSZY8V0y6M7ez4pqnAa67LFSmYGsgTHZQbB8Xs7KTyydLyt2Uq0tr01dxHY8y9Md1PkgUto1Z4iasHwqCVFpvHvh+r891ybsrjBkw7r+Uh7wvwaTL/0mD9InpOFmXgKBuDWXLRRj+lbzGkG93+Ah1tjr/TYZW4kzAb9IozqhxkPMmwefMiuY4gDV0xch1wvYYWPgQX+HqiSz1fzBAt5Z9Ba6Gr1zo29j1kchjazdQd6xbMJSMts8meg1Eq5fvGUkQ2lsNLHjtyHq/in420JW2tfW4CJYXCeVvB58M7rlIV0+eT0n5dwI3dfAZSvH1XPsvLw/YT+GuAOJI7uS + DATA_INCLUSION_URL: >- + AgBkze20wXlbnvKjfCXJxrfdyXrWOodgW1tqoxoaXOkYXmDA1EMFl8OIzbPvs0ydWwAdssqPKU4r4XPsdqiZn5319nZBH3IEsu/dAmWTrQKps2WrVAikSakprkuoz4ssHVRGFQCScjzWpqbZIhX44pbC+BrMf//efpm6Al/sc033wxaFqLg/es5pFVo6izwdwm3Z+1ufcFcW6ooOQKPZNFzNEvkU8zZr/H0NiVv6qrPZWZ7gLJ9Yxx3zYmEBVihNY6yYvOOQrmBugqgLMS+L5OSOeu71CAJHYTT9fW/EXEGtKLi9neKjqI3WxGgzuo50/DpYmAO8ibaQlzW/41AixBU5Q8ZVGrF8Y1ni0EjzYLWsnyK7RgYWCsIUSBetvoarIYeEtEs0o8TGQFYz48qWnYFhM1UUOaf6nasuwoV6fXbBYsYbAPsuvVdoOz64HVbruFe5MoKQHKlyV3Ypt96OHsn6m/FvqCRRjq9DaFRPtGOdbQIGDWn0JSWRtofo5WLkIqAnx56Mqcd4F04d/UXEKHSGwZU60tsWHQtFtmL4kTTsNGOg9laJoY0XSfn+iqvk8DGYuEGQKVeVrY6+uGFIF80NyXEPjc2E00Da1Ka0VdkF0xfYWHhlb1aIA2DFGsI//1cZn7olj0S5rfzWy4k8GhCpMZ4ZfKjNAUx9kHsJxwnfU6nzUMKqxyw9Hd9bwcxDubsNWmTrNu8MjBEABL/6a0ySbdka+NbU8bCKXt8RcLpo5FUwXRWBezcuTIOhcw53czGS0FCCT1Kff98= + DATA_INCLUSION_TOKEN: >- + AgAr7Nnt1AwG+BhUuds/Yo1gavHhRpyrF33yo+dPVhLopJTjd/YWULrk8YkSOAvBsngsGif8mBequV/OqlaBDHT3GF3Dt1L8b0QFPCoprDDYDJ6HzRKEBiZ1wOXPJjNVxQeTrihPRjzUfHHm4+FZ9ai9Te47Iii31a77/HLben9PUSlqG72o6cyombRGJaDkc63MSrrXXg/YkclswgBG14EoZNgVvAXTeh6NwFmcgqKNE2hPX9yUhklK6yP1jKQ0X+mSkt3tkJaD5fmCZEpKp49iMwf2iaW0zwDXYJQS+vMps9RFiaeY20WeUwoXNuiFguT3Fcl3pWw1kw/q81JHr24V4tP0mEpkTRKdz4rq00C8NWIaVbeAtaoo+7Hpe9TuoIaBvhOjwcgeGDPHGJhWChoA8Iu0bfc0GaYBLUMDqF4kZnymtAUi4phkdI1t2omJCt2F4Ki7S/2T98FdaSmurDpIG8XJoN0WG9vFOrceXyWBVtHOL0EJPGzfqlZN13xouGy9VXvPUN/ppU2bLrkBIf/5yXLpLm8oES69xSPqbGisd6GdlqVpe/am147iOHm2jK5aDz29Ab3ZJuy/inD7X6BEwBIIgLJIl6tM8ngjDm72JyFBEQHFJ1Hac7jU8tWBEuI1IvmqCehUCYO1jHa4FGOW9PzZVQahUhEXR9ab2vQaG3IctZuRSgJq/n1wbuSHgEc/yTIlrjwSwm18NsYszVL3Wty1h7JRnZ5/ITiqczax8tlBwR4A6meD3uYJpDJhQGkM1cz50Q3Suq5dB0A0rOdFuou0t5WqtJBTIkXNsN9gzlT5rORV4xRn4BN6JE5ZeYsJFYclwEG8SZ8B50+clDRdW5okbGTKV5VqtrsNa6VB6fJ+h7EbyXjWS2oSLhIdB8zqeapB/xKoftBte3+AUMuXKdtx template: metadata: annotations: diff --git a/_scripts/db/dumps/domifa_test.postgres.custom.gz b/_scripts/db/dumps/domifa_test.postgres.custom.gz index 49942ec6d32e9b99c12d33d833d385a63d7876b7..53b25d0f64929fade1061c764a58f72dc72f8042 100644 GIT binary patch delta 13733 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 delta 11822 zcma)C30zF;`|pfOYG~55XQoI~TFja4%-~WAmw$vTSrU=Bi0tcav9IB!$#TgSx{4f} z6d|c=De7jqk|aCXxsuE8Y}1TW^M3yG`IzW^zTfA0-uKzwbEK4+6&^G59M~tg|3IX* ziKzu*(#nMVVANMj>IOUi9LJW#Z zeNb$z*bzziHD@o{0&#W$F&vAl5vb{Dlx)N6dg4>1Vibf?bF-_@(G1pCX|? zrsN+~rjnUhP=7&{Dy32e5_uk$i^zWm4ek{wWbX{MccD6(G)b8B{4R6 zf{pG1(IrwL^I>dKY7A_WeGq~PbC@#{8viAQZt5D-#E#~qXg^OXrN;O_+ z^-RzF7fe`%9dGkZPkb3Bi>dK}Hn;S`S75?wHNH?dr$wX5S7E{$4G404O3FHc5GQN# zHHfTAssz&C9YC^E4R{jfW-FB=R9v=bgb?&;oN-=EokUHNBPAu3DmYRljq**8MkU37 z%_JB6yi0=K*-{t)#qhK4d~=<%qU$hWIqvF}swchylU2xZ3m*hwJjFOZL4WZOn>hEi%G)LNS&4#2Fx0Pi`pTwi7at#mO!Wt2=MRp^Ty zrjmk5!(UMmrY3(+C9AAS;)X&AP;fN-8AG693Amv;6iOfi??-%L2-GYAH=$yo1ai=8 z)JH045G6QQ;vilCl~#Z)qrcH1wlLgLyc8;{1TQ1rQb&TIT7f;{;FUr(GrHYUUsC-> zD&-ow7mu4UBXa8W7!WsINVjHE3XF{0NV+HXM>ULJyv;5&1sOF)>BxxaGS;h+V)EE> zmVzlHJWE%WBGo8`QVrIQ^K7KZ8K-3_m>R*8=qR=srBGpDcT`6m1%5TkjIMZoQYl?# zc)>b~?M5juHE^4tx1#@qf2pJPlcEg6M-SGI9Yz_{YOp2RqtS?S(Mr|`8AD;yk)_ya zl!9zy!7&|l6d*Pxj4^^~Q9OSg!!BbCOy}`$WavHV2E(9aY}l(~*lm;n#lZC`?R5!xcFDlvT7)4i=@*l(0UB?q(O8qWsoin~u|mSAklj`bL;|A0|6CIi=I zdN=C-HZzUZ5AJKtJ$aoqEI!>RUX6lRvn4t_aGtY|*8Y7h34hUzg&#Bu*GNI@xgDux z-RA-j&#~V;+8m6Wn?qA2l#x_LAuQElV^n1O0dIp`!SC~I4e1_GbRfC6H7J-@s(m6s z+JoeJvyQyH{w!gJQ9`O?>C?Z>f;!S1uTH_CEbxd?pkY4(F$;x;_GrPNB|>dz3&a*= zEnG@D=*!lEurQW5(gzUp=A3Bnu9o`Q(YDF#m`}}Jel!S+@1tv& z^f1buzs}JrR{7h3j6{22ozU|qY3>wto|YyOX6dBZA%u5?k$v zow-^{p+Gr)Xr-J6l1VBM-+~G&wGW&SA>MPf6NQj?>snQjBmJCJ8@l`2Oouk}r zdkKXqajR563hE9@9apT33remFA!gWs8W+R5$|1eu($)kSaXA@&w#>|c-ros zw1rYBGgaskTbm-zc<6pQ=ow$?VALpz7aj1VjG~W5dReFfEM80Q%lRd>1Oty8R-HY=}RXxgSuR5+8AlvWYyl6Hq}6zn1Mlag&9Bd$lTu zA~m=QSJ9r(<@yXvSdQZ7PIO?^aI3~CC{m6qPdOVgun3A&;(G}?E!{CG8!p_2^!6tL zRA%`6O)Xaem(z80w2(Ex!{n#%=gMLxBC>RVfoDV@H}6_wHh+XFP=kNYJf;t+7%Ha$ zHuT`XOx?=NtmC70#(ex_AM5HOGUXP z0~t;9y-Z(0|ArDUkwJMLYfXCoskn$FF&tP@pl~&4bGe!_yy?*P5DL_QfGcmQLB(Sa zOpctL>BvQ|i9q_*3ydc29HNCXpdj}ey|+zG+z18Az=x7&q{ilEu~aBh4*ajbZhlv` zL4gV|{l?4YfuEs3CCDtRq;vHhR89pd%iog<+yON>R6=Dj;8t;umZciURj8~Qgx;hK zcc-iE5vZ&NtiM%DIjL?E?Dt?m6%z|otfo1VvHIlpMV)mXo1j3H38DvgMPS(7^CYOb zBdvf^$iU=EDi|dG`pkL?MKCo5gj9(@@x46SQfkKg7Yb4^mM*z30$-{~5P^E^g#wfe z;Api7cvqhxwUC*}&5wL2g9@l0+@{QHQaLiAxW>u>jvjXb%WF4`M?x_YLM?g_*^d!6xfp5>LZa{7hcUQBZ z47zZ7DFVJPPcsbM6Fm=QU^~+NS0XU#6~)kWduyQt7>KERM|XxtP&qYoj^o~lKY0~t%U4Q9y_42Y`7rbMPTuNR5>QKaSvrDltBa5e5ZG` zX~j7P18SIxvvoQm0#AONYu?cUC@b5wWEeGMawM z8z5zQRP44j@y!{^hY>@pkSIec!|meC>gF&inT&95jYR9WshN#$64C-FBSt;9a3H?6 zL54I-i^`eJY?7DyhwDur9BJe->RF_iC=-y5QxE^WG^lPDo18{Vn1OPP(6&V)^|tkq zX)xW(TK3x9#AQbqqrxyH<_W2kAfJ*4>H-(l(5Fou5$9;yKv^*&*dB@FaLJ5uwS{ph zWrUL>GG6aoSkCb@ot3 zjF`|4nWAUp8#01qXGakXj>!nQ7@5wbeq+rrmin!sR2X6IPNgcOu%X5DCQ7HI|J(#VK-PsTfvi`^+Q>~)-+GtFghq7PioO z^)j8j=T?KysEgqOJNbA;T z%n@AJ@t@=E4h9Y~J^ctf?tIM0_fpcLr1h=ZSY3>m&`mI0R%o#= zRT?s>_oto5HImbti&i--OLr?SjF0Lq@A)+Npc@wQ+lM4+aI3b5+C|w%o%)(JvRW}M z`My|FJ^XQ5H=nAEwbe0w-elbDR8U`Lvoq&LQC8(2Up)))^p{n?xz;Cm)jq3p@i28a zz0kwM>BaclPj^)Qm{ED}NW{r2OYi|79)xutloVn%HGTBQx(5w=+R4u@%ZnbjJNB3O zBjYR2{Fc!@7JT2hV#l0*-X#N8-#-!OtZCOdWPEg3(Bb}P|8Q7o-)Tm~ZMTYjSk{Wd zngJ02dwdhwoo}^B9%BXll~cJ3)i0I=lTQinuu(yYT7V$(LWly!OSA*xiY#p8fg=tdiOTudDavN~ z1+zHIu31ahWP6<{w>1&Ux7x_Hv;7yuF55e}hgtT(VP1c@J-OnxX40wJoOips=PqpD zvU`emK-{-PulQc~^ZY}DMSF9QO=J6^H=XR>rfO<6LPcWE<)CqU%c9~IXGgyqVH&?C zD?jx2K0dLkHY=;WqSNaY_VcncYFlh5ZkrF%-@3&S&CACCW|cpGrExaiku-Tn($mTVgJCU$&8@j=sualLxhHB4An zuw!hcWNk^wu4!B4M8<34%JtYuKH^2Gzu)k?nz24V^g@NgPSHByT>OpN6P-82|M0B~ z`{pvVZhUy&l|1drtMx}_L~6U%lqQaFzcgl_cfsbzJ6pMb+Ayu_zQm%men}_G<9Swo zuBQrx>W%FkkLG0Of3d6?Hags=?On@vnNzJt^vJL1Qy+UYB4Q3Y>vrA2g(2Tb4z>w=bU?Im$~C3aa&2te%9h`F1`OX z4YF_>_DtKq%gc!Fk-iO9#6pK3xuG9=o&4P^zQJYVo7CijVEfg+V;}!P^xm>xxIAth zx;H#f5tc5rEbJ#6G18Wwymw=TaP*8j4~y4d^)OlaDD$ZI7;Y|GZ## z)S>9E$1Xh!6Pi^YdxLacD=geq&hs&|?3>+h_nC3K!b1L4IN#cB zuEW1)gW_uz&-B{a!LN^BL(i23Pu4vdcJ~(|Oz1b@M`DmBYsx%v#p4-&SJbpxy7|PZ zwEJ3Cs_eu9e&zv*~2&*^(IipKAXTf}6~L)kaLx*vh<*Pxy63+*WWx-a)?BH3Ip-JIp6+#vm&ZUIw4o9*MLz { + await queryRunner.query(`CREATE EXTENSION Postgis;`); + await queryRunner.query( + `CREATE TABLE "open_data_places" ("uuid" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "version" integer NOT NULL, "nom" text NOT NULL, "adresse" text NOT NULL, "complementAdresse" text, "ville" text, "codePostal" text, "departement" text NOT NULL, "region" text NOT NULL, "latitude" numeric(10,7) NOT NULL, "longitude" numeric(10,7) NOT NULL, "source" text NOT NULL, "uniqueId" text NOT NULL, "software" text, "structureId" integer, CONSTRAINT "PK_f80b64cfb42753deacd8bf6d78d" PRIMARY KEY ("uuid"))` + ); + await queryRunner.query( + `CREATE INDEX "IDX_d85d3252e11effca2f6b652fde" ON "open_data_places" ("codePostal") ` + ); + await queryRunner.query( + `CREATE INDEX "IDX_0408f9f2c0defbdc5e44f467a3" ON "open_data_places" ("departement") ` + ); + await queryRunner.query( + `CREATE INDEX "IDX_6e030c1cdb3fa54d0d735cdc6b" ON "open_data_places" ("region") ` + ); + await queryRunner.query( + `CREATE INDEX "IDX_d10ac71fca9180b787ef468659" ON "open_data_places" ("structureId") ` + ); + + await queryRunner.query( + `ALTER TABLE "open_data_places" ADD CONSTRAINT "FK_d10ac71fca9180b787ef468659e" FOREIGN KEY ("structureId") REFERENCES "structure"("id") ON DELETE CASCADE ON UPDATE NO ACTION` + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "open_data_places" DROP CONSTRAINT "FK_d10ac71fca9180b787ef468659e"` + ); + await queryRunner.query( + `DROP INDEX "public"."IDX_d10ac71fca9180b787ef468659"` + ); + await queryRunner.query( + `DROP INDEX "public"."IDX_6e030c1cdb3fa54d0d735cdc6b"` + ); + await queryRunner.query( + `DROP INDEX "public"."IDX_0408f9f2c0defbdc5e44f467a3"` + ); + await queryRunner.query( + `DROP INDEX "public"."IDX_d85d3252e11effca2f6b652fde"` + ); + await queryRunner.query(`DROP TABLE "open_data_places"`); + } +} diff --git a/packages/backend/src/_migrations/_init-db/1603812391580-pr-env-create-database.ts b/packages/backend/src/_migrations/_init-db/1603812391580-pr-env-create-database.ts index 8fffa86f45..939a4023e2 100644 --- a/packages/backend/src/_migrations/_init-db/1603812391580-pr-env-create-database.ts +++ b/packages/backend/src/_migrations/_init-db/1603812391580-pr-env-create-database.ts @@ -150,6 +150,55 @@ async function createTables(queryRunner: QueryRunner) { ); + -- public.open_data_places definition + + -- Drop table + + -- DROP TABLE public.open_data_places; + + CREATE UNLOGGED TABLE public.open_data_places ( + uuid uuid NOT NULL DEFAULT uuid_generate_v4(), + "createdAt" timestamptz NOT NULL DEFAULT now(), + "updatedAt" timestamptz NOT NULL DEFAULT now(), + "version" int4 NOT NULL, + nom text NOT NULL, + adresse text NOT NULL, + "complementAdresse" text NULL, + ville text NULL, + "codePostal" text NULL, + departement text NOT NULL, + region text NOT NULL, + latitude numeric(10, 7) NOT NULL, + longitude numeric(10, 7) NOT NULL, + "source" text NOT NULL, + "uniqueId" text NOT NULL, + software text NULL, + "structureId" int4 NULL, + CONSTRAINT "PK_f80b64cfb42753deacd8bf6d78d" PRIMARY KEY (uuid) + ); + CREATE INDEX "IDX_0408f9f2c0defbdc5e44f467a3" ON public.open_data_places USING btree (departement); + CREATE INDEX "IDX_6e030c1cdb3fa54d0d735cdc6b" ON public.open_data_places USING btree (region); + CREATE INDEX "IDX_d10ac71fca9180b787ef468659" ON public.open_data_places USING btree ("structureId"); + CREATE INDEX "IDX_d85d3252e11effca2f6b652fde" ON public.open_data_places USING btree ("codePostal"); + + + -- public.spatial_ref_sys definition + + -- Drop table + + -- DROP TABLE public.spatial_ref_sys; + + CREATE UNLOGGED TABLE public.spatial_ref_sys ( + srid int4 NOT NULL, + auth_name varchar(256) NULL, + auth_srid int4 NULL, + srtext varchar(2048) NULL, + proj4text varchar(2048) NULL, + CONSTRAINT spatial_ref_sys_pkey PRIMARY KEY (srid), + CONSTRAINT spatial_ref_sys_srid_check CHECK (((srid > 0) AND (srid <= 998999))) + ); + + -- public."structure" definition -- Drop table diff --git a/packages/backend/src/config/domifaConfig.service.ts b/packages/backend/src/config/domifaConfig.service.ts index 070fec8b3a..b155ed727f 100644 --- a/packages/backend/src/config/domifaConfig.service.ts +++ b/packages/backend/src/config/domifaConfig.service.ts @@ -318,8 +318,21 @@ export function loadConfig(x: Partial): DomifaConfig { required: smsEnabled, }), }, + openDataApps: { + soliguideUrl: configParser.parseString(x, "SOLIGUIDE_URL", { + required: false, + }), + soliguideToken: configParser.parseString(x, "SOLIGUIDE_TOKEN", { + required: false, + }), + dataInclusionUrl: configParser.parseString(x, "DATA_INCLUSION_URL", { + required: false, + }), + dataInclusionToken: configParser.parseString(x, "DATA_INCLUSION_TOKEN", { + required: false, + }), + }, }; - return config; } diff --git a/packages/backend/src/config/model/DomifaConfig.type.ts b/packages/backend/src/config/model/DomifaConfig.type.ts index 1856e59977..298c8aaa1a 100644 --- a/packages/backend/src/config/model/DomifaConfig.type.ts +++ b/packages/backend/src/config/model/DomifaConfig.type.ts @@ -76,4 +76,10 @@ export type DomifaConfig = { phoneNumberRedirectAllTo: string; // DOMIFA_PHONE_NUMBER_REDIRECT_ALL_TO apiKey: string; // DOMIFA_SMS_API_KEY }; + openDataApps: { + soliguideUrl: string; + soliguideToken: string; + dataInclusionUrl: string; + dataInclusionToken: string; + }; }; diff --git a/packages/backend/src/config/model/DomifaEnv.type.ts b/packages/backend/src/config/model/DomifaEnv.type.ts index cc12ff14f6..69d1db2f7a 100644 --- a/packages/backend/src/config/model/DomifaEnv.type.ts +++ b/packages/backend/src/config/model/DomifaEnv.type.ts @@ -56,4 +56,8 @@ export type DomifaEnv = { DOMIFA_SMS_API_KEY: string; DOMIFA_ENV_PRESET_PARENT: string; DOMIFA_PHONE_NUMBER_REDIRECT_ALL_TO: string; + SOLIGUIDE_URL: string; + SOLIGUIDE_TOKEN: string; + DATA_INCLUSION_URL: string; + DATA_INCLUSION_TOKEN: string; }; diff --git a/packages/backend/src/database/entities/monitoring/index.ts b/packages/backend/src/database/entities/monitoring/index.ts index 9aef934be0..bb3b1de34c 100644 --- a/packages/backend/src/database/entities/monitoring/index.ts +++ b/packages/backend/src/database/entities/monitoring/index.ts @@ -1,3 +1,4 @@ +// @index('./*', f => `export * from '${f.path}'`) export * from "./MonitoringBatchProcess.type"; export * from "./MonitoringBatchProcessId.type"; export * from "./MonitoringBatchProcessStatus.type"; diff --git a/packages/backend/src/database/entities/open-data-place/OpenDataPlaceTable.typeorm.ts b/packages/backend/src/database/entities/open-data-place/OpenDataPlaceTable.typeorm.ts new file mode 100644 index 0000000000..4a6e65df36 --- /dev/null +++ b/packages/backend/src/database/entities/open-data-place/OpenDataPlaceTable.typeorm.ts @@ -0,0 +1,58 @@ +import { Entity, Column, ManyToOne, JoinColumn, Index } from "typeorm"; +import { StructureTable } from "../structure"; +import { AppTypeormTable } from "../_core"; + +@Entity("open_data_places") +export class OpenDataPlaceTable extends AppTypeormTable { + @Column({ type: "text", nullable: false }) + nom: string; + + @Column({ type: "text", nullable: false }) + adresse: string; + + @Column({ type: "text", nullable: true }) + complementAdresse: string; + + @Column({ type: "text", nullable: true }) + ville: string; + + @Index() + @Column({ type: "text", nullable: true }) + codePostal: string; + + @Index() + @Column({ type: "text", nullable: false }) + departement: string; + + @Index() + @Column({ type: "text", nullable: false }) + region: string; + + @Column("decimal", { precision: 10, scale: 7 }) + latitude: number; + + @Column("decimal", { precision: 10, scale: 7 }) + longitude: number; + + @Column({ type: "text", nullable: false }) + source: "soliguide" | "domifa" | "data-inclusion"; + + @Column({ type: "text", nullable: false }) + uniqueId: string; // ID from soliguide | data-inclusion + + @Column({ type: "text", nullable: true }) + software: "domifa" | "millesime" | "other"; + + @Index() + @Column({ type: "integer", nullable: true }) + @ManyToOne(() => StructureTable, (structure) => structure.id, { + onDelete: "CASCADE", + }) + @JoinColumn({ name: "structureId", referencedColumnName: "id" }) + structureId: number; + + public constructor(entity?: Partial) { + super(entity); + Object.assign(this, entity); + } +} diff --git a/packages/backend/src/database/entities/open-data-place/index.ts b/packages/backend/src/database/entities/open-data-place/index.ts new file mode 100644 index 0000000000..39eb51b7fb --- /dev/null +++ b/packages/backend/src/database/entities/open-data-place/index.ts @@ -0,0 +1,2 @@ +// @index('./*', f => `export * from '${f.path}'`) +export * from "./OpenDataPlaceTable.typeorm"; diff --git a/packages/backend/src/database/services/place/index.ts b/packages/backend/src/database/services/place/index.ts new file mode 100644 index 0000000000..ad3d0be97d --- /dev/null +++ b/packages/backend/src/database/services/place/index.ts @@ -0,0 +1,2 @@ +// @index('./*', f => `export * from '${f.path}'`) +export * from "./open-data-place-repository"; diff --git a/packages/backend/src/database/services/place/open-data-place-repository.ts b/packages/backend/src/database/services/place/open-data-place-repository.ts new file mode 100644 index 0000000000..b1e0608cfb --- /dev/null +++ b/packages/backend/src/database/services/place/open-data-place-repository.ts @@ -0,0 +1,21 @@ +import { OpenDataPlace } from "../../../open-data-places/interfaces/OpenDataPlace.interface"; +import { OpenDataPlaceTable } from "../../entities/open-data-place"; +import { myDataSource } from "../_postgres"; + +export const openDataPlaceRepository = myDataSource + .getRepository(OpenDataPlaceTable) + .extend({ + findExistingPlace: async (latitude: number, longitude: number) => { + return openDataPlaceRepository + .createQueryBuilder("open_data_places") + .select(`nom, ville, "structureId"`) + .where( + `source='domifa' and ST_DWithin( ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)::geography, ST_SetSRID(ST_MakePoint(:longitude, :latitude), 4326)::geography, 250);`, + { + longitude, + latitude, + } + ) + .getRawOne(); + }, + }); diff --git a/packages/backend/src/open-data-places/cleanAddress.ts b/packages/backend/src/open-data-places/cleanAddress.ts new file mode 100644 index 0000000000..1d0a75e5f4 --- /dev/null +++ b/packages/backend/src/open-data-places/cleanAddress.ts @@ -0,0 +1,42 @@ +import { ucFirst } from "../usagers/services/custom-docs"; + +export const cleanAddress = (address: string): string => { + if (!address) { + return ""; + } + return address + .toString() + .trim() + .toLowerCase() + .replace(",", "") + .replace(".", "") + .replace("/", "-") + .replace(" b ", "") + .replace(" , ", "") + .replace(" bis ", "") + .replace(" ter ", "") + .replace(/\s+/g, " ") + .trim(); +}; + +export const cleanCity = (city: string): string => { + if (!city) { + return ""; + } + city = city + .toString() + .trim() + .toLowerCase() + .replace(".", "") + .replace(",", "") + .replace("/", "-") + .replace("cedex", "") + .replace(" BP ", "") + .replace("éme arrondissement", "") + .replace("eme arrondissement", "") + .replace("ème arrondissement", "") + .replace(/[0-9]/g, "") + .replace(/\s+/g, " "); + + return ucFirst(city); +}; diff --git a/packages/backend/src/open-data-places/interfaces/DataInclusionPlace.interface.ts b/packages/backend/src/open-data-places/interfaces/DataInclusionPlace.interface.ts new file mode 100644 index 0000000000..9c27238c29 --- /dev/null +++ b/packages/backend/src/open-data-places/interfaces/DataInclusionPlace.interface.ts @@ -0,0 +1,38 @@ +export interface DataInclusionPlace { + _di_geocodage_code_insee: string; + _di_geocodage_score: 1; + id: string; + siret: string; + rna: string; + nom: string; + commune: string; + code_postal: string; + code_insee: string; + adresse: string; + complement_adresse: string; + longitude: number; + latitude: number; + typologie: string; + telephone: string; + courriel: string; + site_web: string; + presentation_resume: string; + presentation_detail: string; + source: string; + date_maj: Date; + antenne: true; + lien_source: string; + horaires_ouverture: string; + accessibilite: string; + labels_nationaux: string[]; + labels_autres: string[]; + thematiques: string[]; +} + +export interface DataInclusionResults { + items: DataInclusionPlace[]; + total: number; + page: number; + size: number; + pages: number; +} diff --git a/packages/backend/src/open-data-places/interfaces/OpenDataPlace.interface.ts b/packages/backend/src/open-data-places/interfaces/OpenDataPlace.interface.ts new file mode 100644 index 0000000000..4cee10a480 --- /dev/null +++ b/packages/backend/src/open-data-places/interfaces/OpenDataPlace.interface.ts @@ -0,0 +1,17 @@ +import { AppEntity } from "@domifa/common"; + +export interface OpenDataPlace extends AppEntity { + nom: string; + adresse: string; + complementAdresse: string; + ville: string; + codePostal: string; + departement: string; + region: string; + latitude: number; + longitude: number; + source: "soliguide" | "domifa" | "data-inclusion"; + uniqueId: string; // ID from soliguide | data-inclusion + software: "domifa" | "millesime" | "other"; + structureId: number; +} diff --git a/packages/backend/src/open-data-places/interfaces/SoliguidePlace.interface.ts b/packages/backend/src/open-data-places/interfaces/SoliguidePlace.interface.ts new file mode 100644 index 0000000000..1378ac4e7c --- /dev/null +++ b/packages/backend/src/open-data-places/interfaces/SoliguidePlace.interface.ts @@ -0,0 +1,26 @@ +export interface SoliguidePlace { + position: { + codePostal: string; + departement: string; + location: { + coordinates: number[]; + type: "Point"; + }; + pays: string; + region: string; + ville: string; + adresse: string; + complementAdresse: string | null; + }; + name: string; + lieu_id: number; + entity: { + mail: string | null; + phones: [ + { + label: string | null; + phoneNumber: string | null; + } + ]; + }; +} diff --git a/packages/backend/src/open-data-places/interfaces/index.ts b/packages/backend/src/open-data-places/interfaces/index.ts new file mode 100644 index 0000000000..a61eb88501 --- /dev/null +++ b/packages/backend/src/open-data-places/interfaces/index.ts @@ -0,0 +1,4 @@ +//@index('./*', f => `export * from '${f.path}'`) +export * from "./DataInclusionPlace.interface"; +export * from "./OpenDataPlace.interface"; +export * from "./SoliguidePlace.interface"; diff --git a/packages/backend/src/open-data-places/load-data-inclusion.ts b/packages/backend/src/open-data-places/load-data-inclusion.ts new file mode 100644 index 0000000000..0111530784 --- /dev/null +++ b/packages/backend/src/open-data-places/load-data-inclusion.ts @@ -0,0 +1,125 @@ +import axios from "axios"; +import { domifaConfig } from "../config"; +import { + DataInclusionPlace, + DataInclusionResults, + OpenDataPlace, +} from "./interfaces"; +import { OpenDataPlaceTable } from "../database/entities/open-data-place"; +import { openDataPlaceRepository } from "../database/services/place"; +import { departementHelper } from "../structures/services"; +import { appLogger } from "../util"; +import { cleanAddress, cleanCity } from "./cleanAddress"; + +let page = 1; +let nbResults = 0; + +export const loadDataInclusionData = async (structureType: "CCAS" | "CIAS") => { + if ( + !domifaConfig().openDataApps.dataInclusionUrl || + !domifaConfig().openDataApps.dataInclusionToken + ) { + console.log("[IMPORT DATA INCLUSION] Fail, token or url is not in env"); + return; + } + appLogger.info("Import data-inclusion start 🏃‍♂️... "); + + await getFromDataInclusion(structureType); +}; + +const getFromDataInclusion = async (structureType: "CCAS" | "CIAS") => { + let datInclusionData: DataInclusionPlace[] = []; + + const url = `${ + domifaConfig().openDataApps.dataInclusionUrl + }?typologie=${structureType}&page=${page}&size=500`; + try { + const response = await axios.get(url, { + headers: { + Authorization: `Bearer ${ + domifaConfig().openDataApps.dataInclusionToken + }`, + }, + }); + + const data: DataInclusionResults = response.data; + datInclusionData = data.items; + nbResults = data.total; + + for await (const place of datInclusionData) { + if ( + place?.code_postal && + place?.latitude && + place?.longitude && + place?.commune + ) { + let dataInclusionPlace: OpenDataPlace = await openDataPlaceRepository + .createQueryBuilder("open_data_places") + .where( + `("uniqueId" = :id and source='data-inclusion') OR (source='data-inclusion' and adresse = :adresse and ville = :ville)`, + { + adresse: cleanAddress(place?.adresse), + ville: cleanCity(place?.commune), + id: place.id, + } + ) + .getOne(); + + if (!dataInclusionPlace) { + const departement = departementHelper.getDepartementFromCodePostal( + place.code_postal + ); + + dataInclusionPlace = await openDataPlaceRepository.save( + new OpenDataPlaceTable({ + nom: place.nom, + adresse: cleanAddress(place?.adresse), + codePostal: place.code_postal, + ville: cleanCity(place?.commune), + departement, + region: + departementHelper.getRegionCodeFromDepartement(departement), + software: "other", + latitude: place?.latitude, + longitude: place?.longitude, + source: "data-inclusion", + uniqueId: place.id, + }) + ); + } + + const placeExist: OpenDataPlace = + await openDataPlaceRepository.findExistingPlace( + dataInclusionPlace?.latitude, + dataInclusionPlace?.longitude + ); + + if (placeExist) { + console.log(placeExist); + await openDataPlaceRepository.update( + { uuid: dataInclusionPlace.uuid }, + { structureId: placeExist.structureId } + ); + } + } + } + + if (datInclusionData.length >= 500) { + appLogger.warn( + "Import DataInclusion data " + + page + + " iteraction: " + + datInclusionData.length * page + + "/" + + nbResults + ); + page++; + await getFromDataInclusion(structureType); + } else { + appLogger.info("END OF MIGRATION"); + } + } catch (e) { + console.log(e); + console.error("[IMPORT] Something happen"); + } +}; diff --git a/packages/backend/src/open-data-places/load-domifa.ts b/packages/backend/src/open-data-places/load-domifa.ts new file mode 100644 index 0000000000..105a0e275b --- /dev/null +++ b/packages/backend/src/open-data-places/load-domifa.ts @@ -0,0 +1,64 @@ +import { OpenDataPlaceTable } from "../database/entities/open-data-place"; + +import { openDataPlaceRepository } from "../database/services/place/open-data-place-repository"; +import { structureRepository } from "../database"; + +import { IsNull, Not } from "typeorm"; +import { appLogger } from "../util"; +import { cleanAddress, cleanCity } from "./cleanAddress"; + +export const loadDomifaData = async () => { + appLogger.info("Import DomiFa start 🏃‍♂️... "); + + try { + const places = await structureRepository.find({ + where: { + latitude: Not(IsNull()), + longitude: Not(IsNull()), + }, + select: [ + "nom", + "adresse", + "codePostal", + "ville", + "departement", + "region", + "latitude", + "longitude", + "id", + ], + }); + + for await (const place of places) { + let domifaPlace = await openDataPlaceRepository.findOneBy({ + source: "domifa", + uniqueId: place.id.toString(), + }); + + if (!domifaPlace) { + console.log("Place not exists: " + place.nom); + + domifaPlace = await openDataPlaceRepository.save( + new OpenDataPlaceTable({ + nom: place.nom, + adresse: cleanAddress(place.adresse), + codePostal: place.codePostal, + ville: cleanCity(place.ville), + departement: place.departement, + region: place.region, + software: "domifa", + latitude: place.latitude, + longitude: place.longitude, + source: "domifa", + structureId: place.id, + uniqueId: place.id.toString(), + }) + ); + } + } + appLogger.info("Import domifa complete"); + } catch (e) { + console.log(e); + console.error("[IMPORT] Something happen"); + } +}; diff --git a/packages/backend/src/open-data-places/load-soliguide.ts b/packages/backend/src/open-data-places/load-soliguide.ts new file mode 100644 index 0000000000..c200744a84 --- /dev/null +++ b/packages/backend/src/open-data-places/load-soliguide.ts @@ -0,0 +1,114 @@ +import axios from "axios"; +import { domifaConfig } from "../config"; +import { OpenDataPlaceTable } from "../database/entities/open-data-place"; +import { SoliguidePlace } from "./interfaces/SoliguidePlace.interface"; +import { departementHelper } from "../structures/services"; +import { openDataPlaceRepository } from "../database/services/place/open-data-place-repository"; +import { appLogger } from "../util"; +import { cleanAddress, cleanCity } from "./cleanAddress"; +import { OpenDataPlace } from "./interfaces/OpenDataPlace.interface"; + +let page = 1; +let nbResults = 0; + +export const loadSoliguideData = async () => { + if ( + !domifaConfig().openDataApps.soliguideUrl || + !domifaConfig().openDataApps.soliguideToken + ) { + console.log("[IMPORT DATA] Fail, token or url is not in env"); + return; + } + appLogger.info("Import Soliguide start 🏃‍♂️... "); + await getFromSoliguide(); +}; + +const getFromSoliguide = async () => { + let soliguideData: SoliguidePlace[] = []; + + try { + const response = await axios.post( + domifaConfig().openDataApps.soliguideUrl, + { + categorie: 402, + placeType: "LIEU", + location: { + geoType: "pays", + geoValue: "france", + }, + options: { + limit: 50, + page, + }, + }, + { + headers: { + Authorization: `JWT ${domifaConfig().openDataApps.soliguideToken}`, + }, + } + ); + + soliguideData = response.data.places; + nbResults = response.data.nbResults; + + for await (const place of soliguideData) { + let soliguidePlace = await openDataPlaceRepository.findOneBy({ + source: "soliguide", + uniqueId: place.lieu_id.toString(), + }); + + if (!soliguidePlace) { + const departement = departementHelper.getDepartementFromCodePostal( + place.position.codePostal + ); + + soliguidePlace = await openDataPlaceRepository.save( + new OpenDataPlaceTable({ + nom: place.name, + adresse: cleanAddress(place?.position?.adresse), + codePostal: place.position.codePostal, + ville: cleanCity(place?.position?.ville), + departement, + region: departementHelper.getRegionCodeFromDepartement(departement), + software: "other", + latitude: place.position.location.coordinates[1], + longitude: place.position.location.coordinates[0], + source: "soliguide", + uniqueId: place.lieu_id.toString(), + }) + ); + } + + const placeExist: OpenDataPlace = + await openDataPlaceRepository.findExistingPlace( + soliguidePlace.latitude, + soliguidePlace.longitude + ); + + if (placeExist) { + await openDataPlaceRepository.update( + { uuid: soliguidePlace.uuid }, + { structureId: placeExist.structureId } + ); + } + } + + if (soliguideData.length >= 50) { + appLogger.warn( + "Import Soliguide data " + + page + + " iteraction: " + + soliguideData.length * page + + "/" + + nbResults + ); + page++; + await getFromSoliguide(); + } else { + appLogger.info("END OF MIGRATION"); + } + } catch (e) { + console.log(e); + console.error("[IMPORT] Something happen"); + } +}; diff --git a/packages/backend/src/run-app.ts b/packages/backend/src/run-app.ts index 9369a12bd0..ba5d42a005 100644 --- a/packages/backend/src/run-app.ts +++ b/packages/backend/src/run-app.ts @@ -2,6 +2,10 @@ import "./open-telemetry"; import { bootstrapApplication, tearDownApplication } from "./app.bootstrap"; import { appLogger } from "./util"; +import { loadSoliguideData } from "./open-data-places/load-soliguide"; +import { loadDomifaData } from "./open-data-places/load-domifa"; +import { domifaConfig } from "./config"; +import { loadDataInclusionData } from "./open-data-places/load-data-inclusion"; (async () => { appLogger.warn(`[${__filename}] Starting app...`); @@ -13,6 +17,13 @@ import { appLogger } from "./util"; const server = await app.listen(3000); server.setTimeout(1000 * 60 * 5); appLogger.warn(`[${__filename}] Application listening on port 3000`); + + if (domifaConfig().envId === "local") { + await loadDomifaData(); + await loadDataInclusionData("CCAS"); + await loadDataInclusionData("CIAS"); + await loadSoliguideData(); + } } catch (error) { const err = error as Error; appLogger.error(`[${__filename}] Error running application`, {