2025-05-26 11:32:53 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Entity;
|
|
|
|
|
|
|
|
use App\Repository\StatsRepository;
|
|
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
|
|
|
use Doctrine\Common\Collections\Collection;
|
|
|
|
use Doctrine\DBAL\Types\Types;
|
|
|
|
use Doctrine\ORM\Mapping as ORM;
|
|
|
|
|
|
|
|
#[ORM\Entity(repositoryClass: StatsRepository::class)]
|
|
|
|
class Stats
|
|
|
|
{
|
|
|
|
#[ORM\Id]
|
|
|
|
#[ORM\GeneratedValue]
|
|
|
|
#[ORM\Column]
|
|
|
|
private ?int $id = null;
|
|
|
|
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(length: 255, type: Types::STRING, nullable: true)]
|
2025-06-17 13:23:47 +02:00
|
|
|
private ?string $zone = null; // code insee de la zone
|
2025-05-26 11:32:53 +02:00
|
|
|
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-05-26 11:32:53 +02:00
|
|
|
private ?int $completion_percent = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Collection<int, Place>
|
|
|
|
*/
|
2025-06-04 00:16:56 +02:00
|
|
|
#[ORM\OneToMany(targetEntity: Place::class, mappedBy: 'stats', cascade: ['persist', 'remove'])]
|
2025-05-26 11:32:53 +02:00
|
|
|
private Collection $places;
|
|
|
|
|
2025-05-26 23:51:46 +02:00
|
|
|
// nombre de commerces dans la zone
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-05-26 11:32:53 +02:00
|
|
|
private ?int $places_count = null;
|
|
|
|
|
2025-05-26 23:51:46 +02:00
|
|
|
// nombre de commerces avec horaires
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-05-26 23:51:46 +02:00
|
|
|
private ?int $avec_horaires = null;
|
|
|
|
|
|
|
|
// nombre de commerces avec adresse
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-05-26 23:51:46 +02:00
|
|
|
private ?int $avec_adresse = null;
|
|
|
|
|
|
|
|
// nombre de commerces avec site
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-05-26 23:51:46 +02:00
|
|
|
private ?int $avec_site = null;
|
|
|
|
|
|
|
|
// nombre de commerces avec accessibilité
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-05-26 23:51:46 +02:00
|
|
|
private ?int $avec_accessibilite = null;
|
|
|
|
|
|
|
|
// nombre de commerces avec note
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-05-26 23:51:46 +02:00
|
|
|
private ?int $avec_note = null;
|
|
|
|
|
2025-06-23 00:53:10 +02:00
|
|
|
#[ORM\Column(length: 255, nullable: true, options: ['charset' => 'utf8mb4'] )]
|
2025-06-03 12:51:20 +02:00
|
|
|
private ?string $name = null;
|
|
|
|
|
2025-06-17 16:23:29 +02:00
|
|
|
// nombre d'habitants dans la zone
|
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
|
|
|
private ?int $population = null;
|
|
|
|
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-06-17 18:27:19 +02:00
|
|
|
private ?int $siren = null;
|
|
|
|
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(type: Types::INTEGER, nullable: true)]
|
2025-06-17 18:27:19 +02:00
|
|
|
private ?int $codeEpci = null;
|
|
|
|
|
|
|
|
#[ORM\Column(length: 255, nullable: true)]
|
|
|
|
private ?string $codesPostaux = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Collection<int, StatsHistory>
|
|
|
|
*/
|
|
|
|
#[ORM\OneToMany(targetEntity: StatsHistory::class, mappedBy: 'stats')]
|
|
|
|
private Collection $statsHistories;
|
|
|
|
|
2025-06-17 19:38:44 +02:00
|
|
|
#[ORM\Column(nullable: true)]
|
|
|
|
private ?\DateTime $date_created = null;
|
|
|
|
|
|
|
|
#[ORM\Column(nullable: true)]
|
|
|
|
private ?\DateTime $date_modified = null;
|
|
|
|
|
|
|
|
#[ORM\Column(nullable: true)]
|
|
|
|
private ?int $avec_siret = null;
|
|
|
|
|
|
|
|
#[ORM\Column(nullable: true)]
|
|
|
|
private ?int $avec_name = null;
|
|
|
|
|
2025-06-19 10:20:40 +02:00
|
|
|
#[ORM\Column(nullable: true)]
|
|
|
|
private ?\DateTime $osm_data_date_min = null;
|
|
|
|
|
|
|
|
#[ORM\Column(nullable: true)]
|
|
|
|
private ?\DateTime $osm_data_date_avg = null;
|
|
|
|
|
|
|
|
#[ORM\Column(nullable: true)]
|
|
|
|
private ?\DateTime $osm_data_date_max = null;
|
|
|
|
|
2025-06-24 12:30:39 +02:00
|
|
|
#[ORM\Column(type: Types::DECIMAL, precision: 15, scale: 2, nullable: true)]
|
|
|
|
private ?string $budget_annuel = null;
|
|
|
|
|
2025-06-18 00:41:24 +02:00
|
|
|
public function getCTCurlBase(): ?string
|
|
|
|
{
|
|
|
|
$base = 'https://complete-tes-commerces.fr/';
|
|
|
|
$zone = $this->zone;
|
|
|
|
|
|
|
|
$departement = substr($zone, 0, 2);
|
|
|
|
$insee_code = $zone;
|
|
|
|
$slug = strtolower(str_replace(' ', '-', $this->getName()));
|
|
|
|
$url = $base . $departement . '/' . $insee_code . '-'.$slug.'/json/' . $slug ;
|
|
|
|
|
|
|
|
return $url;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getLastStats(): string
|
|
|
|
{
|
|
|
|
return $this->getParametricJsonFromCTC('_last_stats');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getDailyStats(): string
|
|
|
|
{
|
|
|
|
return $this->getParametricJsonFromCTC('_dailystats');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getOSMClosedSirets(): string
|
|
|
|
{
|
|
|
|
return $this->getParametricJsonFromCTC('_osm_closed_siret');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getOSMDisusedShops(): string
|
|
|
|
{
|
|
|
|
return $this->getParametricJsonFromCTC('_osm_disused_shops');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getOSMNoSiteShops(): string
|
|
|
|
{
|
|
|
|
return $this->getParametricJsonFromCTC('_osm_no_site_shops');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPanoFile(): string
|
|
|
|
{
|
|
|
|
return $this->getParametricJsonFromCTC('_pano_file');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getClosedPanoFile(): string
|
|
|
|
{
|
|
|
|
return $this->getParametricJsonFromCTC('_closed_pano_file');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSireneMatches(): string
|
|
|
|
{
|
|
|
|
return $this->getParametricJsonFromCTC('_sirene_matches');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getParametricJsonFromCTC($suffixe): string
|
|
|
|
{
|
|
|
|
$url = $this->getCTCurlBase().$suffixe.'.json';
|
|
|
|
|
|
|
|
return $url;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function getAllCTCUrlsMap(): ?array
|
|
|
|
{
|
|
|
|
$functions = [
|
|
|
|
'getLastStats',
|
|
|
|
'getDailyStats',
|
|
|
|
'getOSMClosedSirets',
|
|
|
|
'getOSMDisusedShops',
|
|
|
|
'getOSMNoSiteShops',
|
|
|
|
];
|
|
|
|
|
|
|
|
$urls = [];
|
|
|
|
foreach ($functions as $function) {
|
|
|
|
$urls[$function] = $this->$function();
|
|
|
|
}
|
|
|
|
return $urls;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-05-26 23:51:46 +02:00
|
|
|
// calcule le pourcentage de complétion de la zone
|
|
|
|
public function computeCompletionPercent(): ?int
|
|
|
|
{
|
2025-06-05 17:32:12 +02:00
|
|
|
|
|
|
|
$places_count = $this->places->count();
|
2025-05-26 23:51:46 +02:00
|
|
|
// Si aucun commerce, on retourne 0
|
2025-06-05 17:32:12 +02:00
|
|
|
if ($places_count === 0 || $places_count === null) {
|
2025-05-26 23:51:46 +02:00
|
|
|
$this->setCompletionPercent(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2025-06-05 17:32:12 +02:00
|
|
|
// On réinitialise les compteurs
|
|
|
|
$this->avec_horaires = 0;
|
|
|
|
$this->avec_adresse = 0;
|
|
|
|
$this->avec_site = 0;
|
|
|
|
$this->avec_accessibilite = 0;
|
|
|
|
$this->avec_note = 0;
|
|
|
|
|
|
|
|
$somme_completions = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// On boucle sur chaque place pour compter les attributs renseignés
|
|
|
|
foreach ($this->places as $place) {
|
|
|
|
$place_completions = 0;
|
|
|
|
if ($place->hasAddress()) {
|
|
|
|
$this->avec_adresse++;
|
|
|
|
$place_completions++;
|
|
|
|
}
|
|
|
|
if ($place->hasWebsite()) {
|
|
|
|
$this->avec_site++;
|
|
|
|
$place_completions++;
|
|
|
|
}
|
|
|
|
if ($place->hasWheelchair()) {
|
|
|
|
$this->avec_accessibilite++;
|
|
|
|
$place_completions++;
|
|
|
|
}
|
|
|
|
if ($place->hasOpeningHours()) {
|
|
|
|
$this->avec_horaires++;
|
|
|
|
$place_completions++;
|
|
|
|
}
|
|
|
|
if($place->hasNote()) {
|
|
|
|
$this->avec_note++;
|
|
|
|
}
|
|
|
|
$somme_completions += $place_completions / 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->setPlacesCount($places_count);
|
|
|
|
$this->setCompletionPercent(round($somme_completions / $places_count * 100));
|
2025-05-26 23:51:46 +02:00
|
|
|
return $this->completion_percent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-05-26 11:32:53 +02:00
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
$this->places = new ArrayCollection();
|
2025-06-17 18:27:19 +02:00
|
|
|
$this->statsHistories = new ArrayCollection();
|
2025-05-26 11:32:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getId(): ?int
|
|
|
|
{
|
|
|
|
return $this->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getZone(): ?string
|
|
|
|
{
|
|
|
|
return $this->zone;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setZone(string $zone): static
|
|
|
|
{
|
|
|
|
$this->zone = $zone;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCompletionPercent(): ?int
|
|
|
|
{
|
|
|
|
return $this->completion_percent;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setCompletionPercent(int $completion_percent): static
|
|
|
|
{
|
|
|
|
$this->completion_percent = $completion_percent;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return Collection<int, Place>
|
|
|
|
*/
|
|
|
|
public function getPlaces(): Collection
|
|
|
|
{
|
|
|
|
return $this->places;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addPlace(Place $place): static
|
|
|
|
{
|
|
|
|
if (!$this->places->contains($place)) {
|
|
|
|
$this->places->add($place);
|
|
|
|
$place->setStats($this);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function removePlace(Place $place): static
|
|
|
|
{
|
|
|
|
if ($this->places->removeElement($place)) {
|
|
|
|
// set the owning side to null (unless already changed)
|
|
|
|
if ($place->getStats() === $this) {
|
|
|
|
$place->setStats(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPlacesCount(): ?int
|
|
|
|
{
|
|
|
|
return $this->places_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setPlacesCount(int $places_count): static
|
|
|
|
{
|
|
|
|
$this->places_count = $places_count;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2025-05-26 23:51:46 +02:00
|
|
|
|
|
|
|
public function getAvecHoraires(): ?int
|
|
|
|
{
|
|
|
|
return $this->avec_horaires;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setAvecHoraires(int $avec_horaires): static
|
|
|
|
{
|
|
|
|
$this->avec_horaires = $avec_horaires;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAvecAdresse(): ?int
|
|
|
|
{
|
|
|
|
return $this->avec_adresse;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setAvecAdresse(int $avec_adresse): static
|
|
|
|
{
|
|
|
|
$this->avec_adresse = $avec_adresse;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAvecSite(): ?int
|
|
|
|
{
|
|
|
|
return $this->avec_site;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setAvecSite(int $avec_site): static
|
|
|
|
{
|
|
|
|
$this->avec_site = $avec_site;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAvecAccessibilite(): ?int
|
|
|
|
{
|
|
|
|
return $this->avec_accessibilite;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setAvecAccessibilite(int $avec_accessibilite): static
|
|
|
|
{
|
|
|
|
$this->avec_accessibilite = $avec_accessibilite;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAvecNote(): ?int
|
|
|
|
{
|
|
|
|
return $this->avec_note;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setAvecNote(int $avec_note): static
|
|
|
|
{
|
|
|
|
$this->avec_note = $avec_note;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2025-06-03 12:51:20 +02:00
|
|
|
|
|
|
|
public function getName(): ?string
|
|
|
|
{
|
|
|
|
return $this->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setName(?string $name): static
|
|
|
|
{
|
|
|
|
$this->name = $name;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2025-06-17 16:23:29 +02:00
|
|
|
|
|
|
|
public function getPopulation(): ?int
|
|
|
|
{
|
|
|
|
return $this->population;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setPopulation(?int $population): static
|
|
|
|
{
|
|
|
|
$this->population = $population;
|
|
|
|
return $this;
|
|
|
|
}
|
2025-06-17 18:27:19 +02:00
|
|
|
|
|
|
|
public function getSiren(): ?int
|
|
|
|
{
|
|
|
|
return $this->siren;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setSiren(?int $siren): static
|
|
|
|
{
|
|
|
|
$this->siren = $siren;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCodeEpci(): ?int
|
|
|
|
{
|
|
|
|
return $this->codeEpci;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setCodeEpci(?int $codeEpci): static
|
|
|
|
{
|
|
|
|
$this->codeEpci = $codeEpci;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCodesPostaux(): ?string
|
|
|
|
{
|
|
|
|
return $this->codesPostaux;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setCodesPostaux(?string $codesPostaux): static
|
|
|
|
{
|
|
|
|
$this->codesPostaux = $codesPostaux;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return Collection<int, StatsHistory>
|
|
|
|
*/
|
|
|
|
public function getStatsHistories(): Collection
|
|
|
|
{
|
|
|
|
return $this->statsHistories;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addStatsHistory(StatsHistory $statsHistory): static
|
|
|
|
{
|
|
|
|
if (!$this->statsHistories->contains($statsHistory)) {
|
|
|
|
$this->statsHistories->add($statsHistory);
|
|
|
|
$statsHistory->setStats($this);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function removeStatsHistory(StatsHistory $statsHistory): static
|
|
|
|
{
|
|
|
|
if ($this->statsHistories->removeElement($statsHistory)) {
|
|
|
|
// set the owning side to null (unless already changed)
|
|
|
|
if ($statsHistory->getStats() === $this) {
|
|
|
|
$statsHistory->setStats(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2025-06-17 19:38:44 +02:00
|
|
|
|
|
|
|
public function getDateCreated(): ?\DateTime
|
|
|
|
{
|
|
|
|
return $this->date_created;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setDateCreated(?\DateTime $date_created): static
|
|
|
|
{
|
|
|
|
$this->date_created = $date_created;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getDateModified(): ?\DateTime
|
|
|
|
{
|
|
|
|
return $this->date_modified;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setDateModified(?\DateTime $date_modified): static
|
|
|
|
{
|
|
|
|
$this->date_modified = $date_modified;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAvecSiret(): ?int
|
|
|
|
{
|
|
|
|
return $this->avec_siret;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setAvecSiret(?int $avec_siret): static
|
|
|
|
{
|
|
|
|
$this->avec_siret = $avec_siret;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAvecName(): ?int
|
|
|
|
{
|
|
|
|
return $this->avec_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setAvecName(?int $avec_name): static
|
|
|
|
{
|
|
|
|
$this->avec_name = $avec_name;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2025-06-19 10:20:40 +02:00
|
|
|
|
|
|
|
public function getOsmDataDateMin(): ?\DateTime
|
|
|
|
{
|
|
|
|
return $this->osm_data_date_min;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setOsmDataDateMin(?\DateTime $osm_data_date_min): static
|
|
|
|
{
|
|
|
|
$this->osm_data_date_min = $osm_data_date_min;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getOsmDataDateAvg(): ?\DateTime
|
|
|
|
{
|
|
|
|
return $this->osm_data_date_avg;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setOsmDataDateAvg(?\DateTime $osm_data_date_avg): static
|
|
|
|
{
|
|
|
|
$this->osm_data_date_avg = $osm_data_date_avg;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getOsmDataDateMax(): ?\DateTime
|
|
|
|
{
|
|
|
|
return $this->osm_data_date_max;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setOsmDataDateMax(?\DateTime $osm_data_date_max): static
|
|
|
|
{
|
|
|
|
$this->osm_data_date_max = $osm_data_date_max;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2025-06-24 12:30:39 +02:00
|
|
|
|
|
|
|
public function getBudgetAnnuel(): ?string
|
|
|
|
{
|
|
|
|
return $this->budget_annuel;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setBudgetAnnuel(?string $budget_annuel): static
|
|
|
|
{
|
|
|
|
$this->budget_annuel = $budget_annuel;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2025-05-26 23:51:46 +02:00
|
|
|
|
|
|
|
|
|
|
|
}
|