fix: SonarQube - CGV partial + MeilisearchService deduplique
- templates/pdf/_services_list.html.twig : liste services partagee entre pdf/cgv.html.twig et legal/cgv.html.twig - MeilisearchService : extraction addToIndex/removeFromIndex/searchIndex generiques, serializeOrderDocument pour devis/advert/facture Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ sonar.php.coverage.reportPaths=var/reports/coverage.xml
|
||||
sonar.php.tests.reportPath=var/reports/phpunit.xml
|
||||
|
||||
# Duplication exclusions
|
||||
sonar.cpd.exclusions=migrations/**,src/Service/TarificationService.php,src/Entity/**,src/Repository/**,src/Service/Pdf/**,src/Service/AdvertService.php,src/Service/FactureService.php,src/Service/DevisService.php,templates/pdf/**
|
||||
sonar.cpd.exclusions=migrations/**,src/Service/TarificationService.php,src/Entity/**,src/Repository/**,src/Service/Pdf/**,src/Service/AdvertService.php,src/Service/FactureService.php,src/Service/DevisService.php
|
||||
|
||||
# Global rule ignores
|
||||
sonar.issue.ignore.multicriteria=e1,e2,e3
|
||||
|
||||
@@ -21,6 +21,46 @@ class MeilisearchService
|
||||
|
||||
private Client $client;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $document
|
||||
*/
|
||||
private function addToIndex(string $index, array $document, string $label): void
|
||||
{
|
||||
try {
|
||||
$this->client->index($index)->addDocuments([$document]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index '.$label.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function removeFromIndex(string $index, int $id, string $label): void
|
||||
{
|
||||
try {
|
||||
$this->client->index($index)->deleteDocument($id);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove '.$label.' '.$id.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function searchIndex(string $index, string $query, int $limit, ?int $customerId = null): array
|
||||
{
|
||||
try {
|
||||
$options = ['limit' => $limit];
|
||||
if (null !== $customerId) {
|
||||
$options['filter'] = self::FILTER_CUSTOMER_ID.$customerId;
|
||||
}
|
||||
|
||||
return $this->client->index($index)->search($query, $options)->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: search '.$index.' error: '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct(
|
||||
private LoggerInterface $logger,
|
||||
#[Autowire(env: 'MEILISEARCH_URL')] string $url,
|
||||
@@ -29,314 +69,50 @@ class MeilisearchService
|
||||
$this->client = new Client($url, $apiKey);
|
||||
}
|
||||
|
||||
public function indexCustomer(Customer $customer): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer')->addDocuments([
|
||||
$this->serializeCustomer($customer),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index customer '.$customer->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeCustomer(int $customerId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer')->deleteDocument($customerId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove customer '.$customerId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function indexRevendeur(Revendeur $revendeur): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('reseller')->addDocuments([
|
||||
$this->serializeRevendeur($revendeur),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index reseller '.$revendeur->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeRevendeur(int $revendeurId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('reseller')->deleteDocument($revendeurId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove reseller '.$revendeurId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
public function searchCustomers(string $query, int $limit = 20): array
|
||||
{
|
||||
try {
|
||||
$results = $this->client->index('customer')->search($query, ['limit' => $limit]);
|
||||
|
||||
return $results->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Search customers failed for "'.$query.'": '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
public function searchRevendeurs(string $query, int $limit = 20): array
|
||||
{
|
||||
try {
|
||||
$results = $this->client->index('reseller')->search($query, ['limit' => $limit]);
|
||||
|
||||
return $results->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Search resellers failed for "'.$query.'": '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function indexPrice(PriceAutomatic $price): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('price_auto')->addDocuments([
|
||||
$this->serializePrice($price),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index price '.$price->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removePrice(int $priceId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('price_auto')->deleteDocument($priceId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove price '.$priceId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
public function searchPrices(string $query, int $limit = 20): array
|
||||
{
|
||||
try {
|
||||
$results = $this->client->index('price_auto')->search($query, ['limit' => $limit]);
|
||||
|
||||
return $results->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Search prices failed for "'.$query.'": '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function indexContact(CustomerContact $contact): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_contact')->addDocuments([
|
||||
$this->serializeContact($contact),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index contact '.$contact->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeContact(int $contactId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_contact')->deleteDocument($contactId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove contact '.$contactId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
public function searchContacts(string $query, int $limit = 20): array
|
||||
{
|
||||
try {
|
||||
$results = $this->client->index('customer_contact')->search($query, ['limit' => $limit]);
|
||||
|
||||
return $results->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: search contacts error: '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function indexDomain(Domain $domain): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_ndd')->addDocuments([$this->serializeDomain($domain)]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index domain '.$domain->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeDomain(int $domainId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_ndd')->deleteDocument($domainId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove domain '.$domainId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function indexCustomer(Customer $customer): void { $this->addToIndex('customer', $this->serializeCustomer($customer), 'customer '.$customer->getId()); }
|
||||
public function removeCustomer(int $id): void { $this->removeFromIndex('customer', $id, 'customer'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchDomains(string $query, int $limit = 20): array
|
||||
{
|
||||
try {
|
||||
return $this->client->index('customer_ndd')->search($query, ['limit' => $limit])->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: search domains error: '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function indexWebsite(Website $website): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_website')->addDocuments([$this->serializeWebsite($website)]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index website '.$website->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeWebsite(int $websiteId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_website')->deleteDocument($websiteId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove website '.$websiteId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
public function searchCustomers(string $query, int $limit = 20): array { return $this->searchIndex('customer', $query, $limit); }
|
||||
|
||||
public function indexRevendeur(Revendeur $revendeur): void { $this->addToIndex('reseller', $this->serializeRevendeur($revendeur), 'reseller '.$revendeur->getId()); }
|
||||
public function removeRevendeur(int $id): void { $this->removeFromIndex('reseller', $id, 'reseller'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchWebsites(string $query, int $limit = 20): array
|
||||
{
|
||||
try {
|
||||
return $this->client->index('customer_website')->search($query, ['limit' => $limit])->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: search websites error: '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function indexDevis(Devis $devis): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_devis')->addDocuments([$this->serializeDevis($devis)]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index devis '.$devis->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeDevis(int $devisId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_devis')->deleteDocument($devisId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove devis '.$devisId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
public function searchRevendeurs(string $query, int $limit = 20): array { return $this->searchIndex('reseller', $query, $limit); }
|
||||
|
||||
public function indexPrice(PriceAutomatic $price): void { $this->addToIndex('price_auto', $this->serializePrice($price), 'price '.$price->getId()); }
|
||||
public function removePrice(int $id): void { $this->removeFromIndex('price_auto', $id, 'price'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchDevis(string $query, int $limit = 20, ?int $customerId = null): array
|
||||
{
|
||||
try {
|
||||
$options = ['limit' => $limit];
|
||||
if (null !== $customerId) {
|
||||
$options['filter'] = self::FILTER_CUSTOMER_ID.$customerId;
|
||||
}
|
||||
|
||||
return $this->client->index('customer_devis')->search($query, $options)->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: search devis error: '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function indexAdvert(Advert $advert): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_advert')->addDocuments([$this->serializeAdvert($advert)]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index advert '.$advert->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeAdvert(int $advertId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_advert')->deleteDocument($advertId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove advert '.$advertId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
public function searchPrices(string $query, int $limit = 20): array { return $this->searchIndex('price_auto', $query, $limit); }
|
||||
|
||||
public function indexContact(CustomerContact $contact): void { $this->addToIndex('customer_contact', $this->serializeContact($contact), 'contact '.$contact->getId()); }
|
||||
public function removeContact(int $id): void { $this->removeFromIndex('customer_contact', $id, 'contact'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchAdverts(string $query, int $limit = 20, ?int $customerId = null): array
|
||||
{
|
||||
try {
|
||||
$options = ['limit' => $limit];
|
||||
if (null !== $customerId) {
|
||||
$options['filter'] = self::FILTER_CUSTOMER_ID.$customerId;
|
||||
}
|
||||
|
||||
return $this->client->index('customer_advert')->search($query, $options)->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: search adverts error: '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function indexFacture(Facture $facture): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_facture')->addDocuments([$this->serializeFacture($facture)]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to index facture '.$facture->getId().': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function removeFacture(int $factureId): void
|
||||
{
|
||||
try {
|
||||
$this->client->index('customer_facture')->deleteDocument($factureId);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: Failed to remove facture '.$factureId.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
public function searchContacts(string $query, int $limit = 20): array { return $this->searchIndex('customer_contact', $query, $limit); }
|
||||
|
||||
public function indexDomain(Domain $domain): void { $this->addToIndex('customer_ndd', $this->serializeDomain($domain), 'domain '.$domain->getId()); }
|
||||
public function removeDomain(int $id): void { $this->removeFromIndex('customer_ndd', $id, 'domain'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchFactures(string $query, int $limit = 20, ?int $customerId = null): array
|
||||
{
|
||||
try {
|
||||
$options = ['limit' => $limit];
|
||||
if (null !== $customerId) {
|
||||
$options['filter'] = self::FILTER_CUSTOMER_ID.$customerId;
|
||||
}
|
||||
public function searchDomains(string $query, int $limit = 20): array { return $this->searchIndex('customer_ndd', $query, $limit); }
|
||||
|
||||
return $this->client->index('customer_facture')->search($query, $options)->getHits();
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Meilisearch: search factures error: '.$e->getMessage());
|
||||
public function indexWebsite(Website $website): void { $this->addToIndex('customer_website', $this->serializeWebsite($website), 'website '.$website->getId()); }
|
||||
public function removeWebsite(int $id): void { $this->removeFromIndex('customer_website', $id, 'website'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchWebsites(string $query, int $limit = 20): array { return $this->searchIndex('customer_website', $query, $limit); }
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
public function indexDevis(Devis $devis): void { $this->addToIndex('customer_devis', $this->serializeDevis($devis), 'devis '.$devis->getId()); }
|
||||
public function removeDevis(int $id): void { $this->removeFromIndex('customer_devis', $id, 'devis'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchDevis(string $query, int $limit = 20, ?int $customerId = null): array { return $this->searchIndex('customer_devis', $query, $limit, $customerId); }
|
||||
|
||||
public function indexAdvert(Advert $advert): void { $this->addToIndex('customer_advert', $this->serializeAdvert($advert), 'advert '.$advert->getId()); }
|
||||
public function removeAdvert(int $id): void { $this->removeFromIndex('customer_advert', $id, 'advert'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchAdverts(string $query, int $limit = 20, ?int $customerId = null): array { return $this->searchIndex('customer_advert', $query, $limit, $customerId); }
|
||||
|
||||
public function indexFacture(Facture $facture): void { $this->addToIndex('customer_facture', $this->serializeFacture($facture), 'facture '.$facture->getId()); }
|
||||
public function removeFacture(int $id): void { $this->removeFromIndex('customer_facture', $id, 'facture'); }
|
||||
/** @return list<array<string, mixed>> */
|
||||
public function searchFactures(string $query, int $limit = 20, ?int $customerId = null): array { return $this->searchIndex('customer_facture', $query, $limit, $customerId); }
|
||||
|
||||
public function purgeAllIndexes(): void
|
||||
{
|
||||
@@ -590,59 +366,43 @@ class MeilisearchService
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function serializeDevis(Devis $devis): array
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function serializeOrderDocument(object $doc, ?Customer $customer): array
|
||||
{
|
||||
$customer = $devis->getCustomer();
|
||||
|
||||
return [
|
||||
'id' => $devis->getId(),
|
||||
'numOrder' => $devis->getOrderNumber()->getNumOrder(),
|
||||
'state' => $devis->getState(),
|
||||
'totalHt' => $devis->getTotalHt(),
|
||||
'totalTtc' => $devis->getTotalTtc(),
|
||||
'id' => $doc->getId(),
|
||||
'numOrder' => $doc->getOrderNumber()->getNumOrder(),
|
||||
'state' => $doc->getState(),
|
||||
'totalHt' => $doc->getTotalHt(),
|
||||
'totalTtc' => $doc->getTotalTtc(),
|
||||
'customerId' => $customer?->getId(),
|
||||
'customerName' => $customer?->getFullName(),
|
||||
'customerEmail' => $customer?->getEmail(),
|
||||
'createdAt' => $devis->getCreatedAt()->format('Y-m-d'),
|
||||
'createdAt' => $doc->getCreatedAt()->format('Y-m-d'),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function serializeDevis(Devis $devis): array
|
||||
{
|
||||
return $this->serializeOrderDocument($devis, $devis->getCustomer());
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function serializeFacture(Facture $facture): array
|
||||
{
|
||||
$customer = $facture->getCustomer();
|
||||
|
||||
return [
|
||||
'id' => $facture->getId(),
|
||||
return array_merge($this->serializeOrderDocument($facture, $facture->getCustomer()), [
|
||||
'invoiceNumber' => $facture->getInvoiceNumber(),
|
||||
'state' => $facture->getState(),
|
||||
'totalHt' => $facture->getTotalHt(),
|
||||
'totalTtc' => $facture->getTotalTtc(),
|
||||
'isPaid' => $facture->isPaid(),
|
||||
'paidMethod' => $facture->getPaidMethod(),
|
||||
'customerId' => $customer?->getId(),
|
||||
'customerName' => $customer?->getFullName(),
|
||||
'customerEmail' => $customer?->getEmail(),
|
||||
'createdAt' => $facture->getCreatedAt()->format('Y-m-d'),
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function serializeAdvert(Advert $advert): array
|
||||
{
|
||||
$customer = $advert->getCustomer();
|
||||
|
||||
return [
|
||||
'id' => $advert->getId(),
|
||||
'numOrder' => $advert->getOrderNumber()->getNumOrder(),
|
||||
'state' => $advert->getState(),
|
||||
'totalHt' => $advert->getTotalHt(),
|
||||
'totalTtc' => $advert->getTotalTtc(),
|
||||
'customerId' => $customer?->getId(),
|
||||
'customerName' => $customer?->getFullName(),
|
||||
'customerEmail' => $customer?->getEmail(),
|
||||
'createdAt' => $advert->getCreatedAt()->format('Y-m-d'),
|
||||
];
|
||||
return $this->serializeOrderDocument($advert, $advert->getCustomer());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,7 @@
|
||||
<h2 class="text-xl font-bold uppercase mb-2">Article 2 - Prestations</h2>
|
||||
<p>La Association E-Cosplay propose les prestations suivantes, accessibles via la plateforme <strong>crm.e-cosplay.fr</strong> :</p>
|
||||
<ul class="list-disc pl-6 mt-2">
|
||||
<li><strong>E-Site</strong> : creation, hebergement et maintenance de sites E-Site via le CMS <strong>Esy-Web</strong>, solution developpee par l'association</li>
|
||||
<li><strong>E-Mail</strong> : hebergement et gestion de messagerie professionnelle, utilisant l'infrastructure Amazon Simple Email Service (AWS SES)</li>
|
||||
<li><strong>E-Mailer</strong> : creation et envoi de campagnes emailing</li>
|
||||
<li><strong>E-Track</strong> : suivi et analyse de frequentation des sites E-Site</li>
|
||||
<li><strong>E-Protect</strong> : protection et securisation des infrastructures et des sites E-Site</li>
|
||||
<li><strong>E-Translate</strong> : traduction automatique et multilingue des contenus</li>
|
||||
<li><strong>E-Sign</strong> : signature electronique de documents</li>
|
||||
<li><strong>E-Calendar</strong> : prise de rendez-vous en ligne, propulsee par <strong>Cal.com</strong></li>
|
||||
<li><strong>E-Chat</strong> : chat en ligne en direct sur votre site E-Site, propulsee par <strong>Chatwoot</strong></li>
|
||||
<li><strong>Service de Nom de Domaine</strong> : depot, enregistrement, renouvellement et gestion de noms de domaine pour le compte du client</li>
|
||||
{{ include('pdf/_services_list.html.twig') }}
|
||||
</ul>
|
||||
<p class="mt-2">L'ensemble des services est heberge sur l'infrastructure geree par la Association E-Cosplay, a l'exception d'<strong>E-Calendar</strong> (propulsee par Cal.com) et d'<strong>E-Chat</strong> (propulsee par Chatwoot) qui sont des solutions tierces, sauf disposition exceptionnelle.</p>
|
||||
<p class="mt-2">Le detail des prestations, leurs specificites techniques et les options disponibles sont precises dans le contrat de service conclu entre le client et la société.</p>
|
||||
|
||||
10
templates/pdf/_services_list.html.twig
Normal file
10
templates/pdf/_services_list.html.twig
Normal file
@@ -0,0 +1,10 @@
|
||||
<li><strong>E-Site</strong> : creation, hebergement et maintenance de sites E-Site via le CMS <strong>Esy-Web</strong>, solution developpee par l'association</li>
|
||||
<li><strong>E-Mail</strong> : hebergement et gestion de messagerie professionnelle, utilisant l'infrastructure Amazon Simple Email Service (AWS SES)</li>
|
||||
<li><strong>E-Mailer</strong> : creation et envoi de campagnes emailing</li>
|
||||
<li><strong>E-Track</strong> : suivi et analyse de frequentation des sites E-Site</li>
|
||||
<li><strong>E-Protect</strong> : protection et securisation des infrastructures et des sites E-Site</li>
|
||||
<li><strong>E-Translate</strong> : traduction automatique et multilingue des contenus</li>
|
||||
<li><strong>E-Sign</strong> : signature electronique de documents</li>
|
||||
<li><strong>E-Calendar</strong> : prise de rendez-vous en ligne, propulsee par <strong>Cal.com</strong></li>
|
||||
<li><strong>E-Chat</strong> : chat en ligne en direct sur votre site E-Site, propulsee par <strong>Chatwoot</strong></li>
|
||||
<li><strong>Service de Nom de Domaine</strong> : depot, enregistrement, renouvellement et gestion de noms de domaine pour le compte du client</li>
|
||||
@@ -32,16 +32,7 @@
|
||||
<h2>Article 2 - Prestations</h2>
|
||||
<p>L'Association E-Cosplay propose les prestations suivantes, accessibles via la plateforme <strong>crm.e-cosplay.fr</strong> :</p>
|
||||
<ul>
|
||||
<li><strong>E-Site</strong> : creation, hebergement et maintenance de sites E-Site via le CMS <strong>Esy-Web</strong>, solution developpee par l'association</li>
|
||||
<li><strong>E-Mail</strong> : hebergement et gestion de messagerie professionnelle, utilisant l'infrastructure Amazon Simple Email Service (AWS SES)</li>
|
||||
<li><strong>E-Mailer</strong> : creation et envoi de campagnes emailing</li>
|
||||
<li><strong>E-Track</strong> : suivi et analyse de frequentation des sites E-Site</li>
|
||||
<li><strong>E-Protect</strong> : protection et securisation des infrastructures et des sites E-Site</li>
|
||||
<li><strong>E-Translate</strong> : traduction automatique et multilingue des contenus</li>
|
||||
<li><strong>E-Sign</strong> : signature electronique de documents</li>
|
||||
<li><strong>E-Calendar</strong> : prise de rendez-vous en ligne, propulsee par <strong>Cal.com</strong></li>
|
||||
<li><strong>E-Chat</strong> : chat en ligne en direct sur votre site E-Site, propulsee par <strong>Chatwoot</strong></li>
|
||||
<li><strong>Service de Nom de Domaine</strong> : depot, enregistrement, renouvellement et gestion de noms de domaine pour le compte du client</li>
|
||||
{{ include('pdf/_services_list.html.twig') }}
|
||||
</ul>
|
||||
<p>L'ensemble des services est heberge sur l'infrastructure geree par l'Association E-Cosplay, a l'exception d'<strong>E-Calendar</strong> (propulsee par Cal.com) et d'<strong>E-Chat</strong> (propulsee par Chatwoot) qui sont des solutions tierces, sauf disposition exceptionnelle.</p>
|
||||
<p>Le detail des prestations, leurs specificites techniques et les options disponibles sont precises dans le contrat de service conclu entre le client et la societe.</p>
|
||||
|
||||
Reference in New Issue
Block a user