Commit 7696ea61 by Damien Moulard

WIP: reccurent payment, first draft for tests on preprod

parent b9d2a992
...@@ -428,4 +428,9 @@ form[name="formEncaissement"] label { ...@@ -428,4 +428,9 @@ form[name="formEncaissement"] label {
.text-error { .text-error {
color: #ff4136; color: #ff4136;
}
.tav-cotisation-payment-form {
display: none;
margin-top: 1rem;
} }
\ No newline at end of file
...@@ -806,4 +806,26 @@ $(function() { ...@@ -806,4 +806,26 @@ $(function() {
$('.prestataire-product-families-select').on('change', onPrestataireProductFamilyChange); $('.prestataire-product-families-select').on('change', onPrestataireProductFamilyChange);
}; };
$("#add-prestataire-products-family").on("click", addFormToCollection); $("#add-prestataire-products-family").on("click", addFormToCollection);
$("#tav-cotisation-payment-type").on("change", function() {
$(".tav-cotisation-payment-form").hide();
if (this.value === "instant-payment") {
$("#tav-cotisation-instant-payment-container").show();
} else if (this.value === "recurrent-payment") {
$("#tav-cotisation-recurrent-payment-container").show();
}
});
$("input:text[name='formAchatMonnaieAdherentRecurrent[don][montant]']").on('input', function() {
let montant = 0;
montant = parseFloat($('input#formAchatMonnaieAdherentRecurrent_montant').val());
let montantDon = parseFloat($("input:text[name='formAchatMonnaieAdherentRecurrent[don][montant]']").val().replace(",", "."));
if (isNaN(montantDon)) {
montantDon = 0;
}
var valuetotal = montant + montantDon;
$("span.achat_monnaie_premier_montant_total").text(valuetotal + ' €')
});
}); });
...@@ -61,6 +61,17 @@ class CaptureAction implements ActionInterface, GatewayAwareInterface, GenericTo ...@@ -61,6 +61,17 @@ class CaptureAction implements ActionInterface, GatewayAwareInterface, GenericTo
); );
$model['vads_url_check'] = $notifyToken->getTargetUrl(); $model['vads_url_check'] = $notifyToken->getTargetUrl();
} }
// TODO : here ?
$payment = $request->getFirstModel();
if ('paiement_recurrent_cotisation_tav' == $payment->getDescription()) { // TODO right way to check type
$model['vads_page_action'] = 'REGISTER_PAY_SUBSCRIBE';
$model['vads_sub_amount'] = "1000"; // TODO get params
$model['vads_sub_currency'] = $model['vads_currency'];
$model['vads_sub_effect_date'] = (new \DateTime('now', new \DateTimeZone('UTC')))->format('YmdHis');
$model['vads_sub_desc'] = 'RRULE:FREQ=DAILY;INTERVAL=1;COUNT=2';
// $model['vads_sub_desc'] = 'RRULE:FREQ=MONTHLY;COUNT=12;BYMONTHDAY=10';
}
} }
if (false == $model['vads_trans_id']) { if (false == $model['vads_trans_id']) {
......
...@@ -353,6 +353,10 @@ class Api ...@@ -353,6 +353,10 @@ class Api
'vads_url_return' => null, // Obligatoire si acquisition de la carte par commerçant 'vads_url_return' => null, // Obligatoire si acquisition de la carte par commerçant
'vads_user_info' => null, 'vads_user_info' => null,
'vads_version' => 'V2', 'vads_version' => 'V2',
'vads_sub_amount' => null,
'vads_sub_currency' => null,
'vads_sub_effect_date' => null,
'vads_sub_desc' => null,
]) ])
->setRequired([ ->setRequired([
'vads_amount', 'vads_amount',
...@@ -365,7 +369,7 @@ class Api ...@@ -365,7 +369,7 @@ class Api
->setAllowedValues('vads_action_mode', ['SILENT', 'INTERACTIVE']) ->setAllowedValues('vads_action_mode', ['SILENT', 'INTERACTIVE'])
->setAllowedValues('vads_currency', $this->getCurrencyCodes()) ->setAllowedValues('vads_currency', $this->getCurrencyCodes())
->setAllowedValues('vads_language', $this->getLanguageCodes()) ->setAllowedValues('vads_language', $this->getLanguageCodes())
->setAllowedValues('vads_page_action', 'PAYMENT') ->setAllowedValues('vads_page_action', ['PAYMENT', 'REGISTER_PAY_SUBSCRIBE'])
->setAllowedValues('vads_payment_cards', $this->getCardsCodes()) ->setAllowedValues('vads_payment_cards', $this->getCardsCodes())
->setAllowedValues('vads_payment_config', function ($value) { ->setAllowedValues('vads_payment_config', function ($value) {
if ($value === 'SINGLE') { if ($value === 'SINGLE') {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
"app": { "app": {
"js": [ "js": [
"/build/runtime.6ad5c9da.js", "/build/runtime.6ad5c9da.js",
"/build/app.27091a64.js" "/build/app.3644f7b2.js"
], ],
"css": [ "css": [
"/build/app.5cdc32e6.css" "/build/app.8a3f698b.css"
] ]
}, },
"admin": { "admin": {
......
{ {
"build/app.css": "/build/app.5cdc32e6.css", "build/app.css": "/build/app.8a3f698b.css",
"build/app.js": "/build/app.27091a64.js", "build/app.js": "/build/app.3644f7b2.js",
"build/admin.css": "/build/admin.4de55830.css", "build/admin.css": "/build/admin.4de55830.css",
"build/admin.js": "/build/admin.86a2d986.js", "build/admin.js": "/build/admin.86a2d986.js",
"build/runtime.js": "/build/runtime.6ad5c9da.js", "build/runtime.js": "/build/runtime.6ad5c9da.js",
......
(()=>{"use strict";var e={913:()=>{try{self["workbox:core:6.5.1"]&&_()}catch(e){}},977:()=>{try{self["workbox:precaching:6.5.1"]&&_()}catch(e){}},80:()=>{try{self["workbox:routing:6.5.1"]&&_()}catch(e){}},873:()=>{try{self["workbox:strategies:6.5.1"]&&_()}catch(e){}}},t={};function s(a){var n=t[a];if(void 0!==n)return n.exports;var r=t[a]={exports:{}};return e[a](r,r.exports,s),r.exports}(()=>{s(913);const e=(e,...t)=>{let s=e;return t.length>0&&(s+=` :: ${JSON.stringify(t)}`),s};class t extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}const a={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},n=e=>[a.prefix,e,a.suffix].filter((e=>e&&e.length>0)).join("-"),r=e=>e||n(a.precache),i=e=>e||n(a.runtime);function c(e,t){const s=t();return e.waitUntil(s),s}s(977);function o(e){if(!e)throw new t("add-to-cache-list-unexpected-type",{entry:e});if("string"==typeof e){const t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}const{revision:s,url:a}=e;if(!a)throw new t("add-to-cache-list-unexpected-type",{entry:e});if(!s){const e=new URL(a,location.href);return{cacheKey:e.href,url:e.href}}const n=new URL(a,location.href),r=new URL(a,location.href);return n.searchParams.set("__WB_REVISION__",s),{cacheKey:n.href,url:r.href}}class h{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:s})=>{if("install"===e.type&&t&&t.originalRequest&&t.originalRequest instanceof Request){const e=t.originalRequest.url;s?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return s}}}class l{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:e,params:t})=>{const s=(null==t?void 0:t.cacheKey)||this._precacheController.getCacheKeyForURL(e.url);return s?new Request(s,{headers:e.headers}):e},this._precacheController=e}}let u;async function f(e,s){let a=null;if(e.url){a=new URL(e.url).origin}if(a!==self.location.origin)throw new t("cross-origin-copy-response",{origin:a});const n=e.clone(),r={headers:new Headers(n.headers),status:n.status,statusText:n.statusText},i=s?s(r):r,c=function(){if(void 0===u){const e=new Response("");if("body"in e)try{new Response(e.body),u=!0}catch(e){u=!1}u=!1}return u}()?n.body:await n.blob();return new Response(c,i)}function d(e,t){const s=new URL(e);for(const e of t)s.searchParams.delete(e);return s.href}class p{constructor(){this.promise=new Promise(((e,t)=>{this.resolve=e,this.reject=t}))}}const g=new Set;s(873);function y(e){return"string"==typeof e?new Request(e):e}class w{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new p,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(const e of this._plugins)this._pluginStateMap.set(e,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){const{event:s}=this;let a=y(e);if("navigate"===a.mode&&s instanceof FetchEvent&&s.preloadResponse){const e=await s.preloadResponse;if(e)return e}const n=this.hasCallback("fetchDidFail")?a.clone():null;try{for(const e of this.iterateCallbacks("requestWillFetch"))a=await e({request:a.clone(),event:s})}catch(e){if(e instanceof Error)throw new t("plugin-error-request-will-fetch",{thrownErrorMessage:e.message})}const r=a.clone();try{let e;e=await fetch(a,"navigate"===a.mode?void 0:this._strategy.fetchOptions);for(const t of this.iterateCallbacks("fetchDidSucceed"))e=await t({event:s,request:r,response:e});return e}catch(e){throw n&&await this.runCallbacks("fetchDidFail",{error:e,event:s,originalRequest:n.clone(),request:r.clone()}),e}}async fetchAndCachePut(e){const t=await this.fetch(e),s=t.clone();return this.waitUntil(this.cachePut(e,s)),t}async cacheMatch(e){const t=y(e);let s;const{cacheName:a,matchOptions:n}=this._strategy,r=await this.getCacheKey(t,"read"),i=Object.assign(Object.assign({},n),{cacheName:a});s=await caches.match(r,i);for(const e of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await e({cacheName:a,matchOptions:n,cachedResponse:s,request:r,event:this.event})||void 0;return s}async cachePut(e,s){const a=y(e);var n;await(n=0,new Promise((e=>setTimeout(e,n))));const r=await this.getCacheKey(a,"write");if(!s)throw new t("cache-put-with-no-response",{url:(i=r.url,new URL(String(i),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var i;const c=await this._ensureResponseSafeToCache(s);if(!c)return!1;const{cacheName:o,matchOptions:h}=this._strategy,l=await self.caches.open(o),u=this.hasCallback("cacheDidUpdate"),f=u?await async function(e,t,s,a){const n=d(t.url,s);if(t.url===n)return e.match(t,a);const r=Object.assign(Object.assign({},a),{ignoreSearch:!0}),i=await e.keys(t,r);for(const t of i)if(n===d(t.url,s))return e.match(t,a)}(l,r.clone(),["__WB_REVISION__"],h):null;try{await l.put(r,u?c.clone():c)}catch(e){if(e instanceof Error)throw"QuotaExceededError"===e.name&&await async function(){for(const e of g)await e()}(),e}for(const e of this.iterateCallbacks("cacheDidUpdate"))await e({cacheName:o,oldResponse:f,newResponse:c.clone(),request:r,event:this.event});return!0}async getCacheKey(e,t){const s=`${e.url} | ${t}`;if(!this._cacheKeys[s]){let a=e;for(const e of this.iterateCallbacks("cacheKeyWillBeUsed"))a=y(await e({mode:t,request:a,event:this.event,params:this.params}));this._cacheKeys[s]=a}return this._cacheKeys[s]}hasCallback(e){for(const t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(const s of this.iterateCallbacks(e))await s(t)}*iterateCallbacks(e){for(const t of this._strategy.plugins)if("function"==typeof t[e]){const s=this._pluginStateMap.get(t),a=a=>{const n=Object.assign(Object.assign({},a),{state:s});return t[e](n)};yield a}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){let e;for(;e=this._extendLifetimePromises.shift();)await e}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,s=!1;for(const e of this.iterateCallbacks("cacheWillUpdate"))if(t=await e({request:this.request,response:t,event:this.event})||void 0,s=!0,!t)break;return s||t&&200!==t.status&&(t=void 0),t}}class m extends class{constructor(e={}){this.cacheName=i(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){const[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});const t=e.event,s="string"==typeof e.request?new Request(e.request):e.request,a="params"in e?e.params:void 0,n=new w(this,{event:t,request:s,params:a}),r=this._getResponse(n,s,t);return[r,this._awaitComplete(r,n,s,t)]}async _getResponse(e,s,a){let n;await e.runCallbacks("handlerWillStart",{event:a,request:s});try{if(n=await this._handle(s,e),!n||"error"===n.type)throw new t("no-response",{url:s.url})}catch(t){if(t instanceof Error)for(const r of e.iterateCallbacks("handlerDidError"))if(n=await r({error:t,event:a,request:s}),n)break;if(!n)throw t}for(const t of e.iterateCallbacks("handlerWillRespond"))n=await t({event:a,request:s,response:n});return n}async _awaitComplete(e,t,s,a){let n,r;try{n=await e}catch(r){}try{await t.runCallbacks("handlerDidRespond",{event:a,request:s,response:n}),await t.doneWaiting()}catch(e){e instanceof Error&&(r=e)}if(await t.runCallbacks("handlerDidComplete",{event:a,request:s,response:n,error:r}),t.destroy(),r)throw r}}{constructor(e={}){e.cacheName=r(e.cacheName),super(e),this._fallbackToNetwork=!1!==e.fallbackToNetwork,this.plugins.push(m.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){const s=await t.cacheMatch(e);return s||(t.event&&"install"===t.event.type?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,s){let a;const n=s.params||{};if(!this._fallbackToNetwork)throw new t("missing-precache-entry",{cacheName:this.cacheName,url:e.url});{0;const t=n.integrity,r=e.integrity,i=!r||r===t;if(a=await s.fetch(new Request(e,{integrity:r||t})),t&&i){this._useDefaultCacheabilityPluginIfNeeded();await s.cachePut(e,a.clone());0}}return a}async _handleInstall(e,s){this._useDefaultCacheabilityPluginIfNeeded();const a=await s.fetch(e);if(!await s.cachePut(e,a.clone()))throw new t("bad-precaching-response",{url:e.url,status:a.status});return a}_useDefaultCacheabilityPluginIfNeeded(){let e=null,t=0;for(const[s,a]of this.plugins.entries())a!==m.copyRedirectedCacheableResponsesPlugin&&(a===m.defaultPrecacheCacheabilityPlugin&&(e=s),a.cacheWillUpdate&&t++);0===t?this.plugins.push(m.defaultPrecacheCacheabilityPlugin):t>1&&null!==e&&this.plugins.splice(e,1)}}m.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:e})=>!e||e.status>=400?null:e},m.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:e})=>e.redirected?await f(e):e};class _{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:s=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new m({cacheName:r(e),plugins:[...t,new l({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this._installAndActiveListenersAdded=!0)}addToCacheList(e){const s=[];for(const a of e){"string"==typeof a?s.push(a):a&&void 0===a.revision&&s.push(a.url);const{cacheKey:e,url:n}=o(a),r="string"!=typeof a&&a.revision?"reload":"default";if(this._urlsToCacheKeys.has(n)&&this._urlsToCacheKeys.get(n)!==e)throw new t("add-to-cache-list-conflicting-entries",{firstEntry:this._urlsToCacheKeys.get(n),secondEntry:e});if("string"!=typeof a&&a.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==a.integrity)throw new t("add-to-cache-list-conflicting-integrities",{url:n});this._cacheKeysToIntegrities.set(e,a.integrity)}if(this._urlsToCacheKeys.set(n,e),this._urlsToCacheModes.set(n,r),s.length>0){const e=`Workbox is precaching URLs without revision info: ${s.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(e)}}}install(e){return c(e,(async()=>{const t=new h;this.strategy.plugins.push(t);for(const[t,s]of this._urlsToCacheKeys){const a=this._cacheKeysToIntegrities.get(s),n=this._urlsToCacheModes.get(t),r=new Request(t,{integrity:a,cache:n,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:r,event:e}))}const{updatedURLs:s,notUpdatedURLs:a}=t;return{updatedURLs:s,notUpdatedURLs:a}}))}activate(e){return c(e,(async()=>{const e=await self.caches.open(this.strategy.cacheName),t=await e.keys(),s=new Set(this._urlsToCacheKeys.values()),a=[];for(const n of t)s.has(n.url)||(await e.delete(n),a.push(n.url));return{deletedURLs:a}}))}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){const t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){const t=e instanceof Request?e.url:e,s=this.getCacheKeyForURL(t);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(e){const s=this.getCacheKeyForURL(e);if(!s)throw new t("non-precached-url",{url:e});return t=>(t.request=new Request(e),t.params=Object.assign({cacheKey:s},t.params),this.strategy.handle(t))}}let R;const v=()=>(R||(R=new _),R);s(80);const C=e=>e&&"object"==typeof e?e:{handle:e};class b{constructor(e,t,s="GET"){this.handler=C(t),this.match=e,this.method=s}setCatchHandler(e){this.catchHandler=C(e)}}class q extends b{constructor(e,t,s){super((({url:t})=>{const s=e.exec(t.href);if(s&&(t.origin===location.origin||0===s.index))return s.slice(1)}),t,s)}}class U{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",(e=>{const{request:t}=e,s=this.handleRequest({request:t,event:e});s&&e.respondWith(s)}))}addCacheListener(){self.addEventListener("message",(e=>{if(e.data&&"CACHE_URLS"===e.data.type){const{payload:t}=e.data;0;const s=Promise.all(t.urlsToCache.map((t=>{"string"==typeof t&&(t=[t]);const s=new Request(...t);return this.handleRequest({request:s,event:e})})));e.waitUntil(s),e.ports&&e.ports[0]&&s.then((()=>e.ports[0].postMessage(!0)))}}))}handleRequest({request:e,event:t}){const s=new URL(e.url,location.href);if(!s.protocol.startsWith("http"))return void 0;const a=s.origin===location.origin,{params:n,route:r}=this.findMatchingRoute({event:t,request:e,sameOrigin:a,url:s});let i=r&&r.handler;const c=e.method;if(!i&&this._defaultHandlerMap.has(c)&&(i=this._defaultHandlerMap.get(c)),!i)return void 0;let o;try{o=i.handle({url:s,request:e,event:t,params:n})}catch(e){o=Promise.reject(e)}const h=r&&r.catchHandler;return o instanceof Promise&&(this._catchHandler||h)&&(o=o.catch((async a=>{if(h){0;try{return await h.handle({url:s,request:e,event:t,params:n})}catch(e){e instanceof Error&&(a=e)}}if(this._catchHandler)return this._catchHandler.handle({url:s,request:e,event:t});throw a}))),o}findMatchingRoute({url:e,sameOrigin:t,request:s,event:a}){const n=this._routes.get(s.method)||[];for(const r of n){let n;const i=r.match({url:e,sameOrigin:t,request:s,event:a});if(i)return n=i,(Array.isArray(n)&&0===n.length||i.constructor===Object&&0===Object.keys(i).length||"boolean"==typeof i)&&(n=void 0),{route:r,params:n}}return{}}setDefaultHandler(e,t="GET"){this._defaultHandlerMap.set(t,C(e))}setCatchHandler(e){this._catchHandler=C(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new t("unregister-route-but-not-found-with-method",{method:e.method});const s=this._routes.get(e.method).indexOf(e);if(!(s>-1))throw new t("unregister-route-route-not-registered");this._routes.get(e.method).splice(s,1)}}let L;class k extends b{constructor(e,t){super((({request:s})=>{const a=e.getURLsToCacheKeys();for(const n of function*(e,{ignoreURLParametersMatching:t=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:a=!0,urlManipulation:n}={}){const r=new URL(e,location.href);r.hash="",yield r.href;const i=function(e,t=[]){for(const s of[...e.searchParams.keys()])t.some((e=>e.test(s)))&&e.searchParams.delete(s);return e}(r,t);if(yield i.href,s&&i.pathname.endsWith("/")){const e=new URL(i.href);e.pathname+=s,yield e.href}if(a){const e=new URL(i.href);e.pathname+=".html",yield e.href}if(n){const e=n({url:r});for(const t of e)yield t.href}}(s.url,t)){const t=a.get(n);if(t){return{cacheKey:t,integrity:e.getIntegrityForCacheKey(t)}}}}),e.strategy)}}function K(e){const s=v();!function(e,s,a){let n;if("string"==typeof e){const t=new URL(e,location.href);n=new b((({url:e})=>e.href===t.href),s,a)}else if(e instanceof RegExp)n=new q(e,s,a);else if("function"==typeof e)n=new b(e,s,a);else{if(!(e instanceof b))throw new t("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});n=e}(L||(L=new U,L.addFetchListener(),L.addCacheListener()),L).registerRoute(n)}(new k(s,e))}var T;(function(e){v().precache(e)})([{'revision':null,'url':'/build/admin.4de55830.css'},{'revision':null,'url':'/build/admin.86a2d986.js'},{'revision':'ad79405d542b397996a3079203114b42','url':'/build/admin.86a2d986.js.LICENSE.txt'},{'revision':null,'url':'/build/app.27091a64.js'},{'revision':'4ff7361e3c3e359ae88c5fae5738746d','url':'/build/app.27091a64.js.LICENSE.txt'},{'revision':null,'url':'/build/app.5cdc32e6.css'},{'revision':null,'url':'/build/fonts/fa-brands-400.3dc44d22.woff2'},{'revision':null,'url':'/build/fonts/fa-regular-400.3dc6ca01.woff2'},{'revision':null,'url':'/build/fonts/fa-solid-900.496d5fc1.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-300.d2c7d5c5.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-600.17c0392c.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-600italic.cc34c6e7.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-700.ed37bc60.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-900.476756cd.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-italic.a07cb9c5.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-regular.f74389bd.woff2'},{'revision':null,'url':'/build/images/fa-brands-400.05d20183.svg'},{'revision':null,'url':'/build/images/fa-regular-400.9a0810d6.svg'},{'revision':null,'url':'/build/images/fa-solid-900.a838c42a.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-300.4e7fe004.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-600.cf2758ae.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-600italic.7249d863.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-700.3e4b9e19.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-900.060d8c51.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-italic.08dc9b1c.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-regular.3bb9538c.svg'},{'revision':null,'url':'/build/runtime.6ad5c9da.js'}]),K(T),self.addEventListener("fetch",(function(e){e.respondWith(caches.match(e.request).then((function(t){return t||fetch(e.request)})).catch((function(){return caches.match("/offline.html")})))}))})()})(); (()=>{"use strict";var e={913:()=>{try{self["workbox:core:6.5.1"]&&_()}catch(e){}},977:()=>{try{self["workbox:precaching:6.5.1"]&&_()}catch(e){}},80:()=>{try{self["workbox:routing:6.5.1"]&&_()}catch(e){}},873:()=>{try{self["workbox:strategies:6.5.1"]&&_()}catch(e){}}},t={};function s(a){var n=t[a];if(void 0!==n)return n.exports;var r=t[a]={exports:{}};return e[a](r,r.exports,s),r.exports}(()=>{s(913);const e=(e,...t)=>{let s=e;return t.length>0&&(s+=` :: ${JSON.stringify(t)}`),s};class t extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}const a={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},n=e=>[a.prefix,e,a.suffix].filter((e=>e&&e.length>0)).join("-"),r=e=>e||n(a.precache),i=e=>e||n(a.runtime);function c(e,t){const s=t();return e.waitUntil(s),s}s(977);function o(e){if(!e)throw new t("add-to-cache-list-unexpected-type",{entry:e});if("string"==typeof e){const t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}const{revision:s,url:a}=e;if(!a)throw new t("add-to-cache-list-unexpected-type",{entry:e});if(!s){const e=new URL(a,location.href);return{cacheKey:e.href,url:e.href}}const n=new URL(a,location.href),r=new URL(a,location.href);return n.searchParams.set("__WB_REVISION__",s),{cacheKey:n.href,url:r.href}}class h{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:s})=>{if("install"===e.type&&t&&t.originalRequest&&t.originalRequest instanceof Request){const e=t.originalRequest.url;s?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return s}}}class l{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:e,params:t})=>{const s=(null==t?void 0:t.cacheKey)||this._precacheController.getCacheKeyForURL(e.url);return s?new Request(s,{headers:e.headers}):e},this._precacheController=e}}let u;async function f(e,s){let a=null;if(e.url){a=new URL(e.url).origin}if(a!==self.location.origin)throw new t("cross-origin-copy-response",{origin:a});const n=e.clone(),r={headers:new Headers(n.headers),status:n.status,statusText:n.statusText},i=s?s(r):r,c=function(){if(void 0===u){const e=new Response("");if("body"in e)try{new Response(e.body),u=!0}catch(e){u=!1}u=!1}return u}()?n.body:await n.blob();return new Response(c,i)}function d(e,t){const s=new URL(e);for(const e of t)s.searchParams.delete(e);return s.href}class p{constructor(){this.promise=new Promise(((e,t)=>{this.resolve=e,this.reject=t}))}}const g=new Set;s(873);function y(e){return"string"==typeof e?new Request(e):e}class w{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new p,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(const e of this._plugins)this._pluginStateMap.set(e,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){const{event:s}=this;let a=y(e);if("navigate"===a.mode&&s instanceof FetchEvent&&s.preloadResponse){const e=await s.preloadResponse;if(e)return e}const n=this.hasCallback("fetchDidFail")?a.clone():null;try{for(const e of this.iterateCallbacks("requestWillFetch"))a=await e({request:a.clone(),event:s})}catch(e){if(e instanceof Error)throw new t("plugin-error-request-will-fetch",{thrownErrorMessage:e.message})}const r=a.clone();try{let e;e=await fetch(a,"navigate"===a.mode?void 0:this._strategy.fetchOptions);for(const t of this.iterateCallbacks("fetchDidSucceed"))e=await t({event:s,request:r,response:e});return e}catch(e){throw n&&await this.runCallbacks("fetchDidFail",{error:e,event:s,originalRequest:n.clone(),request:r.clone()}),e}}async fetchAndCachePut(e){const t=await this.fetch(e),s=t.clone();return this.waitUntil(this.cachePut(e,s)),t}async cacheMatch(e){const t=y(e);let s;const{cacheName:a,matchOptions:n}=this._strategy,r=await this.getCacheKey(t,"read"),i=Object.assign(Object.assign({},n),{cacheName:a});s=await caches.match(r,i);for(const e of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await e({cacheName:a,matchOptions:n,cachedResponse:s,request:r,event:this.event})||void 0;return s}async cachePut(e,s){const a=y(e);var n;await(n=0,new Promise((e=>setTimeout(e,n))));const r=await this.getCacheKey(a,"write");if(!s)throw new t("cache-put-with-no-response",{url:(i=r.url,new URL(String(i),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var i;const c=await this._ensureResponseSafeToCache(s);if(!c)return!1;const{cacheName:o,matchOptions:h}=this._strategy,l=await self.caches.open(o),u=this.hasCallback("cacheDidUpdate"),f=u?await async function(e,t,s,a){const n=d(t.url,s);if(t.url===n)return e.match(t,a);const r=Object.assign(Object.assign({},a),{ignoreSearch:!0}),i=await e.keys(t,r);for(const t of i)if(n===d(t.url,s))return e.match(t,a)}(l,r.clone(),["__WB_REVISION__"],h):null;try{await l.put(r,u?c.clone():c)}catch(e){if(e instanceof Error)throw"QuotaExceededError"===e.name&&await async function(){for(const e of g)await e()}(),e}for(const e of this.iterateCallbacks("cacheDidUpdate"))await e({cacheName:o,oldResponse:f,newResponse:c.clone(),request:r,event:this.event});return!0}async getCacheKey(e,t){const s=`${e.url} | ${t}`;if(!this._cacheKeys[s]){let a=e;for(const e of this.iterateCallbacks("cacheKeyWillBeUsed"))a=y(await e({mode:t,request:a,event:this.event,params:this.params}));this._cacheKeys[s]=a}return this._cacheKeys[s]}hasCallback(e){for(const t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(const s of this.iterateCallbacks(e))await s(t)}*iterateCallbacks(e){for(const t of this._strategy.plugins)if("function"==typeof t[e]){const s=this._pluginStateMap.get(t),a=a=>{const n=Object.assign(Object.assign({},a),{state:s});return t[e](n)};yield a}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){let e;for(;e=this._extendLifetimePromises.shift();)await e}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,s=!1;for(const e of this.iterateCallbacks("cacheWillUpdate"))if(t=await e({request:this.request,response:t,event:this.event})||void 0,s=!0,!t)break;return s||t&&200!==t.status&&(t=void 0),t}}class m extends class{constructor(e={}){this.cacheName=i(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){const[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});const t=e.event,s="string"==typeof e.request?new Request(e.request):e.request,a="params"in e?e.params:void 0,n=new w(this,{event:t,request:s,params:a}),r=this._getResponse(n,s,t);return[r,this._awaitComplete(r,n,s,t)]}async _getResponse(e,s,a){let n;await e.runCallbacks("handlerWillStart",{event:a,request:s});try{if(n=await this._handle(s,e),!n||"error"===n.type)throw new t("no-response",{url:s.url})}catch(t){if(t instanceof Error)for(const r of e.iterateCallbacks("handlerDidError"))if(n=await r({error:t,event:a,request:s}),n)break;if(!n)throw t}for(const t of e.iterateCallbacks("handlerWillRespond"))n=await t({event:a,request:s,response:n});return n}async _awaitComplete(e,t,s,a){let n,r;try{n=await e}catch(r){}try{await t.runCallbacks("handlerDidRespond",{event:a,request:s,response:n}),await t.doneWaiting()}catch(e){e instanceof Error&&(r=e)}if(await t.runCallbacks("handlerDidComplete",{event:a,request:s,response:n,error:r}),t.destroy(),r)throw r}}{constructor(e={}){e.cacheName=r(e.cacheName),super(e),this._fallbackToNetwork=!1!==e.fallbackToNetwork,this.plugins.push(m.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){const s=await t.cacheMatch(e);return s||(t.event&&"install"===t.event.type?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,s){let a;const n=s.params||{};if(!this._fallbackToNetwork)throw new t("missing-precache-entry",{cacheName:this.cacheName,url:e.url});{0;const t=n.integrity,r=e.integrity,i=!r||r===t;if(a=await s.fetch(new Request(e,{integrity:r||t})),t&&i){this._useDefaultCacheabilityPluginIfNeeded();await s.cachePut(e,a.clone());0}}return a}async _handleInstall(e,s){this._useDefaultCacheabilityPluginIfNeeded();const a=await s.fetch(e);if(!await s.cachePut(e,a.clone()))throw new t("bad-precaching-response",{url:e.url,status:a.status});return a}_useDefaultCacheabilityPluginIfNeeded(){let e=null,t=0;for(const[s,a]of this.plugins.entries())a!==m.copyRedirectedCacheableResponsesPlugin&&(a===m.defaultPrecacheCacheabilityPlugin&&(e=s),a.cacheWillUpdate&&t++);0===t?this.plugins.push(m.defaultPrecacheCacheabilityPlugin):t>1&&null!==e&&this.plugins.splice(e,1)}}m.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:e})=>!e||e.status>=400?null:e},m.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:e})=>e.redirected?await f(e):e};class _{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:s=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new m({cacheName:r(e),plugins:[...t,new l({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this._installAndActiveListenersAdded=!0)}addToCacheList(e){const s=[];for(const a of e){"string"==typeof a?s.push(a):a&&void 0===a.revision&&s.push(a.url);const{cacheKey:e,url:n}=o(a),r="string"!=typeof a&&a.revision?"reload":"default";if(this._urlsToCacheKeys.has(n)&&this._urlsToCacheKeys.get(n)!==e)throw new t("add-to-cache-list-conflicting-entries",{firstEntry:this._urlsToCacheKeys.get(n),secondEntry:e});if("string"!=typeof a&&a.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==a.integrity)throw new t("add-to-cache-list-conflicting-integrities",{url:n});this._cacheKeysToIntegrities.set(e,a.integrity)}if(this._urlsToCacheKeys.set(n,e),this._urlsToCacheModes.set(n,r),s.length>0){const e=`Workbox is precaching URLs without revision info: ${s.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(e)}}}install(e){return c(e,(async()=>{const t=new h;this.strategy.plugins.push(t);for(const[t,s]of this._urlsToCacheKeys){const a=this._cacheKeysToIntegrities.get(s),n=this._urlsToCacheModes.get(t),r=new Request(t,{integrity:a,cache:n,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:r,event:e}))}const{updatedURLs:s,notUpdatedURLs:a}=t;return{updatedURLs:s,notUpdatedURLs:a}}))}activate(e){return c(e,(async()=>{const e=await self.caches.open(this.strategy.cacheName),t=await e.keys(),s=new Set(this._urlsToCacheKeys.values()),a=[];for(const n of t)s.has(n.url)||(await e.delete(n),a.push(n.url));return{deletedURLs:a}}))}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){const t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){const t=e instanceof Request?e.url:e,s=this.getCacheKeyForURL(t);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(e){const s=this.getCacheKeyForURL(e);if(!s)throw new t("non-precached-url",{url:e});return t=>(t.request=new Request(e),t.params=Object.assign({cacheKey:s},t.params),this.strategy.handle(t))}}let R;const v=()=>(R||(R=new _),R);s(80);const C=e=>e&&"object"==typeof e?e:{handle:e};class b{constructor(e,t,s="GET"){this.handler=C(t),this.match=e,this.method=s}setCatchHandler(e){this.catchHandler=C(e)}}class q extends b{constructor(e,t,s){super((({url:t})=>{const s=e.exec(t.href);if(s&&(t.origin===location.origin||0===s.index))return s.slice(1)}),t,s)}}class U{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",(e=>{const{request:t}=e,s=this.handleRequest({request:t,event:e});s&&e.respondWith(s)}))}addCacheListener(){self.addEventListener("message",(e=>{if(e.data&&"CACHE_URLS"===e.data.type){const{payload:t}=e.data;0;const s=Promise.all(t.urlsToCache.map((t=>{"string"==typeof t&&(t=[t]);const s=new Request(...t);return this.handleRequest({request:s,event:e})})));e.waitUntil(s),e.ports&&e.ports[0]&&s.then((()=>e.ports[0].postMessage(!0)))}}))}handleRequest({request:e,event:t}){const s=new URL(e.url,location.href);if(!s.protocol.startsWith("http"))return void 0;const a=s.origin===location.origin,{params:n,route:r}=this.findMatchingRoute({event:t,request:e,sameOrigin:a,url:s});let i=r&&r.handler;const c=e.method;if(!i&&this._defaultHandlerMap.has(c)&&(i=this._defaultHandlerMap.get(c)),!i)return void 0;let o;try{o=i.handle({url:s,request:e,event:t,params:n})}catch(e){o=Promise.reject(e)}const h=r&&r.catchHandler;return o instanceof Promise&&(this._catchHandler||h)&&(o=o.catch((async a=>{if(h){0;try{return await h.handle({url:s,request:e,event:t,params:n})}catch(e){e instanceof Error&&(a=e)}}if(this._catchHandler)return this._catchHandler.handle({url:s,request:e,event:t});throw a}))),o}findMatchingRoute({url:e,sameOrigin:t,request:s,event:a}){const n=this._routes.get(s.method)||[];for(const r of n){let n;const i=r.match({url:e,sameOrigin:t,request:s,event:a});if(i)return n=i,(Array.isArray(n)&&0===n.length||i.constructor===Object&&0===Object.keys(i).length||"boolean"==typeof i)&&(n=void 0),{route:r,params:n}}return{}}setDefaultHandler(e,t="GET"){this._defaultHandlerMap.set(t,C(e))}setCatchHandler(e){this._catchHandler=C(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new t("unregister-route-but-not-found-with-method",{method:e.method});const s=this._routes.get(e.method).indexOf(e);if(!(s>-1))throw new t("unregister-route-route-not-registered");this._routes.get(e.method).splice(s,1)}}let L;class k extends b{constructor(e,t){super((({request:s})=>{const a=e.getURLsToCacheKeys();for(const n of function*(e,{ignoreURLParametersMatching:t=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:a=!0,urlManipulation:n}={}){const r=new URL(e,location.href);r.hash="",yield r.href;const i=function(e,t=[]){for(const s of[...e.searchParams.keys()])t.some((e=>e.test(s)))&&e.searchParams.delete(s);return e}(r,t);if(yield i.href,s&&i.pathname.endsWith("/")){const e=new URL(i.href);e.pathname+=s,yield e.href}if(a){const e=new URL(i.href);e.pathname+=".html",yield e.href}if(n){const e=n({url:r});for(const t of e)yield t.href}}(s.url,t)){const t=a.get(n);if(t){return{cacheKey:t,integrity:e.getIntegrityForCacheKey(t)}}}}),e.strategy)}}function K(e){const s=v();!function(e,s,a){let n;if("string"==typeof e){const t=new URL(e,location.href);n=new b((({url:e})=>e.href===t.href),s,a)}else if(e instanceof RegExp)n=new q(e,s,a);else if("function"==typeof e)n=new b(e,s,a);else{if(!(e instanceof b))throw new t("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});n=e}(L||(L=new U,L.addFetchListener(),L.addCacheListener()),L).registerRoute(n)}(new k(s,e))}var T;(function(e){v().precache(e)})([{'revision':null,'url':'/build/admin.4de55830.css'},{'revision':null,'url':'/build/admin.86a2d986.js'},{'revision':'ad79405d542b397996a3079203114b42','url':'/build/admin.86a2d986.js.LICENSE.txt'},{'revision':null,'url':'/build/app.3644f7b2.js'},{'revision':'4ff7361e3c3e359ae88c5fae5738746d','url':'/build/app.3644f7b2.js.LICENSE.txt'},{'revision':null,'url':'/build/app.8a3f698b.css'},{'revision':null,'url':'/build/fonts/fa-brands-400.3dc44d22.woff2'},{'revision':null,'url':'/build/fonts/fa-regular-400.3dc6ca01.woff2'},{'revision':null,'url':'/build/fonts/fa-solid-900.496d5fc1.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-300.d2c7d5c5.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-600.17c0392c.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-600italic.cc34c6e7.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-700.ed37bc60.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-900.476756cd.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-italic.a07cb9c5.woff2'},{'revision':null,'url':'/build/fonts/source-sans-pro-v14-latin-regular.f74389bd.woff2'},{'revision':null,'url':'/build/images/fa-brands-400.05d20183.svg'},{'revision':null,'url':'/build/images/fa-regular-400.9a0810d6.svg'},{'revision':null,'url':'/build/images/fa-solid-900.a838c42a.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-300.4e7fe004.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-600.cf2758ae.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-600italic.7249d863.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-700.3e4b9e19.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-900.060d8c51.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-italic.08dc9b1c.svg'},{'revision':null,'url':'/build/images/source-sans-pro-v14-latin-regular.3bb9538c.svg'},{'revision':null,'url':'/build/runtime.6ad5c9da.js'}]),K(T),self.addEventListener("fetch",(function(e){e.respondWith(caches.match(e.request).then((function(t){return t||fetch(e.request)})).catch((function(){return caches.match("/offline.html")})))}))})()})();
\ No newline at end of file \ No newline at end of file
...@@ -190,7 +190,7 @@ class PaymentController extends AbstractController ...@@ -190,7 +190,7 @@ class PaymentController extends AbstractController
$this->authenticator, $this->authenticator,
'main' 'main'
); );
} else if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type) { } else if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type || Payment::TYPE_PAIEMENT_RECURRENT_COTISATION_TAV) {
$this->addFlash( $this->addFlash(
'success', 'success',
$this->translator->trans('Cotisation payée !') $this->translator->trans('Cotisation payée !')
......
...@@ -11,6 +11,7 @@ use App\Entity\TransactionAdherentAdherent; ...@@ -11,6 +11,7 @@ use App\Entity\TransactionAdherentAdherent;
use App\Entity\TransactionAdherentPrestataire; use App\Entity\TransactionAdherentPrestataire;
use App\Form\Type\AchatMonnaieAConfirmerAdherentFormType; use App\Form\Type\AchatMonnaieAConfirmerAdherentFormType;
use App\Form\Type\AchatMonnaieAdherentFormType; use App\Form\Type\AchatMonnaieAdherentFormType;
use App\Form\Type\AchatMonnaieAdherentRecurrentFormType;
use App\Form\Type\AdherentInfosFormType; use App\Form\Type\AdherentInfosFormType;
use App\Form\Type\TransactionAdherentAdherentFormType; use App\Form\Type\TransactionAdherentAdherentFormType;
use App\Form\Type\TransactionAdherentPrestataireFormType; use App\Form\Type\TransactionAdherentPrestataireFormType;
...@@ -122,6 +123,37 @@ class UserAdherentController extends FluxController ...@@ -122,6 +123,37 @@ class UserAdherentController extends FluxController
} }
/** /**
* Validations before proceeding to payment.
*
* Returns error message or null if no error.
*/
private function paiementCotisTavValidation($flux) {
// Look for existing cotisation
if ($this->tavCotisationsUtils->checkExistingCotisation($flux)) {
// return "Cotisation déjà payée ce mois-ci.";
}
$destinataire = $flux->getDestinataire();
// Look for cotisation data depending on active process
if (true == $this->getParameter('household_based_allowance')) {
$cotisationAmount = $destinataire->getCotisationAmount();
if (is_null($cotisationAmount) || is_null($destinataire->getHouseholdAdultCount())) {
return "Opération impossible : votre profil est incomplet, informations de cotisation manquantes. Veuillez contacter un administrateur.";
}
} else {
$profile = $destinataire->getProfilDeCotisation();
if (is_null($profile)) {
return "Opération impossible : vous n'avez pas de profil de cotisation associé. Veuillez contacter un administrateur.";
}
}
return null;
}
/**
* @Route("/adherent/paiement-cotis-tav/", name="paiementCotisTav") * @Route("/adherent/paiement-cotis-tav/", name="paiementCotisTav")
* @IsGranted("ROLE_ADHERENT") * @IsGranted("ROLE_ADHERENT")
*/ */
...@@ -138,23 +170,11 @@ class UserAdherentController extends FluxController ...@@ -138,23 +170,11 @@ class UserAdherentController extends FluxController
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$flux = $form->getData(); $flux = $form->getData();
// Look for existing cotisation $validationError = $this->paiementCotisTavValidation($flux);
if ($this->tavCotisationsUtils->checkExistingCotisation($flux)) { if (!is_null($validationError)) {
$this->addFlash( $this->addFlash(
'error', 'error',
$this->translator->trans('Cotisation déjà payée ce mois-ci.') $this->translator->trans($validationError)
);
return $this->redirectToRoute('index');
}
$destinataire = $flux->getDestinataire();
$profile = $destinataire->getProfilDeCotisation();
if (is_null($profile)) {
$this->addFlash(
'error',
$this->translator->trans('Opération impossible : vous n\'avez pas de profil de cotisation associé. Veuillez contacter un administrateur.')
); );
return $this->redirectToRoute('index'); return $this->redirectToRoute('index');
...@@ -193,6 +213,50 @@ class UserAdherentController extends FluxController ...@@ -193,6 +213,50 @@ class UserAdherentController extends FluxController
} }
/** /**
* @Route("/adherent/paiement-reccurent-cotis-tav/", name="paiementRecurrentCotisTav")
* @IsGranted("ROLE_ADHERENT")
*/
public function paiementRecurrentCotisTavAction(Request $request)
{
if (empty($this->getUser()) || empty($this->getUser()->getAdherent())) {
return $this->redirectToRoute('index');
}
$entity = new AchatMonnaieAdherent();
$form = $this->createForm(AchatMonnaieAdherentRecurrentFormType::class, $entity);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$flux = $form->getData();
$validationError = $this->paiementCotisTavValidation($flux);
if (!is_null($validationError)) {
$this->addFlash(
'error',
$this->translator->trans($validationError)
);
return $this->redirectToRoute('index');
}
if (null == $flux->getDon() || 0 == $flux->getDon()->getMontant()) {
$flux->setDon(null);
}
// Redirect to payment
return $this->forward('App\Controller\PaymentController::preparePaymentAction', [
'form' => $form,
'type' => Payment::TYPE_PAIEMENT_RECURRENT_COTISATION_TAV
]);
}
return $this->render('@kohinos/flux/transaction.html.twig', [
'form' => $form->createView(),
'title' => $this->translator->trans('Payer sa cotisation'),
]);
}
/**
* @Route("/adherent/demande/achat-monnaie/", name="achatMonnaieAConfirmerAdherent") * @Route("/adherent/demande/achat-monnaie/", name="achatMonnaieAConfirmerAdherent")
* @IsGranted("ROLE_ADHERENT") * @IsGranted("ROLE_ADHERENT")
*/ */
......
...@@ -18,6 +18,9 @@ class Payment extends BasePayment ...@@ -18,6 +18,9 @@ class Payment extends BasePayment
const TYPE_COTISATION_PRESTA = 'cotisation_presta'; const TYPE_COTISATION_PRESTA = 'cotisation_presta';
const TYPE_ADHESION = 'adhesion'; const TYPE_ADHESION = 'adhesion';
const TYPE_PAIEMENT_COTISATION_TAV = 'paiement_cotisation_tav'; const TYPE_PAIEMENT_COTISATION_TAV = 'paiement_cotisation_tav';
const TYPE_PAIEMENT_RECURRENT_COTISATION_TAV = 'paiement_recurrent_cotisation_tav';
// todo : new field pour donnes d'abonnement
/** /**
* @var \Ramsey\Uuid\UuidInterface * @var \Ramsey\Uuid\UuidInterface
......
...@@ -14,6 +14,7 @@ use Doctrine\ORM\EntityManagerInterface; ...@@ -14,6 +14,7 @@ use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Model\UserManagerInterface; use FOS\UserBundle\Model\UserManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use App\Events\MLCEvents; use App\Events\MLCEvents;
use App\Events\FluxEvent; use App\Events\FluxEvent;
use App\Entity\Flux; use App\Entity\Flux;
...@@ -42,6 +43,7 @@ class PaymentStatusExtension implements ExtensionInterface ...@@ -42,6 +43,7 @@ class PaymentStatusExtension implements ExtensionInterface
private $userManager; private $userManager;
private $operationUtils; private $operationUtils;
private $tavCotisationsUtils; private $tavCotisationsUtils;
private $container;
/** /**
* PaymentStatusExtension constructor. * PaymentStatusExtension constructor.
...@@ -54,7 +56,8 @@ class PaymentStatusExtension implements ExtensionInterface ...@@ -54,7 +56,8 @@ class PaymentStatusExtension implements ExtensionInterface
SerializerInterface $serializer, SerializerInterface $serializer,
UserManagerInterface $userManager, UserManagerInterface $userManager,
OperationUtils $operationUtils, OperationUtils $operationUtils,
TAVCotisationUtils $tavCotisationsUtils TAVCotisationUtils $tavCotisationsUtils,
ContainerInterface $container
) { ) {
$this->em = $em; $this->em = $em;
$this->eventDispatcher = $eventDispatcher; $this->eventDispatcher = $eventDispatcher;
...@@ -62,6 +65,7 @@ class PaymentStatusExtension implements ExtensionInterface ...@@ -62,6 +65,7 @@ class PaymentStatusExtension implements ExtensionInterface
$this->userManager = $userManager; $this->userManager = $userManager;
$this->operationUtils = $operationUtils; $this->operationUtils = $operationUtils;
$this->tavCotisationsUtils = $tavCotisationsUtils; $this->tavCotisationsUtils = $tavCotisationsUtils;
$this->container = $container;
} }
/** /**
...@@ -253,7 +257,8 @@ class PaymentStatusExtension implements ExtensionInterface ...@@ -253,7 +257,8 @@ class PaymentStatusExtension implements ExtensionInterface
$payment->setClientId($user->getId()); $payment->setClientId($user->getId());
$payment->setExtraData(''); $payment->setExtraData('');
$this->em->persist($payment); $this->em->persist($payment);
} else if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type) { } else if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type || Payment::TYPE_PAIEMENT_RECURRENT_COTISATION_TAV) {
// TODO deal with recurrent payment (don only on first payment...)
$flux = $this->serializer->deserialize( $flux = $this->serializer->deserialize(
$payment->getFluxData(), $payment->getFluxData(),
AchatMonnaieAdherent::class, AchatMonnaieAdherent::class,
...@@ -284,9 +289,13 @@ class PaymentStatusExtension implements ExtensionInterface ...@@ -284,9 +289,13 @@ class PaymentStatusExtension implements ExtensionInterface
$this->em->persist($flux); $this->em->persist($flux);
$this->operationUtils->executeOperations($flux); $this->operationUtils->executeOperations($flux);
if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type) { if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type || Payment::TYPE_PAIEMENT_RECURRENT_COTISATION_TAV) {
// Apply cotisation rate, create new flux // Create new flux for cotisation, depending on process
$this->tavCotisationsUtils->applyTauxCotisation($flux); if ($this->container->getParameter('household_based_allowance')) {
$this->tavCotisationsUtils->applyHouseholdAllowance($flux);
} else {
$this->tavCotisationsUtils->applyTauxCotisation($flux);
}
} }
// Invalidate (delete) notify token after payment is captured // Invalidate (delete) notify token after payment is captured
......
...@@ -28,6 +28,7 @@ use App\Entity\User; ...@@ -28,6 +28,7 @@ use App\Entity\User;
use App\Form\Type\AchatMonnaieAConfirmerAdherentFormType; use App\Form\Type\AchatMonnaieAConfirmerAdherentFormType;
use App\Form\Type\AchatMonnaieAConfirmerPrestataireFormType; use App\Form\Type\AchatMonnaieAConfirmerPrestataireFormType;
use App\Form\Type\AchatMonnaieAdherentFormType; use App\Form\Type\AchatMonnaieAdherentFormType;
use App\Form\Type\AchatMonnaieAdherentRecurrentFormType;
use App\Form\Type\AchatMonnaiePrestataireFormType; use App\Form\Type\AchatMonnaiePrestataireFormType;
use App\Form\Type\AdherentInfosFormType; use App\Form\Type\AdherentInfosFormType;
use App\Form\Type\ChangeAdherentComptoirFormType; use App\Form\Type\ChangeAdherentComptoirFormType;
...@@ -474,6 +475,19 @@ class FormFactory ...@@ -474,6 +475,19 @@ class FormFactory
return $form->createView(); return $form->createView();
} }
public function getPaiementRecurrentCotisationTAVForm(User $user)
{
if (empty($user) || !$user->isGranted('ROLE_ADHERENT')) {
throw new \Exception('[FORM 25] Opération impossible !');
}
$entity = new AchatMonnaieAdherent();
$entity->setOperateur($user);
$form = $this->ff->create(AchatMonnaieAdherentRecurrentFormType::class, $entity, ['action' => $this->router->generate('paiementRecurrentCotisTav')]);
return $form->createView();
}
public function getComptoirEncaisserDonAdherentForm(User $user) public function getComptoirEncaisserDonAdherentForm(User $user)
{ {
if (empty($user) || empty($this->session->get('_comptoirgere'))) { if (empty($user) || empty($this->session->get('_comptoirgere'))) {
......
<?php
namespace App\Form\Type;
use App\Entity\AchatMonnaieAdherent;
use App\Entity\Adherent;
use App\Entity\DonAdherent;
use App\Entity\GlobalParameter;
use App\Entity\Prestataire;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AchatMonnaieAdherentRecurrentFormType extends AchatMonnaieAdherentFormType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$jourPrelevementChoices = [];
for ($i = 1; $i <= 28; $i++) {
$jourPrelevementChoices[strval($i)] = $i;
}
$builder
->add('nombreMois', IntegerType::class, [
'label' => 'Nombre d\'échéances désirées : ',
'required' => true,
'mapped' => false,
'help' => "Une échéance par mois.",
'attr' => ['autocomplete' => 'off']
])
->add('jourPrelevement', ChoiceType::class, [
'label' => 'Jour du prélèvement dans le mois : ',
'choices' => $jourPrelevementChoices,
'required' => true,
'mapped' => false,
'attr' => ['autocomplete' => 'off']
])
->remove('saveHelloAsso')
->remove('save')
->add('save', SubmitType::class, [
'label' => 'Payer en CB mon premier paiement et créer un paiement récurrent',
'translation_domain' => 'messages',
'attr' => [
'class' => 'btn-primary btn achatCBSubmit',
],
])
;
$builder
;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => AchatMonnaieAdherent::class,
]);
}
public function getParent()
{
return AchatMonnaieAdherentFormType::class;
}
public function getBlockPrefix()
{
return 'formAchatMonnaieAdherentRecurrent';
}
}
...@@ -55,6 +55,7 @@ class FormExtension extends AbstractExtension ...@@ -55,6 +55,7 @@ class FormExtension extends AbstractExtension
new \Twig_SimpleFunction('getSetPaymentCodeForm', [$this, 'getSetPaymentCodeForm']), new \Twig_SimpleFunction('getSetPaymentCodeForm', [$this, 'getSetPaymentCodeForm']),
new \Twig_SimpleFunction('getComptoirEncaisserCotisationForm', [$this, 'getComptoirEncaisserCotisationForm']), new \Twig_SimpleFunction('getComptoirEncaisserCotisationForm', [$this, 'getComptoirEncaisserCotisationForm']),
new \Twig_SimpleFunction('getPayerCotisationTAVForm', [$this, 'getPayerCotisationTAVForm']), new \Twig_SimpleFunction('getPayerCotisationTAVForm', [$this, 'getPayerCotisationTAVForm']),
new \Twig_SimpleFunction('getPaiementRecurrentCotisationTAVForm', [$this, 'getPaiementRecurrentCotisationTAVForm']),
new \Twig_SimpleFunction('getComptoirEncaisserDonAdherentForm', [$this, 'getComptoirEncaisserDonAdherentForm']) new \Twig_SimpleFunction('getComptoirEncaisserDonAdherentForm', [$this, 'getComptoirEncaisserDonAdherentForm'])
]; ];
} }
...@@ -219,6 +220,11 @@ class FormExtension extends AbstractExtension ...@@ -219,6 +220,11 @@ class FormExtension extends AbstractExtension
return $this->container->get('app.formfactory')->getPayerCotisationTAVForm($user); return $this->container->get('app.formfactory')->getPayerCotisationTAVForm($user);
} }
public function getPaiementRecurrentCotisationTAVForm(User $user)
{
return $this->container->get('app.formfactory')->getPaiementRecurrentCotisationTAVForm($user);
}
public function getComptoirEncaisserDonAdherentForm(User $user) public function getComptoirEncaisserDonAdherentForm(User $user)
{ {
return $this->container->get('app.formfactory')->getComptoirEncaisserDonAdherentForm($user); return $this->container->get('app.formfactory')->getComptoirEncaisserDonAdherentForm($user);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
{% endblock blocktitle %} {% endblock blocktitle %}
{% block blockcontent %} {% block blockcontent %}
{% set form = getPayerCotisationTAVForm(app.user) %} {% set form = getPayerCotisationTAVForm(app.user) %}
{% set formRecurrentPayment = getPaiementRecurrentCotisationTAVForm(app.user) %}
{% if form.montant.vars.value == false and not household_based_allowance %} {% if form.montant.vars.value == false and not household_based_allowance %}
<p>{{ 'Vous n\'avez pas de profil de cotisation associé, vous ne pouvez donc pas payer de cotisation.'|trans }}</p> <p>{{ 'Vous n\'avez pas de profil de cotisation associé, vous ne pouvez donc pas payer de cotisation.'|trans }}</p>
...@@ -16,20 +17,42 @@ ...@@ -16,20 +17,42 @@
<p> <p>
{{ 'Montant de la cotisation à payer'|trans }} : <span class="paiement_cotisation_montant">{{ form.montant.vars.value }}</span> {{ 'Montant de la cotisation à payer'|trans }} : <span class="paiement_cotisation_montant">{{ form.montant.vars.value }}</span>
</p> </p>
{{form_start(form)}} <select name="tav-cotisation-payment-type" id="tav-cotisation-payment-type" class="form-control" autocomplete="off">
{% if form.don is defined %} <option value="">Choisir une option de paiement</option>
{% include '@kohinos/tav/block/adherent_payer_cotisation_don.html.twig' %} <option value="instant-payment">Paiement immédiat</option>
<hr/> <option value="recurrent-payment">Paiement récurrent</option>
<p><b>{{ 'TOTAL A PAYER'|trans }} : <span class="achat_monnaie_montant_total">{{ form.montant.vars.value }}</span></b></p> </select>
{% endif %} <div id="tav-cotisation-instant-payment-container" class="tav-cotisation-payment-form">
{% if form.save is defined %} {{form_start(form)}}
{{ form_widget(form.save) }} {% if form.don is defined %}
{% endif %} {% include '@kohinos/tav/block/adherent_payer_cotisation_don.html.twig' with {'parentForm': form} %}
{% if form.saveHelloAsso is defined %} <hr/>
{{ form_widget(form.saveHelloAsso) }} <p><b>{{ 'TOTAL A PAYER'|trans }} : <span class="achat_monnaie_montant_total">{{ form.montant.vars.value }}</span></b></p>
{% endif %} {% endif %}
{{form_end(form)}} {% if form.save is defined %}
{{ form_widget(form.save) }}
{% endif %}
{% if form.saveHelloAsso is defined %}
{{ form_widget(form.saveHelloAsso) }}
{% endif %}
{{form_end(form)}}
</div>
<div id="tav-cotisation-recurrent-payment-container" class="tav-cotisation-payment-form">
{{form_start(formRecurrentPayment)}}
{{ form_row(formRecurrentPayment.nombreMois) }}
{{ form_row(formRecurrentPayment.jourPrelevement) }}
{% if formRecurrentPayment.don is defined %}
{% include '@kohinos/tav/block/adherent_payer_cotisation_don.html.twig' with {'parentForm': formRecurrentPayment} %}
<hr/>
<p><b>{{ 'TOTAL PREMIER PAIEMENT'|trans }} : <span class="achat_monnaie_premier_montant_total">{{ formRecurrentPayment.montant.vars.value }}</span></b></p>
<p><b>{{ 'ÉHÉANCES SUIVANTES'|trans }} : <span class="achat_monnaie_montant_total">{{ formRecurrentPayment.montant.vars.value }}</span></b></p>
{% endif %}
{% if formRecurrentPayment.save is defined %}
{{ form_widget(formRecurrentPayment.save) }}
{% endif %}
{{form_end(formRecurrentPayment)}}
</div>
{% endif %} {% endif %}
{% endblock blockcontent %} {% endblock blockcontent %}
\ No newline at end of file
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
En plus de ma cotisation je souhaite faire un don pour ce mois En plus de ma cotisation je souhaite faire un don pour ce mois
{% endblock blocktitle %} {% endblock blocktitle %}
{% block blockcontent %} {% block blockcontent %}
{{ form_row(form.don, {row_attr:{style: 'max-width: 200px;margin: 0 auto;'}}) }} {{ form_row(parentForm.don, {row_attr:{style: 'max-width: 200px;margin: 0 auto;'}}) }}
{% endblock blockcontent %} {% endblock blockcontent %}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment