https://dev.app.pol-crm.com/api/templates/f47ef469dac34bc29180feb40a25724c Return to referer URL

Security Token

demoyanigav Username
Authenticated
Property Value
Roles
[
  "ROLE_USER"
  "ROLE_SUPERADMIN"
  "ROLE_ADMIN"
  "ROLE_MODULE_PRODUCT"
  "ROLE_MODULE_PRODUCT_CUSTOMIZE"
  "ROLE_MODULE_QUOTE_LINE"
  "PROSPECT_SHOW"
  "PROSPECT_CUD"
  "CONTACT_CUD"
  "CONTACT_SHOW"
  "TASK_SHOW"
  "TASK_CUD"
  "QUOTE_SHOW"
  "QUOTE_CUD"
  "QUOTE_REGENERATE_PRICES"
]
Inherited Roles none
Token
Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Token\JWTUserToken {#494
  #rawToken: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3NjA5MTI0NDEsImV4cCI6MTc2MDkxNjA0MSwicm9sZXMiOlsiUk9MRV9VU0VSIiwiUk9MRV9TVVBFUkFETUlOIiwiUk9MRV9BRE1JTiIsIlJPTEVfTU9EVUxFX1BST0RVQ1QiLCJST0xFX01PRFVMRV9QUk9EVUNUX0NVU1RPTUlaRSIsIlJPTEVfTU9EVUxFX1FVT1RFX0xJTkUiLCJQUk9TUEVDVF9TSE9XIiwiUFJPU1BFQ1RfQ1VEIiwiQ09OVEFDVF9DVUQiLCJDT05UQUNUX1NIT1ciLCJUQVNLX1NIT1ciLCJUQVNLX0NVRCIsIlFVT1RFX1NIT1ciLCJRVU9URV9DVUQiLCJRVU9URV9SRUdFTkVSQVRFX1BSSUNFUyJdLCJsb2dpbiI6ImRlbW95YW5pZ2F2IiwidXNlcl9pZCI6InVzZXJfMTAxMSIsInVzZXJfZXh0ZXJuYWxfaWQiOiIxMDExIiwiZW1haWwiOiJnLXNhdXRyb25Ac2ZpLmZyIiwiY3VzdG9tZXJfaWQiOiJjdXN0b21lcl8xMjEiLCJjdXN0b21lcl9uYW1lIjoiWUFOSUdBViIsImN1c3RvbWVyX2V4dGVybmFsX2lkIjoiMTIxIiwiY3VzdG9tZXJfbWFpbGluZ19pZCI6IjE0NyIsImZpcnN0bmFtZSI6Ikd1aWxsYXVtZSIsImxhc3RuYW1lIjoiU0FVVFJPTiIsImxpdmVvTG9naW4iOm51bGwsImxpdmVvUGFzc3dvcmQiOm51bGwsImhhc0ludHJhbmV0IjpmYWxzZSwibGFuZ3VhZ2UiOiJGUiIsInNlY3Rpb25zX2xlYWRlZCI6W10sInNlY3Rpb25zX21lbWJlcnMiOlsidXNlcl8xMDExIl0sImlzX3NlY3Rpb25zX2FjdGl2YXRlZCI6ZmFsc2UsInJlZnJlc2hfdG9rZW4iOiIifQ.smruhTDO6MF4efpXGiPp4DyZoLSpsUh3ykwBDmscLGtkvlySQlnSFvS1bxozG8T5Y0oGdkijvDiliogWK_zhqLF6FXho-oEscgCbKhvTjdosGLc4QHX0QAtM1LeVpT3BGVz9isHY1J7X0RDnoWA2GdCwCZ-ELXlS7fP08w_Mc5j8GqGhN5XwD70MLfR5ltD75o5BEhCWKMsWsatkGs3bbd7AfjhqoSz7qexpiHj1BRszq-H5QekWiJWgwOLDUJc85rZYaNVbYu75qseEbKfW-kWAxOZhAZCmVfFDQ-qBxSJ1i7KwVasIGTJDTnJn7l8fDqFWF0jGtC4LJzQEOZDjoOrQVaP2szLusNdOeKICnE3GOpY7E2sHIJpbTf8KlRUSm0uKc4t4hgoSRxnCdQGLx4hcTGSGHyITgso7tVs6068piCfp8JttEo5SoXERPiVNl2oeKa7VQAgtUWMzPI-SYX6QfGCjnrYE3JcTufx8xFtvlS4pmeIaLNJs7Y8l21f-A8MB7y-3zOAzriYExuKUOtT9oZ0GRtCWG5oTUyQ2LI4IjzaqBW_ikRfcccdSOZqZxV_FVw1fO9vPg9Lgi9XKAfKtjCLtI9nMboiZsSk9mx5_CAREqtb476hnnUVOfvHCBazVRQo-FWsSSWNLCIe8MtR9pUny0D8hn5qCQ712Axk"
  #providerKey: "api"
  -user: App\Security\User {#422 …}
  -roles: [
    Symfony\Component\Security\Core\Role\Role {#757
      -role: "ROLE_USER"
    }
    Symfony\Component\Security\Core\Role\Role {#759
      -role: "ROLE_SUPERADMIN"
    }
    Symfony\Component\Security\Core\Role\Role {#758
      -role: "ROLE_ADMIN"
    }
    Symfony\Component\Security\Core\Role\Role {#472
      -role: "ROLE_MODULE_PRODUCT"
    }
    Symfony\Component\Security\Core\Role\Role {#760
      -role: "ROLE_MODULE_PRODUCT_CUSTOMIZE"
    }
    Symfony\Component\Security\Core\Role\Role {#761
      -role: "ROLE_MODULE_QUOTE_LINE"
    }
    Symfony\Component\Security\Core\Role\Role {#762
      -role: "PROSPECT_SHOW"
    }
    Symfony\Component\Security\Core\Role\Role {#763
      -role: "PROSPECT_CUD"
    }
    Symfony\Component\Security\Core\Role\Role {#764
      -role: "CONTACT_CUD"
    }
    Symfony\Component\Security\Core\Role\Role {#765
      -role: "CONTACT_SHOW"
    }
    Symfony\Component\Security\Core\Role\Role {#766
      -role: "TASK_SHOW"
    }
    Symfony\Component\Security\Core\Role\Role {#767
      -role: "TASK_CUD"
    }
    Symfony\Component\Security\Core\Role\Role {#768
      -role: "QUOTE_SHOW"
    }
    Symfony\Component\Security\Core\Role\Role {#769
      -role: "QUOTE_CUD"
    }
    Symfony\Component\Security\Core\Role\Role {#770
      -role: "QUOTE_REGENERATE_PRICES"
    }
  ]
  -roleNames: [
    "ROLE_USER"
    "ROLE_SUPERADMIN"
    "ROLE_ADMIN"
    "ROLE_MODULE_PRODUCT"
    "ROLE_MODULE_PRODUCT_CUSTOMIZE"
    "ROLE_MODULE_QUOTE_LINE"
    "PROSPECT_SHOW"
    "PROSPECT_CUD"
    "CONTACT_CUD"
    "CONTACT_SHOW"
    "TASK_SHOW"
    "TASK_CUD"
    "QUOTE_SHOW"
    "QUOTE_CUD"
    "QUOTE_REGENERATE_PRICES"
  ]
  -authenticated: true
  -attributes: []
}

Security Firewall

api Name
Security enabled
Stateless
Allows anonymous

Configuration

Key Value
provider security.user.provider.concrete.jwt
context (none)
entry_point App\Security\JWTTokenWhitelistAuthenticator
user_checker security.user_checker
access_denied_handler (none)
access_denied_url (none)
listeners
[
  "guard"
  "anonymous"
]

Listeners

Listener Duration Response
Symfony\Component\Security\Http\Firewall\ChannelListener {#483
  -map: Symfony\Component\Security\Http\AccessMap {#469 …}
  -authenticationEntryPoint: Symfony\Component\Security\Http\EntryPoint\RetryAuthenticationEntryPoint {#428 …}
  -logger: Symfony\Bridge\Monolog\Logger {#417 …}
}
0.00 ms (none)
Symfony\Component\Security\Guard\Firewall\GuardAuthenticationListener {#420
  -guardHandler: Symfony\Component\Security\Guard\GuardAuthenticatorHandler {#419 …}
  -authenticationManager: Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager {#1085 …}
  -providerKey: "api"
  -guardAuthenticators: Symfony\Component\DependencyInjection\Argument\RewindableGenerator {#459 …}
  -logger: Symfony\Bridge\Monolog\Logger {#417 …}
  -rememberMeServices: null
}
6.93 ms (none)
Symfony\Component\Security\Http\Firewall\AnonymousAuthenticationListener {#448
  -tokenStorage: Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage {#1320 …}
  -secret: "Vx0Rxv0"
  -authenticationManager: Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager {#1085 …}
  -logger: Symfony\Bridge\Monolog\Logger {#417 …}
}
0.00 ms (none)
Symfony\Component\Security\Http\Firewall\AccessListener {#439
  -tokenStorage: Symfony\Component\Security\Core\Authentication\Token\Storage\UsageTrackingTokenStorage {#1146 …}
  -accessDecisionManager: Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager {#1148 …}
  -map: Symfony\Component\Security\Http\AccessMap {#469 …}
  -authManager: Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager {#1085 …}
}
0.48 ms (none)

Security Voters (29)

affirmative Strategy
# Voter class
1
"Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter"
2
"Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter"
3
"Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter"
4
"App\V4\Voters\ContactVoter"
5
"App\V4\Voters\CustomActionVoter"
6
"App\V4\Voters\CustomEventTriggerVoter"
7
"App\V4\Voters\CustomerEventServiceVoter"
8
"App\V4\Voters\DolibarrApiVoter"
9
"App\V4\Voters\ListingVoter"
10
"App\V4\Voters\MailTypeVoter"
11
"App\V4\Voters\OutlookSubscriptionConfigurationVoter"
12
"App\V4\Voters\ProspectVoter"
13
"App\V4\Voters\QuoteVoter"
14
"App\V4\Voters\SavedRequestVoter"
15
"App\V4\Voters\SectionVoter"
16
"App\V4\Voters\TabVoter"
17
"App\V4\Voters\TagVoter"
18
"App\V4\Voters\TaskVoter"
19
"App\V4\Voters\UnitMailVoter"
20
"App\V4\Voters\UserInfoVoter"
21
"App\Voters\AdvancedQuoteVoter"
22
"App\Voters\CampaignVoter"
23
"App\Voters\ContactVoter"
24
"App\Voters\ModuleConfigurationVoter"
25
"App\Voters\ModuleVoter"
26
"App\Voters\ProductVoter"
27
"App\Voters\ProspectVoter"
28
"App\Voters\QuoteVoter"
29
"App\Voters\TaskVoter"

Access decision log

# Result Attributes Object
1 GRANTED IS_AUTHENTICATED_FULLY
Symfony\Component\HttpFoundation\Request {#55
  +attributes: Symfony\Component\HttpFoundation\ParameterBag {#92 …}
  +request: Symfony\Component\HttpFoundation\ParameterBag {#98 …}
  +query: Symfony\Component\HttpFoundation\ParameterBag {#93 …}
  +server: Symfony\Component\HttpFoundation\ServerBag {#89 …}
  +files: Symfony\Component\HttpFoundation\FileBag {#90 …}
  +cookies: Symfony\Component\HttpFoundation\ParameterBag {#91 …}
  +headers: Symfony\Component\HttpFoundation\HeaderBag {#88 …}
  #content: "{"id":"f47ef469dac34bc29180feb40a25724c","customerId":"customer_121","name":"Test","content":"<!doctype html>\n<html lang=\"fr\">\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Devis – YANIGAV – {{ quote.name|default('Enfonce-pieux HYDROCHOC HPG 790') }}</title>\n<style>\n  :root { --primary:#0f172a; --muted:#475569; --border:#e2e8f0; --bg:#f8fafc; }\n  html, body { margin:0; padding:0; background:var(--bg); color:#0b1220; font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,\"Apple Color Emoji\",\"Segoe UI Emoji\"; }\n  .page { max-width:900px; margin:2rem auto; background:#fff; border:1px solid var(--border); border-radius:12px; overflow:hidden; box-shadow:0 10px 30px rgba(0,0,0,.04); }\n  header { padding:1.25rem 1.5rem; background:#fff; border-bottom:1px solid var(--border); display:flex; gap:1rem; align-items:center; }\n  .brand { font-weight:700; letter-spacing:.2px; font-size:1rem; color:var(--primary); }\n  .sub { color:var(--muted); font-size:.9rem; }\n  .grid-2 { display:grid; grid-template-columns:1fr 1fr; gap:1rem; }\n  .section { padding:1.25rem 1.5rem; }\n  h1 { font-size:1.4rem; margin:.25rem 0 .5rem; letter-spacing:.2px; }\n  h2 { font-size:1.1rem; margin:0 0 .75rem; color:var(--primary); }\n  p { margin:.25rem 0; line-height:1.55; }\n  .card { background:#fff; border:1px solid var(--border); border-radius:10px; padding:1rem; }\n  .muted { color:var(--muted); }\n  .kvs { display:grid; grid-template-columns:1fr 1fr; gap:.5rem 1rem; font-size:.95rem; }\n  .kvs div { display:flex; align-items:center; gap:.5rem; }\n  .pill { font-size:.8rem; padding:.15rem .5rem; border:1px solid var(--border); border-radius:999px; background:#f1f5f9; }\n  table { width:100%; border-collapse:collapse; }\n  th, td { border:1px solid var(--border); padding:.6rem .5rem; text-align:left; vertical-align:top; }\n  thead th { background:#f1f5f9; }\n  tfoot td { font-weight:600; }\n  .note { font-size:.92rem; background:#f8fafc; border:1px dashed var(--border); padding:.75rem; border-radius:8px; }\n  .cols-3 { columns:2; column-gap:1rem; }\n  .signature { height:80px; border:1px dashed var(--border); border-radius:10px; display:flex; align-items:center; justify-content:center; color:var(--muted); }\n  footer { padding:1rem 1.5rem; border-top:1px solid var(--border); color:var(--muted); font-size:.9rem; background:#fff; }\n</style>\n\n<body>\n<div class=\"page\">\n\n  {# ==== Raccourcis / sécurisation des accès ==== #}\n  {% set c = (quote.prospect is defined and quote.prospect.contact is defined) ? quote.prospect.contact : null %}\n  {% set a = (c and c.mainAddress is defined) ? c.mainAddress : null %}\n  {% set comp = (quote.prospect is defined and quote.prospect.company is defined) ? quote.prospect.company : null %}\n  {% set lines = quote.quoteLines|default([]) %}\n\n  {# Portable du commercial : on cherche dans un ordre sûr #}\n  {% set tel_portable = '' %}\n  {% if managedBy is defined %}\n    {% if managedBy.phoneNumber is defined and managedBy.phoneNumber %}{% set tel_portable = managedBy.phoneNumber %}\n    {% elseif managedBy.mobilePhone is defined and managedBy.mobilePhone %}{% set tel_portable = managedBy.mobilePhone %}\n    {% elseif managedBy.phone is defined and managedBy.phone %}{% set tel_portable = managedBy.phone %}\n    {% endif %}\n  {% endif %}\n\n  {# ==== Totaux/remise/TVA - robustes ==== #}\n  {% set total_ht_before_discount = 0 %}\n  {% for l in lines %}\n    {% set q = l.quantity|default(1) %}\n    {% set pu = l.unitPriceExclVat|default(0) %}\n    {% set total_ht_before_discount = total_ht_before_discount + (q * pu) %}\n  {% endfor %}\n  {% if total_ht_before_discount == 0 %}\n    {% set total_ht_before_discount = quote.totalExcludingVat|default(0) %}\n  {% endif %}\n  {% set total_ht = quote.totalExcludingVat|default(total_ht_before_discount) %}\n  {% set discount_value = total_ht_before_discount - total_ht %}\n  {% set discount_percent = total_ht_before_discount > 0 ? (discount_value / total_ht_before_discount * 100) : 0 %}\n  {% set vat_total = 0 %}\n  {% for l in lines %}\n    {% set vat_total = vat_total + (l.vatAmount|default(0)) %}\n  {% endfor %}\n\n  {# ==== Sélection ligne principale / formation / options (sans filtres avancés) ==== #}\n  {% set first = (lines[0] is defined) ? lines[0] : null %}\n  {% set mainLine = null %}\n  {% set formationLine = null %}\n  {% set options = [] %}\n  {% for l in lines %}\n    {% set ref = l.reference|default('')|lower %}\n    {% set isOpt = l.isOptional is defined and l.isOptional %}\n    {% if mainLine is null and not isOpt and ('formation' not in ref) %}\n      {% set mainLine = l %}\n    {% endif %}\n    {% if formationLine is null and ('formation' in ref) %}\n      {% set formationLine = l %}\n    {% endif %}\n    {% if isOpt %}\n      {% set options = options|merge([l]) %}\n    {% endif %}\n  {% endfor %}\n  {% if mainLine is null %}{% set mainLine = first %}{% endif %}\n\n  <!-- HEADER -->\n  <header>\n    <div style=\"flex:1\">\n      <div class=\"brand\">YANIGAV – Enfonce-pieux • Affûte-piquet • Fendeuse de bûche</div>\n      <div class=\"sub\">RCS ROANNE B 403 872 724 • SIRET 403 872 724 00014 • APE 4661Z • TVA FR114038727224</div>\n    </div>\n    <div class=\"pill\">{{ (quote.createdAt|default('now'))|date('d F Y') }}</div>\n  </header>\n\n  <!-- COORDONNÉES -->\n  <div class=\"section grid-2\">\n    <div class=\"card\">\n      <h2>Expéditeur</h2>\n      <p><strong>YANIGAV</strong></p>\n      <p>De la part de <strong>{{ managedBy is defined and managedBy.fullname is defined ? managedBy.fullname : (quote.managedByRealName|default('')) }}</strong> ({{ managedBy is defined and managedBy.role is defined and managedBy.role ? managedBy.role : 'Resp. Commercial' }})</p>\n      <div class=\"kvs\">\n        <div><span class=\"pill\">Tél</span> {{ managedBy is defined and managedBy.phone is defined and managedBy.phone ? managedBy.phone : '—' }}</div>\n        {% if tel_portable %}\n          <div><span class=\"pill\">Port</span> {{ tel_portable }}</div>\n        {% endif %}\n        <div><span class=\"pill\">Email</span>\n          {% if managedBy is defined and managedBy.email is defined and managedBy.email %}\n            <a href=\"mailto:{{ managedBy.email }}\">{{ managedBy.email }}</a>\n          {% else %}—{% endif %}\n        </div>\n      </div>\n    </div>\n    <div class=\"card\">\n      <h2>Destinataire</h2>\n      <p><strong>{{ quote.contactIdRealName|default(c and (c.fullname is defined and c.fullname ? c.fullname : (c.name|default('')))) }}</strong></p>\n      {% if comp and comp.name is defined and comp.name %}<p><strong>{{ comp.name }}</strong></p>{% endif %}\n      {% if a and (a.postalCode is defined or a.city is defined) %}<p class=\"muted\">{{ a.postalCode|default('') }} {{ a.city|default('') }}</p>{% endif %}\n    </div>\n  </div>\n\n  <!-- INTRO -->\n  <div class=\"section\">\n    <div class=\"card\">\n      <h1>Proposition commerciale</h1>\n      <p>{% if c and c.civility is defined and c.civility %}{{ c.civility }},{% else %}Madame, Monsieur,{% endif %}</p>\n      <p>Nous vous remercions de l’intérêt que vous portez à la marque YANIGAV et à ses produits. Suite à votre récent appel téléphonique, voici notre proposition pour un <strong>{{ quote.name|default('Enfonce-pieux HYDROCHOC HPG 790') }}</strong> correspondant à votre demande.</p>\n      {% if quote.priceListRef is defined and quote.priceListRef %}\n        <p class=\"muted\">{{ quote.priceListRef }}</p>\n      {% else %}\n        <p class=\"muted\">Tarif — {{ (quote.createdAt|default('now'))|date('Y') }}</p>\n      {% endif %}\n    </div>\n  </div>\n\n  <!-- OFFRE PRINCIPALE -->\n  <div class=\"section\">\n    <div class=\"card\">\n      <h2>Offre principale</h2>\n      <table>\n        <thead>\n          <tr>\n            <th>Désignation</th>\n            <th>Référence</th>\n            <th>Prix unitaire HT</th>\n          </tr>\n        </thead>\n        <tbody>\n          {% set pu = (mainLine and mainLine.unitPriceExclVat is defined) ? mainLine.unitPriceExclVat : (total_ht_before_discount > 0 ? total_ht_before_discount : 0) %}\n          <tr>\n            <td>{{ (mainLine and mainLine.name is defined and mainLine.name) ? mainLine.name : quote.name }}</td>\n            <td>{{ (mainLine and mainLine.reference is defined and mainLine.reference) ? mainLine.reference : '—' }}</td>\n            <td>{{ pu|number_format(0, ',', ' ') }} €</td>\n          </tr>\n        </tbody>\n      </table>\n      {% set note = 'Cinématique unique sur le marché — un véritable atout dans les terrains compliqués.' %}\n      <p class=\"note\" style=\"margin-top:.75rem\">{{ note }}</p>\n    </div>\n  </div>\n\n  {# ==== DESCRIPTION / ÉQUIPEMENT / FORMATION / OPTIONS ==== #}\n  {% set description = (mainLine and mainLine.description is defined and mainLine.description) ? mainLine.description : '' %}\n  {% set description = description|replace({'•':'\\n',';':'\\n'}) %}\n  {% set descList = description|split('\\n') %}\n\n  <div class=\"section grid-2\">\n    <div class=\"card\">\n      <h2>Points forts</h2>\n      {% set hasPoint = false %}\n      <ul class=\"cols-3\">\n        {% for item in descList %}\n          {% set t = item|trim %}\n          {% if t != '' %}\n            {% set hasPoint = true %}\n            <li>{{ t }}</li>\n          {% endif %}\n        {% endfor %}\n      </ul>\n      {% if not hasPoint %}\n        <p class=\"muted\">Aucun détail technique renseigné pour cet article.</p>\n      {% endif %}\n    </div>\n\n    <div class=\"card\">\n      <h2>Équipement de série</h2>\n      {% set printedEquip = false %}\n      {# 1) Liste explicite mainLine.features si fournie #}\n      {% if mainLine and mainLine.features is defined and mainLine.features %}\n        <ul>\n          {% for f in mainLine.features %}\n            <li>{{ f }}</li>\n            {% set printedEquip = true %}\n          {% endfor %}\n        </ul>\n      {% endif %}\n\n      {# 2) Sinon, tentative d’extraction depuis descList avec mots-clés #}\n      {% if not printedEquip %}\n        {% set equipList = [] %}\n        {% for item in descList %}\n          {% set t = item|trim %}\n          {% if t matches '/(équipement|equipement|de série|serie)/i' %}\n            {% set equipList = equipList|merge([t]) %}\n          {% endif %}\n        {% endfor %}\n        {% if equipList %}\n          <ul>\n            {% for f in equipList %}<li>{{ f }}</li>{% endfor %}\n          </ul>\n          {% set printedEquip = true %}\n        {% endif %}\n      {% endif %}\n\n      {% if not printedEquip %}\n        <p class=\"muted\">Aucun équipement de série spécifié.</p>\n      {% endif %}\n\n      {% if formationLine %}\n        <h2 style=\"margin-top:1rem\">Formation / Mise en route</h2>\n        <p><strong>{{ formationLine.name|default('Formation / Mise en route') }}</strong> – Prix net :\n          {{ (formationLine.totalExclVat|default(formationLine.unitPriceExclVat|default(0)))|number_format(0, ',', ' ') }} € HT</p>\n        {% if formationLine.description is defined and formationLine.description %}<p class=\"muted\">{{ formationLine.description }}</p>{% endif %}\n      {% endif %}\n\n      {% if options %}\n        <h2 style=\"margin-top:1rem\">Équipements recommandés</h2>\n        <ul>\n          {% for opt in options %}\n            {% set q = opt.quantity|default(1) %}\n            {% set puo = opt.unitPriceExclVat|default(0) %}\n            {% set rem = opt.discountPercent|default(0) %}\n            {% set opt_total = opt.totalExclVat|default(q * puo * (1 - (rem / 100))) %}\n            <li>{{ opt.name }} — {{ opt_total|number_format(0, ',', ' ') }} € HT</li>\n          {% endfor %}\n        </ul>\n      {% endif %}\n    </div>\n  </div>\n\n  <!-- CONDITIONS COMMERCIALES -->\n  <div class=\"section\">\n    <div class=\"card\">\n      <h2>Conditions commerciales</h2>\n      <ul>\n        {% if quote.expiredAt is defined and quote.expiredAt %}<li>Validité de l’offre : 1 mois (jusqu’au {{ quote.expiredAt|date('d/m/Y') }})</li>{% else %}<li>Validité de l’offre : 1 mois</li>{% endif %}\n        {% if discount_value > 0 %}<li>Remise de service : {{ discount_percent|round(0, 'floor') }} %</li>{% endif %}\n        {% if quote.orderContext is defined and quote.orderContext %}<li>{{ quote.orderContext }}</li>{% endif %}\n        <li>Règlement {{ quote.paymentMode|default('30 jours nets par LCR') }}</li>\n        <li>Délai : {{ quote.leadTime|default('2 à 3 mois après commande') }}</li>\n        {% if quote.shippingFeesHt is defined %}\n          {% if quote.shippingFeesHt == 0 %}<li>Port franco</li>\n          {% elseif quote.shippingFeesHt > 0 %}<li>Frais de port : {{ quote.shippingFeesHt|number_format(2, ',', ' ') }} € HT</li>\n          {% else %}<li>Port : {{ quote.shippingMode|default('selon conditions') }}</li>\n          {% endif %}\n        {% else %}\n          <li>Port : {{ quote.shippingMode|default('selon conditions') }}</li>\n        {% endif %}\n        {% if quote.customerRef is defined and quote.customerRef %}<li>Réf. client : {{ quote.customerRef }}</li>{% endif %}\n      </ul>\n    </div>\n  </div>\n\n  <!-- SIGNATURES -->\n  <div class=\"section grid-2\">\n    <div class=\"card\">\n      <h2>Signataires</h2>\n      <p>\n        <strong>{{ managedBy is defined and managedBy.fullname is defined ? managedBy.fullname : (quote.managedByRealName|default('')) }}</strong>\n        – {{ managedBy is defined and managedBy.role is defined and managedBy.role ? managedBy.role : 'Resp. Commercial' }}\n        {% if tel_portable %} – {{ tel_portable }}{% endif %}\n      </p>\n      <div class=\"signature\">Signature expéditeur</div>\n    </div>\n    <div class=\"card\">\n      <h2>Bon pour accord</h2>\n      <p><strong>{{ quote.contactIdRealName|default(c and (c.fullname is defined and c.fullname ? c.fullname : (c.name|default('')))) }}</strong>{% if comp and comp.name is defined and comp.name %} – {{ comp.name }}{% endif %}</p>\n      <div class=\"signature\">Cachet et signature</div>\n    </div>\n  </div>\n\n  <!-- PIED -->\n  <footer>\n    YANIGAV – Enfonce-pieux • Affûte-piquet • Fendeuse de bûche — RCS ROANNE B 403 872 724 — SIRET 403 872 724 00014 — APE 4661Z — TVA FR114038727224\n  </footer>\n</div>\n\n{# PAGE 2 : CGV (optionnelle) #}\n{% if cgv is defined or quote.cgvText is defined %}\n  <div style=\"page-break-before:always;\"></div>\n  <div class=\"page\">\n    <div class=\"section\">\n      <div class=\"card\">\n        <h2>Conditions Générales de Vente</h2>\n        <div class=\"note\" style=\"white-space:pre-wrap\">\n          {{ cgv|default(quote.cgvText)|raw }}\n        </div>\n      </div>\n    </div>\n    <footer>\n      Document généré automatiquement — valable sous réserve des conditions précisées ci-dessus.\n    </footer>\n  </div>\n{% endif %}\n</body>\n</html>\n"}"
  #languages: null
  #charsets: null
  #encodings: null
  #acceptableContentTypes: [
    "application/ld+json"
  ]
  #pathInfo: "/api/templates/f47ef469dac34bc29180feb40a25724c"
  #requestUri: "/api/templates/f47ef469dac34bc29180feb40a25724c"
  #baseUrl: ""
  #basePath: null
  #method: "PUT"
  #format: "jsonld"
  #session: Symfony\Component\HttpFoundation\Session\Session {#954 …}
  #locale: null
  #defaultLocale: "fr"
  -preferredFormat: null
  -isHostValid: true
  -isForwardedValid: true
  basePath: ""
}
"Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter"
ACCESS GRANTED
Show voter details
2 GRANTED IS_AUTHENTICATED_REMEMBERED
null
"Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter"
ACCESS GRANTED
Show voter details
3 DENIED tag_use
null
"Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter"
ACCESS ABSTAIN
"Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter"
ACCESS ABSTAIN
"Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter"
ACCESS ABSTAIN
"App\V4\Voters\ContactVoter"
ACCESS ABSTAIN
"App\V4\Voters\CustomActionVoter"
ACCESS ABSTAIN
"App\V4\Voters\CustomEventTriggerVoter"
ACCESS ABSTAIN
"App\V4\Voters\CustomerEventServiceVoter"
ACCESS ABSTAIN
"App\V4\Voters\DolibarrApiVoter"
ACCESS ABSTAIN
"App\V4\Voters\ListingVoter"
ACCESS ABSTAIN
"App\V4\Voters\MailTypeVoter"
ACCESS ABSTAIN
"App\V4\Voters\OutlookSubscriptionConfigurationVoter"
ACCESS ABSTAIN
"App\V4\Voters\ProspectVoter"
ACCESS ABSTAIN
"App\V4\Voters\QuoteVoter"
ACCESS ABSTAIN
"App\V4\Voters\SavedRequestVoter"
ACCESS ABSTAIN
"App\V4\Voters\SectionVoter"
ACCESS ABSTAIN
"App\V4\Voters\TabVoter"
ACCESS ABSTAIN
"App\V4\Voters\TagVoter"
ACCESS DENIED
"App\V4\Voters\TaskVoter"
ACCESS ABSTAIN
"App\V4\Voters\UnitMailVoter"
ACCESS ABSTAIN
"App\V4\Voters\UserInfoVoter"
ACCESS ABSTAIN
"App\Voters\AdvancedQuoteVoter"
ACCESS ABSTAIN
"App\Voters\CampaignVoter"
ACCESS ABSTAIN
"App\Voters\ContactVoter"
ACCESS ABSTAIN
"App\Voters\ModuleConfigurationVoter"
ACCESS ABSTAIN
"App\Voters\ModuleVoter"
ACCESS ABSTAIN
"App\Voters\ProductVoter"
ACCESS ABSTAIN
"App\Voters\ProspectVoter"
ACCESS ABSTAIN
"App\Voters\QuoteVoter"
ACCESS ABSTAIN
"App\Voters\TaskVoter"
ACCESS ABSTAIN
Show voter details
4 DENIED ROLE_MODULE_DOLIBARR_API
null
"Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter"
ACCESS ABSTAIN
"Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter"
ACCESS DENIED
"Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter"
ACCESS ABSTAIN
"App\V4\Voters\ContactVoter"
ACCESS ABSTAIN
"App\V4\Voters\CustomActionVoter"
ACCESS ABSTAIN
"App\V4\Voters\CustomEventTriggerVoter"
ACCESS ABSTAIN
"App\V4\Voters\CustomerEventServiceVoter"
ACCESS ABSTAIN
"App\V4\Voters\DolibarrApiVoter"
ACCESS ABSTAIN
"App\V4\Voters\ListingVoter"
ACCESS ABSTAIN
"App\V4\Voters\MailTypeVoter"
ACCESS ABSTAIN
"App\V4\Voters\OutlookSubscriptionConfigurationVoter"
ACCESS ABSTAIN
"App\V4\Voters\ProspectVoter"
ACCESS ABSTAIN
"App\V4\Voters\QuoteVoter"
ACCESS ABSTAIN
"App\V4\Voters\SavedRequestVoter"
ACCESS ABSTAIN
"App\V4\Voters\SectionVoter"
ACCESS ABSTAIN
"App\V4\Voters\TabVoter"
ACCESS ABSTAIN
"App\V4\Voters\TagVoter"
ACCESS ABSTAIN
"App\V4\Voters\TaskVoter"
ACCESS ABSTAIN
"App\V4\Voters\UnitMailVoter"
ACCESS ABSTAIN
"App\V4\Voters\UserInfoVoter"
ACCESS ABSTAIN
"App\Voters\AdvancedQuoteVoter"
ACCESS ABSTAIN
"App\Voters\CampaignVoter"
ACCESS ABSTAIN
"App\Voters\ContactVoter"
ACCESS ABSTAIN
"App\Voters\ModuleConfigurationVoter"
ACCESS ABSTAIN
"App\Voters\ModuleVoter"
ACCESS ABSTAIN
"App\Voters\ProductVoter"
ACCESS ABSTAIN
"App\Voters\ProspectVoter"
ACCESS ABSTAIN
"App\Voters\QuoteVoter"
ACCESS ABSTAIN
"App\Voters\TaskVoter"
ACCESS ABSTAIN
Show voter details