(
+
+ Data.subvention est un outil développé par la . Il recense les
+ subventions demandées et reçues par une association.
+
+ Les données sont issues de Chorus et du Fonjep (Fonds de
+ coopération de la jeunesse et de l’éducation populaire).
+
+);
+
+const SubventionDetails: React.FC<{ subventions: ISubventions }> = ({
+ subventions,
+}) => {
+ const subventionStats = useMemo(() => {
+ const totalSubventions = subventions.length;
+ const mostRecentYear = subventions[totalSubventions - 1]?.year;
+ const approvedSubventions = subventions.filter(
+ (subvention) => subvention.label === 'Accordé'
+ );
+ const totalApproved = approvedSubventions.length;
+ const totalAmount = approvedSubventions.reduce(
+ (acc, subvention) => acc + subvention.amount,
+ 0
+ );
+
+ return {
+ totalSubventions,
+ mostRecentYear,
+ totalApproved,
+ totalAmount,
+ };
+ }, [subventions]);
+
+ return (
+ <>
+ Depuis {subventionStats.mostRecentYear}, cette association compte{' '}
+ {subventionStats.totalSubventions} demandes de subventions référencées
+ dans .
+
+ Parmi ces subventions :{' '}
+ {subventionStats.totalApproved} ont été accordées pour un total
+ de {formatCurrency(subventionStats.totalAmount)}. Le reste a été
+ refusé, est en cours d’instruction ou se situe dans un état inconnu.
+
+ >
+ );
+};
+
+const SubventionsAssociation: React.FC<{
+ uniteLegale: IAssociation;
+ session: ISession | null;
+}> = ({ uniteLegale, session }) => {
+ const subventions = useAPIRouteData(
+ 'subventions-association',
+ uniteLegale.siren,
+ session
+ );
+
+ return (
+
+ {(subventions) =>
+ !subventions || subventions?.length === 0 ? (
+ <>
+ Aucune demande de subvention n’a été trouvée pour cette association
+ dans .
+ >
+ ) : (
+ <>
+
+ [
+ {subvention.year},
+ subvention.description ? (
+ {subvention.description}
+ ) : (
+
+ ),
+ formatCurrency(subvention.amount),
+ subvention.label ? (
+
+ {subvention.label}
+
+ ) : (
+ Inconnu
+ ),
+ ])}
+ />
+ >
+ )
+ }
+
+ );
+};
+
+export const SubventionsAssociationSection: React.FC<{
+ uniteLegale: IAssociation;
+ session: ISession | null;
+}> = ({ uniteLegale, session }) => {
+ if (!hasRights(session, AppScope.subventionsAssociation)) {
+ // for a start lets hide it first before Data subvention validation
+ return null;
+ // return (
+ //
+ // );
+ }
+ return ;
+};
diff --git a/components/title-section/tabs/index.tsx b/components/title-section/tabs/index.tsx
index 01dc3a44d..cb3e91cde 100644
--- a/components/title-section/tabs/index.tsx
+++ b/components/title-section/tabs/index.tsx
@@ -1,4 +1,3 @@
-import Link from 'next/link';
import { PrintNever } from '#components-ui/print-visibility';
import {
checkHasLabelsAndCertificates,
@@ -11,6 +10,7 @@ import {
} from '#models/core/types';
import { AppScope, hasRights } from '#models/user/rights';
import { ISession } from '#models/user/session';
+import Link from 'next/link';
import styles from './styles.module.css';
import TabLink from './tab-link';
@@ -87,7 +87,7 @@ export const Tabs: React.FC<{
pathPrefix: '/annonces/',
noFollow: false,
shouldDisplay: true,
- width: '130px',
+ width: uniteLegale.dateMiseAJourInpi ? '130px' : '90px',
},
{
ficheType: FICHE.CERTIFICATS,
diff --git a/data/administrations/djepva.yml b/data/administrations/djepva.yml
index 393060985..0c94d1e21 100644
--- a/data/administrations/djepva.yml
+++ b/data/administrations/djepva.yml
@@ -8,10 +8,18 @@ apiMonitors:
apiSlug: rna
updownIoId: phbs
apiDocumentationLink: https://www.associations.gouv.fr/les-api-et-autres-outils.html
+ - label: API Data.Subvention
+ apiSlug: data-subvention
+ isProtected: true
+ apiDocumentationLink: https://datasubvention.beta.gouv.fr/api/
dataSources:
- label: Documents complémentaires des associations
apiSlug: api-entreprise
data:
- label: documents administratifs complémentaires
+ - label: Subventions des associations
+ apiSlug: data-subvention
+ data:
+ - label: subventions (sources Chorus et Fonjep)
description: |
Au sein du ministère de l'Éducation nationale et de la Jeunesse, la DJEPVA élabore et pilote les politiques en faveur des jeunes, de l'engagement, de l'éducation populaire et de la vie associative.
diff --git a/models/subventions/association/index.ts b/models/subventions/association/index.ts
new file mode 100644
index 000000000..b0990ff63
--- /dev/null
+++ b/models/subventions/association/index.ts
@@ -0,0 +1,49 @@
+import { clientDataSubvention } from '#clients/api-data-subvention';
+import { HttpNotFound } from '#clients/exceptions';
+import { EAdministration } from '#models/administrations/EAdministration';
+import {
+ APINotRespondingFactory,
+ IAPINotRespondingError,
+} from '#models/api-not-responding';
+import { getUniteLegaleFromSlug } from '#models/core/unite-legale';
+import { FetchRessourceException } from '#models/exceptions';
+import logErrorInSentry from '#utils/sentry';
+
+export type ISubventions = ISubvention[];
+
+export interface ISubvention {
+ year: number;
+ label: string;
+ status: string;
+ description: string;
+ amount: number;
+}
+
+export const getSubventionsAssociationFromSlug = async (
+ slug: string
+): Promise => {
+ const uniteLegale = await getUniteLegaleFromSlug(slug, {
+ isBot: false,
+ });
+
+ const { siren } = uniteLegale;
+
+ try {
+ return await clientDataSubvention(siren);
+ } catch (e: any) {
+ if (e instanceof HttpNotFound) {
+ return APINotRespondingFactory(EAdministration.DJEPVA, 404);
+ }
+ logErrorInSentry(
+ new FetchRessourceException({
+ ressource: 'DataSubvention',
+ cause: e,
+ context: {
+ siren,
+ },
+ administration: EAdministration.DJEPVA,
+ })
+ );
+ return APINotRespondingFactory(EAdministration.DJEPVA, 500);
+ }
+};
diff --git a/models/user/rights.ts b/models/user/rights.ts
index 2a2ac9989..6d479a179 100644
--- a/models/user/rights.ts
+++ b/models/user/rights.ts
@@ -17,6 +17,7 @@ export enum AppScope {
carteProfessionnelleTravauxPublics = 'opendata',
nonDiffusible = 'nonDiffusible',
isAgent = 'isAgent',
+ subventionsAssociation = 'subventionsAssociation',
}
/**
@@ -40,6 +41,8 @@ export function hasRights(session: ISession | null, rightScope: AppScope) {
return userScopes.includes('opendata');
case AppScope.beneficiaires:
return userScopes.includes('beneficiaires');
+ case AppScope.subventionsAssociation:
+ return userScopes.includes('subventions_association');
case AppScope.nonDiffusible:
return userScopes.includes('nonDiffusible');
case AppScope.isAgent:
diff --git a/models/user/scopes.ts b/models/user/scopes.ts
index 2d6bbb458..cacf330ea 100644
--- a/models/user/scopes.ts
+++ b/models/user/scopes.ts
@@ -5,6 +5,7 @@ export type IAgentScope =
| 'nonDiffusible'
| 'conformite'
| 'beneficiaires'
+ | 'subventions_association'
| 'agent'
| 'opendata';
@@ -15,6 +16,7 @@ export const isAgentScope = (str: string): str is IAgentScope => {
'nonDiffusible',
'conformite',
'beneficiaires',
+ 'subventions_association',
'agent',
'opendata',
].indexOf(str) > 0
@@ -24,7 +26,7 @@ export const isAgentScope = (str: string): str is IAgentScope => {
return false;
};
-const agentScope = [
+const defaultAgentScopes = [
'agent',
'nonDiffusible',
'rne',
@@ -47,7 +49,12 @@ export const getAgentScopes = async (
if (isTestAccount) {
return {
- scopes: [...agentScope, 'conformite', 'beneficiaires'],
+ scopes: [
+ ...defaultAgentScopes,
+ 'conformite',
+ 'beneficiaires',
+ 'subventions_association',
+ ],
userType: 'Super-agent connecté',
};
}
@@ -55,7 +62,7 @@ export const getAgentScopes = async (
const additionnalScopes = await getAdditionnalIAgentScope(userEmail);
return {
- scopes: [...agentScope, ...additionnalScopes],
+ scopes: [...defaultAgentScopes, ...additionnalScopes],
userType:
additionnalScopes.length > 0 ? 'Super-agent connecté' : 'Agent connecté',
};