Commit 7a12ca10 by Yvon Kerdoncuff

Merge branch '6150-et-6159-correction-solde-et-envois-mails' into 'develop'

add fields to fix balance in fiche adherent form for super admin only

See merge request cooperatic/kohinos-tav!84
parents 15b362e3 9639b5c6
...@@ -51,6 +51,7 @@ AUTOMATISATION_RECONVERSION=0 ...@@ -51,6 +51,7 @@ AUTOMATISATION_RECONVERSION=0
PRESTA_EXTRA_DATA=0 PRESTA_EXTRA_DATA=0
HOUSEHOLD_BASED_ALLOWANCE=0 HOUSEHOLD_BASED_ALLOWANCE=0
SSA_FRIENDLY_FLUX_TYPE_NAMES=0 SSA_FRIENDLY_FLUX_TYPE_NAMES=0
FIX_BALANCE_ADHERENT_PASSWORD=ChangeMe
EMAIL_ERROR=technique@kohinos.net EMAIL_ERROR=technique@kohinos.net
EMAIL_USER_FROM=noreply@kohinos.fr EMAIL_USER_FROM=noreply@kohinos.fr
......
...@@ -10,6 +10,7 @@ require('../css/admin.css'); ...@@ -10,6 +10,7 @@ require('../css/admin.css');
require('bootstrap'); require('bootstrap');
require('../css/common.css'); require('../css/common.css');
require('../js/geoloc.js'); require('../js/geoloc.js');
const $ = require("jquery");
$('#flash-messages').flashNotification('init'); $('#flash-messages').flashNotification('init');
...@@ -130,4 +131,11 @@ $(document).ready(function() { ...@@ -130,4 +131,11 @@ $(document).ready(function() {
} }
actionOnRecevoirUnRappelChange(); actionOnRecevoirUnRappelChange();
} }
if($(".fixBalanceAdherentFormPart").length > 0) {
$(".fixBalanceAdherentFormPart").parent().parent().hide();
$("div[id$='_idmlc']").append(
"<br/><input type='button' id='showFieldsToFixBalance' onclick='$(\".fixBalanceAdherentFormPart\").parent().parent().show();' value='Afficher les champs pour corriger le solde'> </input>"
);
}
}); });
...@@ -18,6 +18,7 @@ parameters: ...@@ -18,6 +18,7 @@ parameters:
presta_extra_data: '%env(PRESTA_EXTRA_DATA)%' presta_extra_data: '%env(PRESTA_EXTRA_DATA)%'
household_based_allowance: '%env(HOUSEHOLD_BASED_ALLOWANCE)%' household_based_allowance: '%env(HOUSEHOLD_BASED_ALLOWANCE)%'
ssa_friendly_flux_type_names: '%env(SSA_FRIENDLY_FLUX_TYPE_NAMES)%' ssa_friendly_flux_type_names: '%env(SSA_FRIENDLY_FLUX_TYPE_NAMES)%'
fix_balance_adherent_password: '%env(FIX_BALANCE_ADHERENT_PASSWORD)%'
# PARAMETRES DES IMPORTS POSSIBLE POUR L'APPLICATION DE GESTION DE MONNAIE LOCALE COMPLEMENTAIRE # PARAMETRES DES IMPORTS POSSIBLE POUR L'APPLICATION DE GESTION DE MONNAIE LOCALE COMPLEMENTAIRE
......
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.
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"admin": { "admin": {
"js": [ "js": [
"/build/runtime.6ad5c9da.js", "/build/runtime.6ad5c9da.js",
"/build/admin.86a2d986.js" "/build/admin.3edfb527.js"
], ],
"css": [ "css": [
"/build/admin.4de55830.css" "/build/admin.4de55830.css"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"build/app.css": "/build/app.8a3f698b.css", "build/app.css": "/build/app.8a3f698b.css",
"build/app.js": "/build/app.3644f7b2.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.3edfb527.js",
"build/runtime.js": "/build/runtime.6ad5c9da.js", "build/runtime.js": "/build/runtime.6ad5c9da.js",
"build/images/fa-solid-900.svg": "/build/images/fa-solid-900.a838c42a.svg", "build/images/fa-solid-900.svg": "/build/images/fa-solid-900.a838c42a.svg",
"build/images/fa-brands-400.svg": "/build/images/fa-brands-400.05d20183.svg", "build/images/fa-brands-400.svg": "/build/images/fa-brands-400.05d20183.svg",
......
(()=>{"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")})))}))})()})(); (()=>{"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.3edfb527.js'},{'revision':'ad79405d542b397996a3079203114b42','url':'/build/admin.3edfb527.js.LICENSE.txt'},{'revision':null,'url':'/build/admin.4de55830.css'},{'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
...@@ -40,6 +40,7 @@ use Symfony\Component\Form\Extension\Core\Type\CheckboxType; ...@@ -40,6 +40,7 @@ use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType; use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\NumberType; use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormError;
...@@ -359,6 +360,42 @@ class AdherentAdmin extends AbstractAdmin ...@@ -359,6 +360,42 @@ class AdherentAdmin extends AbstractAdmin
]) ])
->end() ->end()
->end(); ->end();
//Add form part allowing super admin to fix balance
if($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')
&& $this->security->isGranted('ROLE_SUPER_ADMIN')) {
$formMapper
->tab('General')
->with('Informations de cotisation')
->add('fixedBalance', TextType::class, [
'label' => "Corriger le solde suite à une erreur de cotisation",
'mapped' => false,
'required' => false,
'attr' => [
'autocomplete' => 'off',
'class' => 'fixBalanceAdherentFormPart'
]
])
->add('justification', TextType::class, [
'mapped' => false,
'required' => false,
'attr' => [
'autocomplete' => 'off',
'class' => 'fixBalanceAdherentFormPart'
]
])
->add('password', PasswordType::class, [
'label' => 'Mot de passe pour corriger le solde',
'mapped' => false,
'required' => false,
'data' => "",
'attr' => [
'autocomplete' => 'off',
'class' => 'fixBalanceAdherentFormPart'
]
])
->end()
->end();
}
} }
} }
...@@ -378,8 +415,8 @@ class AdherentAdmin extends AbstractAdmin ...@@ -378,8 +415,8 @@ class AdherentAdmin extends AbstractAdmin
} }
} }
// check cotisation amount
if ($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')) { if ($this->getConfigurationPool()->getContainer()->getParameter('household_based_allowance')) {
// check cotisation amount
$adultsCount = $adherent->getHouseholdAdultCount(); $adultsCount = $adherent->getHouseholdAdultCount();
$dependentChildrenCount = count($adherent->getDependentChildren()); $dependentChildrenCount = count($adherent->getDependentChildren());
$minCotisationAmount = 10 + 5 * ( $adultsCount - 1 ) + 5 * $dependentChildrenCount; $minCotisationAmount = 10 + 5 * ( $adultsCount - 1 ) + 5 * $dependentChildrenCount;
...@@ -387,6 +424,26 @@ class AdherentAdmin extends AbstractAdmin ...@@ -387,6 +424,26 @@ class AdherentAdmin extends AbstractAdmin
if ($adherent->getCotisationAmount() < $minCotisationAmount) { if ($adherent->getCotisationAmount() < $minCotisationAmount) {
$event->getForm()->get('cotisationAmount')->addError(new FormError('Le montant minimum est de ' . $minCotisationAmount . '€ (selon les données du foyer indiquées)')); $event->getForm()->get('cotisationAmount')->addError(new FormError('Le montant minimum est de ' . $minCotisationAmount . '€ (selon les données du foyer indiquées)'));
} }
// try to fix balance if required
if($this->security->isGranted('ROLE_SUPER_ADMIN')
&& $event->getForm()->has('fixedBalance')
&& $event->getForm()->get('fixedBalance')->getData()
&& $event->getForm()->get('fixedBalance')->getData() >= 0) {
$password = $this->getConfigurationPool()->getContainer()->getParameter('fix_balance_adherent_password');
//this password purpose is to be an additional warning for super admin and
//is not intended to be securely stored as only super admin can use this feature
if ($event->getForm()->get('password')->getData() !== $password) {
$event->getForm()->get('password')->addError(new FormError('Mot de passe incorrect.'));
} elseif(!$event->getForm()->get('justification')->getData()) {
$event->getForm()->get('justification')->addError(new FormError('Merci de justifier cette opération sensible.'));
} else {
$this->tavCotisationUtils->fixBalance(
$adherent, $event->getForm()->get('fixedBalance')->getData(), $event->getForm()->get('justification')->getData()
);
$em->flush();
}
}
} }
}); });
parent::configureFormFields($formMapper); parent::configureFormFields($formMapper);
......
...@@ -23,6 +23,9 @@ class CotisationTavApplication extends Flux ...@@ -23,6 +23,9 @@ class CotisationTavApplication extends Flux
{ {
const TYPE_REVERSEMENT_COTISATION_ADHERENT = 'reversement_cotisation_adherent'; const TYPE_REVERSEMENT_COTISATION_ADHERENT = 'reversement_cotisation_adherent';
const TYPE_PRELEVEMENT_COTISATION_ADHERENT = 'prelevement_cotisation_adherent'; const TYPE_PRELEVEMENT_COTISATION_ADHERENT = 'prelevement_cotisation_adherent';
const TYPE_PRELEVEMENT_COTISATION_ADHERENT_DEPASSEMENT_PLAFOND = 'prelevement_cotisation_adherent_depassement_plafond';
const TYPE_PRELEVEMENT_COTISATION_ADHERENT_CORRECTION_SOLDE = 'prelevement_cotisation_adherent_correction_solde';
const TYPE_REVERSEMENT_COTISATION_ADHERENT_CORRECTION_SOLDE = 'reversement_cotisation_adherent_correction_solde';
/** /**
* @return string * @return string
......
...@@ -12,6 +12,7 @@ use Doctrine\ORM\Mapping as ORM; ...@@ -12,6 +12,7 @@ use Doctrine\ORM\Mapping as ORM;
* - [Allocation selon foyer] Le montant reçu calculé est inférieur au montant payé * - [Allocation selon foyer] Le montant reçu calculé est inférieur au montant payé
* - [Allocation selon foyer] Un administrateur effectue une opération manuelle de prélèvement de l'adhérent * - [Allocation selon foyer] Un administrateur effectue une opération manuelle de prélèvement de l'adhérent
* pour ramener son solde au niveau de son plafond. * pour ramener son solde au niveau de son plafond.
* - [Allocation selon foyer] Un administrateur effectue une opération de correction de solde qui conduit à un prélèvement.
* *
* L'adhérent•e reçoit moins d'emlc que ce qu'elle•il paye en €, * L'adhérent•e reçoit moins d'emlc que ce qu'elle•il paye en €,
* un second flux est créé pour prélever le complément de la cotisation. * un second flux est créé pour prélever le complément de la cotisation.
......
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Child class used to notify adherents by email.
*
* - [Allocation selon foyer] Un administrateur effectue une opération de correction de solde qui conduit à un prélèvement.
* @ORM\Entity
*/
class CotisationTavPrelevementCorrectionSolde extends CotisationTavPrelevement
{
/**
* @return string
*/
public function getType(): string
{
return parent::TYPE_PRELEVEMENT_COTISATION_ADHERENT_CORRECTION_SOLDE;
}
public function getUsersToNotify()
{
return [
'expediteurs' => [$this->getExpediteur()->getUser()],
];
}
}
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Child class used to notify adherents by email.
*
* - [Allocation selon foyer] Un administrateur effectue une opération manuelle de prélèvement de l'adhérent
* pour ramener son solde au niveau de son plafond.
* @ORM\Entity
*/
class CotisationTavPrelevementDepassementPlafond extends CotisationTavPrelevement
{
/**
* @return string
*/
public function getType(): string
{
return parent::TYPE_PRELEVEMENT_COTISATION_ADHERENT_DEPASSEMENT_PLAFOND;
}
public function getUsersToNotify()
{
return [
'expediteurs' => [$this->getExpediteur()->getUser()],
];
}
}
...@@ -10,6 +10,7 @@ use Doctrine\ORM\Mapping as ORM; ...@@ -10,6 +10,7 @@ use Doctrine\ORM\Mapping as ORM;
* * Dans les cas suivants : * * Dans les cas suivants :
* - [Profil de Cotisation] La taux est supérieur à 1 * - [Profil de Cotisation] La taux est supérieur à 1
* - [Allocation selon foyer] Le montant reçu calculé est supérieur au montant payé * - [Allocation selon foyer] Le montant reçu calculé est supérieur au montant payé
* - [Allocation selon foyer] Un administrateur effectue une opération de correction de solde qui conduit à un reversement.
* *
* L'adhérent•e reçoit plus d'emlc que ce qu'elle•il paye en €, * L'adhérent•e reçoit plus d'emlc que ce qu'elle•il paye en €,
* un second flux est créé pour reverser le complément de la cotisation. * un second flux est créé pour reverser le complément de la cotisation.
......
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Child class used to notify adherents by email.
*
* - [Allocation selon foyer] Un administrateur effectue une opération de correction de solde qui conduit à un reversement.
* @ORM\Entity
*/
class CotisationTavReversementCorrectionSolde extends CotisationTavReversement
{
/**
* @return string
*/
public function getType(): string
{
return parent::TYPE_REVERSEMENT_COTISATION_ADHERENT_CORRECTION_SOLDE;
}
public function getUsersToNotify()
{
return [
'destinataires' => [$this->getDestinataire()->getUser()],
];
}
}
...@@ -57,6 +57,9 @@ use Symfony\Component\Validator\Constraints as Assert; ...@@ -57,6 +57,9 @@ use Symfony\Component\Validator\Constraints as Assert;
* "application_cotisation_tav" = "CotisationTavApplication", * "application_cotisation_tav" = "CotisationTavApplication",
* "reversement_cotisation_adherent" = "CotisationTavReversement", * "reversement_cotisation_adherent" = "CotisationTavReversement",
* "prelevement_cotisation_adherent" = "CotisationTavPrelevement", * "prelevement_cotisation_adherent" = "CotisationTavPrelevement",
* "prelevement_cotisation_adherent_depassement_plafond" = "CotisationTavPrelevementDepassementPlafond",
* "prelevement_cotisation_adherent_correction_solde" = "CotisationTavPrelevementCorrectionSolde",
* "reversement_cotisation_adherent_correction_solde" = "CotisationTavReversementCorrectionSolde",
* }) * })
*/ */
abstract class Flux implements FluxInterface abstract class Flux implements FluxInterface
...@@ -658,13 +661,16 @@ abstract class Flux implements FluxInterface ...@@ -658,13 +661,16 @@ abstract class Flux implements FluxInterface
: $this->type; : $this->type;
} }
public static function ssaUsefulFriendlyTypeNames($differentiateAchatsDeMonaPayzenOrComptoir = false) public static function ssaUsefulFriendlyTypeNames($uniqueValues = false)
{ {
return [ return [
VenteEmlc::TYPE_VENTE_EMLC_ADHERENT => "Achat de MonA via cotisation" . ($differentiateAchatsDeMonaPayzenOrComptoir ? " (au comptoir)" : ""), VenteEmlc::TYPE_VENTE_EMLC_ADHERENT => "Achat de MonA via cotisation" . ($uniqueValues ? " (au comptoir)" : ""),
AchatMonnaie::TYPE_ACHAT_ADHERENT => "Achat de MonA via cotisation" . ($differentiateAchatsDeMonaPayzenOrComptoir ? " (via Payzen)" : ""), AchatMonnaie::TYPE_ACHAT_ADHERENT => "Achat de MonA via cotisation" . ($uniqueValues ? " (via Payzen)" : ""),
CotisationTavApplication::TYPE_REVERSEMENT_COTISATION_ADHERENT => "Allocation complémentaire de la caisse", CotisationTavApplication::TYPE_REVERSEMENT_COTISATION_ADHERENT => "Allocation complémentaire de la caisse",
CotisationTavApplication::TYPE_REVERSEMENT_COTISATION_ADHERENT_CORRECTION_SOLDE => "Allocation complémentaire de la caisse" . ($uniqueValues ? " (correction solde)" : ""),
CotisationTavApplication::TYPE_PRELEVEMENT_COTISATION_ADHERENT => "Réduction de l'allocation", CotisationTavApplication::TYPE_PRELEVEMENT_COTISATION_ADHERENT => "Réduction de l'allocation",
CotisationTavApplication::TYPE_PRELEVEMENT_COTISATION_ADHERENT_DEPASSEMENT_PLAFOND => "Réduction de l'allocation" . ($uniqueValues ? " (dépassement plafond)" : ""),
CotisationTavApplication::TYPE_PRELEVEMENT_COTISATION_ADHERENT_CORRECTION_SOLDE => "Réduction de l'allocation" . ($uniqueValues ? " (correction solde)" : ""),
Don::TYPE_DON_ADHERENT => Don::TYPE_DON_ADHERENT, Don::TYPE_DON_ADHERENT => Don::TYPE_DON_ADHERENT,
Don::TYPE_DON_PRESTATAIRE => Don::TYPE_DON_PRESTATAIRE, Don::TYPE_DON_PRESTATAIRE => Don::TYPE_DON_PRESTATAIRE,
Reconversion::TYPE_RECONVERSION_PRESTATAIRE => Reconversion::TYPE_RECONVERSION_PRESTATAIRE, Reconversion::TYPE_RECONVERSION_PRESTATAIRE => Reconversion::TYPE_RECONVERSION_PRESTATAIRE,
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
namespace App\Utils; namespace App\Utils;
use App\Entity\Adherent; use App\Entity\Adherent;
use App\Entity\CotisationTavPrelevementCorrectionSolde;
use App\Entity\CotisationTavPrelevementDepassementPlafond;
use App\Entity\CotisationTavReversementCorrectionSolde;
use App\Entity\Payment; use App\Entity\Payment;
use App\Entity\Siege; use App\Entity\Siege;
use App\Entity\Flux; use App\Entity\Flux;
...@@ -234,7 +237,7 @@ class TAVCotisationUtils ...@@ -234,7 +237,7 @@ class TAVCotisationUtils
throw new \Exception("Impossible de prélèver : le solde de l'adhérent est inférieur ou égal au plafond."); throw new \Exception("Impossible de prélèver : le solde de l'adhérent est inférieur ou égal au plafond.");
} }
$flux = new CotisationTavPrelevement(); $flux = new CotisationTavPrelevementDepassementPlafond();
$flux->setExpediteur($adherent); $flux->setExpediteur($adherent);
$flux->setDestinataire($siege); $flux->setDestinataire($siege);
$flux->setMontant(-$amountDiff); $flux->setMontant(-$amountDiff);
...@@ -249,6 +252,41 @@ class TAVCotisationUtils ...@@ -249,6 +252,41 @@ class TAVCotisationUtils
} }
/** /**
* Method called to create Flux to fix balance (for household based allowance).
*/
public function fixBalance(Adherent $adherent, $fixedBalance, $justification)
{
$balance = $adherent->getEmlcAccount()->getBalance();
$siege = $this->em->getRepository(Siege::class)->getTheOne();
$amountDiff = $fixedBalance - $balance;
if ($amountDiff >= 0) {
//Accroissement du solde
$flux = new CotisationTavReversementCorrectionSolde();
$flux->setExpediteur($siege);
$flux->setDestinataire($adherent);
$flux->setReference(
"Reversement pour corriger le solde de " . $balance . " MonA à " . $fixedBalance . " MonA : " . $justification
);
} else {
//Réduction du solde
$flux = new CotisationTavPrelevementCorrectionSolde();
$flux->setExpediteur($adherent);
$flux->setDestinataire($siege);
$flux->setReference(
"Prélèvement pour corriger le solde de " . $balance . " MonA à " . $fixedBalance . " MonA : " . $justification
);
}
$flux->setMontant(abs($amountDiff));
$flux->setOperateur($this->security->getUser());
$flux->setRole($this->security->getUser()->getGroups()[0]->__toString());
$flux->setMoyen(MoyenEnum::MOYEN_EMLC);
$this->em->persist($flux);
$this->operationUtils->executeOperations($flux);
}
/**
* Get the last cotisation of an adhérent * Get the last cotisation of an adhérent
* *
* @param Adherent $adherent * @param Adherent $adherent
......
...@@ -10,6 +10,12 @@ ...@@ -10,6 +10,12 @@
<h3> <h3>
{% if flux.type == 'reconversion' %} {% if flux.type == 'reconversion' %}
{{ 'Demande de reconversion' }} {{ 'Demande de reconversion' }}
{% elseif flux.type == 'prelevement_cotisation_adherent_depassement_plafond' %}
{{ "Réduction de l'allocation après dépassement du plafond" }}
{% elseif flux.type == 'prelevement_cotisation_adherent_correction_solde' %}
{{ "Correction de solde (réduction de l'allocation) suite à une erreur de cotisation" }}
{% elseif flux.type == 'reversement_cotisation_adherent_correction_solde' %}
{{ "Correction de solde (allocation complémentaire de la caisse) suite à une erreur de cotisation" }}
{% else %} {% else %}
{{ flux.parenttype|capitalize }} : {{ flux.type|replace({'_' : ' => '}) }} {{ flux.parenttype|capitalize }} : {{ flux.type|replace({'_' : ' => '}) }}
{% endif %} {% endif %}
......
...@@ -130,3 +130,6 @@ des_vente_emlc: 'Achat monnaie numérique' ...@@ -130,3 +130,6 @@ des_vente_emlc: 'Achat monnaie numérique'
exp_vente_emlc: 'Vente monnaie numérique' exp_vente_emlc: 'Vente monnaie numérique'
exp_ticket_print: 'Impression de billets' exp_ticket_print: 'Impression de billets'
exp_ticket_destroy: 'Destruction de billets' exp_ticket_destroy: 'Destruction de billets'
exp_prelevement_cotisation_adherent_depassement_plafond_email_subject: 'Réduction de l''allocation après dépassement du plafond'
exp_prelevement_cotisation_adherent_correction_solde_email_subject: 'Correction de solde (réduction de l''allocation) suite à une erreur de cotisation'
des_reversement_cotisation_adherent_correction_solde_email_subject: 'Correction de solde (allocation complémentaire de la caisse) suite à une erreur de cotisation'
\ 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