Skip to content
This repository has been archived by the owner on Nov 14, 2024. It is now read-only.

Commit

Permalink
feat(simplification): fusion des scl en adc (#1443)
Browse files Browse the repository at this point in the history
  • Loading branch information
anis authored Sep 12, 2024
1 parent 0192de3 commit c177c80
Show file tree
Hide file tree
Showing 20 changed files with 128 additions and 110 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('vérifie l’arbre d’octroi d’AXM', () => {
date: toCaminoDate('2022-04-15'),
},
{
...ETES.saisineDesCollectivitesLocales.FAIT,
...ETES.avisDesCollectivites.FAIT,
date: toCaminoDate('2022-04-15'),
},
{ ...ETES.avisDesServicesEtCommissionsConsultatives.FAIT, date: toCaminoDate('2022-04-15') },
Expand Down Expand Up @@ -102,7 +102,7 @@ describe('vérifie l’arbre d’octroi d’AXM', () => {
date: toCaminoDate('2022-04-15'),
},
{
...ETES.saisineDesCollectivitesLocales.FAIT,
...ETES.avisDesCollectivites.FAIT,
date: toCaminoDate('2022-04-15'),
},
{ ...ETES.avisDesServicesEtCommissionsConsultatives.FAIT, date: toCaminoDate('2022-04-15') },
Expand Down Expand Up @@ -221,10 +221,6 @@ describe('vérifie l’arbre d’octroi d’AXM', () => {
...ETES.recevabiliteDeLaDemande.FAVORABLE,
date: toCaminoDate('2022-04-15'),
},
{
...ETES.saisineDesCollectivitesLocales.FAIT,
date: toCaminoDate('2022-04-16'),
},
{ ...ETES.avisDesCollectivites.FAIT, date: toCaminoDate('2022-04-17') },
{ ...ETES.avisDesServicesEtCommissionsConsultatives.FAIT, date: toCaminoDate('2022-04-18') },
{
Expand Down Expand Up @@ -283,7 +279,7 @@ describe('vérifie l’arbre d’octroi d’AXM', () => {
date: toCaminoDate('2022-04-15'),
},
{
...ETES.saisineDesCollectivitesLocales.FAIT,
...ETES.avisDesCollectivites.FAIT,
date: toCaminoDate('2022-04-16'),
},
{ ...ETES.avisDesServicesEtCommissionsConsultatives.FAIT, date: toCaminoDate('2022-04-18') },
Expand All @@ -294,13 +290,11 @@ describe('vérifie l’arbre d’octroi d’AXM', () => {
'FAIRE_CLASSEMENT_SANS_SUITE',
'DEMANDER_INFORMATION_POUR_AVIS_DREAL',
'FAIRE_DESISTEMENT_DEMANDEUR',
'RENDRE_AVIS_DES_COLLECTIVITES',
])
expect(service).canOnlyTransitionTo({ machine: axmOctMachine, date: toCaminoDate('2022-05-17') }, [
'FAIRE_CLASSEMENT_SANS_SUITE',
'DEMANDER_INFORMATION_POUR_AVIS_DREAL',
'FAIRE_DESISTEMENT_DEMANDEUR',
'RENDRE_AVIS_DES_COLLECTIVITES',
])
})

Expand Down
27 changes: 11 additions & 16 deletions packages/api/src/business/rules-demarches/axm/oct.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ type AXMOctXStateEvent =
| { type: 'FAIRE_RECEVABILITE_DEMANDE_FAVORABLE' }
| { type: 'FAIRE_RECEVABILITE_DEMANDE_DEFAVORABLE' }
| { type: 'MODIFIER_LA_DEMANDE' }
| { type: 'FAIRE_SAISINE_COLLECTIVITES_LOCALES' }
| { type: 'RENDRE_AVIS_DES_COLLECTIVITES' }
| RendreAvisDreal
| RendreAvisDesServicesEtCommissionsConsultatives
Expand Down Expand Up @@ -130,8 +129,7 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
DEMANDER_COMPLEMENTS_POUR_RECEVABILITE: { db: ETES.demandeDeComplements_RecevabiliteDeLaDemande_, mainStep: false },
RECEVOIR_COMPLEMENTS_POUR_RECEVABILITE: { db: ETES.receptionDeComplements_RecevabiliteDeLaDemande_, mainStep: false },
MODIFIER_LA_DEMANDE: { db: ETES.modificationDeLaDemande, mainStep: true },
FAIRE_SAISINE_COLLECTIVITES_LOCALES: { db: ETES.saisineDesCollectivitesLocales, mainStep: true },
RENDRE_AVIS_DES_COLLECTIVITES: { db: ETES.avisDesCollectivites, mainStep: false },
RENDRE_AVIS_DES_COLLECTIVITES: { db: ETES.avisDesCollectivites, mainStep: true },
RENDRE_AVIS_DREAL: { db: ETES.rapportEtAvisDeLaDREAL, mainStep: true },
RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES: { db: ETES.avisDesServicesEtCommissionsConsultatives, mainStep: true },
FAIRE_SAISINE_COMMISSION_DEPARTEMENTALE_DES_MINES: { db: ETES.saisineDeLaCommissionDepartementaleDesMines_CDM_, mainStep: false },
Expand Down Expand Up @@ -178,7 +176,7 @@ interface AxmContext extends CaminoCommonContext {
publicationDecisionsRecueilActesAdministratifsFaite: boolean
publicationDansUnJournalLocalOuNationalFaite: boolean
daeRequiseOuDemandeDeposee: boolean
saisineDesCollectivitesLocalesFaite: boolean
avisDesCollectivitesFaite: boolean
avisDesServicesEtCommissionsConsultatives: RendreAvisDesServicesEtCommissonsConsultatives
}

Expand All @@ -198,7 +196,7 @@ const axmOctMachine = createMachine({
notificationDesCollectivitesLocalesFaite: false,
publicationDecisionsRecueilActesAdministratifsFaite: false,
publicationDansUnJournalLocalOuNationalFaite: false,
saisineDesCollectivitesLocalesFaite: false,
avisDesCollectivitesFaite: false,
avisDesServicesEtCommissionsConsultatives: { faite: false },
daeRequiseOuDemandeDeposee: false,
visibilite: 'confidentielle',
Expand Down Expand Up @@ -332,7 +330,7 @@ const axmOctMachine = createMachine({
rendreAvisDrealPasEncorePossible: {
always: {
target: 'rendreAvisDrealAFaire',
guard: ({ context }) => context.avisDesServicesEtCommissionsConsultatives.faite && context.saisineDesCollectivitesLocalesFaite,
guard: ({ context }) => context.avisDesServicesEtCommissionsConsultatives.faite && context.avisDesCollectivitesFaite,
},
},
rendreAvisDrealAFaire: {
Expand Down Expand Up @@ -361,23 +359,20 @@ const axmOctMachine = createMachine({
},
},
},
saisineCollectivitesLocalesMachine: {
initial: 'saisineCollectivitesLocalesAFaire',
avisDesCollectivitesMachine: {
initial: 'avisDesCollectivitesARendre',
states: {
saisineCollectivitesLocalesAFaire: {
avisDesCollectivitesARendre: {
on: {
FAIRE_SAISINE_COLLECTIVITES_LOCALES: {
target: 'avisDesCollectivitesARendre',
guard: ({ context }) => !context.saisineDesCollectivitesLocalesFaite,
RENDRE_AVIS_DES_COLLECTIVITES: {
target: 'avisDesCollectivitesRendu',
guard: ({ context }) => !context.avisDesCollectivitesFaite,
actions: assign({
saisineDesCollectivitesLocalesFaite: true,
avisDesCollectivitesFaite: true,
}),
},
},
},
avisDesCollectivitesARendre: {
on: { RENDRE_AVIS_DES_COLLECTIVITES: 'avisDesCollectivitesRendu' },
},
avisDesCollectivitesRendu: { type: 'final' },
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('vérifie l’arbre de prolongation d’AXM', () => {
'DEMANDER_INFORMATION_POUR_AVIS_DREAL',
'FAIRE_CLASSEMENT_SANS_SUITE',
'FAIRE_DESISTEMENT_DEMANDEUR',
'FAIRE_SAISINE_COLLECTIVITES_LOCALES',
'RENDRE_AVIS_DE_COLLECTIVITES',
'RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES',
'RENDRE_DECISION_IMPLICITE_REJET',
])
Expand Down
27 changes: 11 additions & 16 deletions packages/api/src/business/rules-demarches/axm/pro.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ type AXMProXStateEvent =
| { type: 'FAIRE_RECEVABILITE_DEMANDE_FAVORABLE' }
| { type: 'FAIRE_RECEVABILITE_DEMANDE_DEFAVORABLE' }
| { type: 'MODIFIER_LA_DEMANDE' }
| { type: 'FAIRE_SAISINE_COLLECTIVITES_LOCALES' }
| { type: 'RENDRE_AVIS_DE_COLLECTIVITES' }
| RendreAvisDreal
| RendreAvisDesServicesEtCommissionsConsultatives
Expand Down Expand Up @@ -54,8 +53,7 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
DEMANDER_COMPLEMENTS_POUR_RECEVABILITE: { db: ETES.demandeDeComplements_RecevabiliteDeLaDemande_, mainStep: false },
RECEVOIR_COMPLEMENTS_POUR_RECEVABILITE: { db: ETES.receptionDeComplements_RecevabiliteDeLaDemande_, mainStep: false },
MODIFIER_LA_DEMANDE: { db: ETES.modificationDeLaDemande, mainStep: true },
FAIRE_SAISINE_COLLECTIVITES_LOCALES: { db: ETES.saisineDesCollectivitesLocales, mainStep: true },
RENDRE_AVIS_DE_COLLECTIVITES: { db: ETES.avisDesCollectivites, mainStep: false },
RENDRE_AVIS_DE_COLLECTIVITES: { db: ETES.avisDesCollectivites, mainStep: true },
RENDRE_AVIS_DREAL: { db: ETES.rapportEtAvisDeLaDREAL, mainStep: true },
RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES: { db: ETES.avisDesServicesEtCommissionsConsultatives, mainStep: true },
FAIRE_SAISINE_COMMISSION_DEPARTEMENTALE_DES_MINES: { db: ETES.saisineDeLaCommissionDepartementaleDesMines_CDM_, mainStep: false },
Expand Down Expand Up @@ -143,7 +141,7 @@ export class AxmProMachine extends CaminoMachine<AxmProContext, AXMProXStateEven

type AvisDesServicesEtCommissionsConsultatives = { faite: false } | { faite: true; date: CaminoDate }
interface AxmProContext extends CaminoCommonContext {
saisineDesCollectivitesLocalesFaite: boolean
avisDesCollectivitesFaite: boolean
avisDesServicesEtCommissionsConsultatives: AvisDesServicesEtCommissionsConsultatives
notificationDuDemandeurFaite: boolean
notificationDesCollectivitesLocalesFaite: boolean
Expand All @@ -166,7 +164,7 @@ const axmProMachine = createMachine({
notificationDesCollectivitesLocalesFaite: false,
publicationDecisionsRecueilActesAdministratifsFaite: false,
publicationDansUnJournalLocalOuNationalFaite: false,
saisineDesCollectivitesLocalesFaite: false,
avisDesCollectivitesFaite: false,
avisDesServicesEtCommissionsConsultatives: { faite: false },
visibilite: 'confidentielle',
},
Expand Down Expand Up @@ -246,7 +244,7 @@ const axmProMachine = createMachine({
rendreAvisDrealPasEncorePossible: {
always: {
target: 'rendreAvisDrealAFaire',
guard: ({ context }) => context.avisDesServicesEtCommissionsConsultatives.faite && context.saisineDesCollectivitesLocalesFaite,
guard: ({ context }) => context.avisDesServicesEtCommissionsConsultatives.faite && context.avisDesCollectivitesFaite,
},
},
rendreAvisDrealAFaire: {
Expand Down Expand Up @@ -275,23 +273,20 @@ const axmProMachine = createMachine({
},
},
},
saisineCollectivitesLocalesMachine: {
initial: 'saisineCollectivitesLocalesAFaire',
avisDesCollectivitesMachine: {
initial: 'avisDesCollectivitesARendre',
states: {
saisineCollectivitesLocalesAFaire: {
avisDesCollectivitesARendre: {
on: {
FAIRE_SAISINE_COLLECTIVITES_LOCALES: {
target: 'avisDesCollectivitesARendre',
guard: ({ context }) => !context.saisineDesCollectivitesLocalesFaite,
RENDRE_AVIS_DE_COLLECTIVITES: {
target: 'avisDesCollectivitesRendu',
guard: ({ context }) => !context.avisDesCollectivitesFaite,
actions: assign({
saisineDesCollectivitesLocalesFaite: true,
avisDesCollectivitesFaite: true,
}),
},
},
},
avisDesCollectivitesARendre: {
on: { RENDRE_AVIS_DE_COLLECTIVITES: 'avisDesCollectivitesRendu' },
},
avisDesCollectivitesRendu: { type: 'final' },
},
},
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ describe('vérifie l’arbre d’octroi de PRM', () => {
ETES.avisDeMiseEnConcurrenceAuJORF.FAIT,
{ ...ETES.participationDuPublic.TERMINE, addDays: 31 },
ETES.avisDesServicesEtCommissionsConsultatives.FAIT,
ETES.saisineDesCollectivitesLocales.FAIT,
ETES.avisDesCollectivites.FAIT,
{ ...ETES.avisDeLaCommissionDepartementaleDesMines_CDM_.FAVORABLE, addDays: 31 },
ETES.rapportEtAvisDeLaDREAL.FAVORABLE,
Expand All @@ -66,7 +65,6 @@ describe('vérifie l’arbre d’octroi de PRM', () => {
ETES.receptionDeComplements_RecevabiliteDeLaDemande_.FAIT,
ETES.recevabiliteDeLaDemande.FAVORABLE,
ETES.avisDesServicesEtCommissionsConsultatives.FAIT,
ETES.saisineDesCollectivitesLocales.FAIT,
{ ...ETES.avisDeLaCommissionDepartementaleDesMines_CDM_.FAVORABLE, addDays: 31 },
ETES.rapportEtAvisDeLaDREAL.FAVORABLE,
ETES.avisDuPrefet.FAVORABLE,
Expand Down
13 changes: 3 additions & 10 deletions packages/api/src/business/rules-demarches/prm/oct.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ type XStateEvent =
| RendreAvisCDM
| RendreRapportDREAL
| { type: 'RENDRE_AVIS_PREFET' }
| { type: 'FAIRE_SAISINE_DES_COLLECTIVITES_LOCALES' }
| { type: 'RENDRE_AVIS_DES_COLLECTIVITES' }
| { type: 'FAIRE_SAISINE_CONSEIL_GENERAL_CHARGE_DES_MINES' }
| { type: 'FAIRE_RAPPORT_CONSEIL_GENERAL_CHARGE_DES_MINES' }
Expand Down Expand Up @@ -106,7 +105,6 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
RENDRE_AVIS_CDM: { db: EtapesTypesEtapesStatuts.avisDeLaCommissionDepartementaleDesMines_CDM_, mainStep: true },
RENDRE_RAPPORT_DREAL: { db: EtapesTypesEtapesStatuts.rapportEtAvisDeLaDREAL, mainStep: true },
RENDRE_AVIS_PREFET: { db: EtapesTypesEtapesStatuts.avisDuPrefet, mainStep: true },
FAIRE_SAISINE_DES_COLLECTIVITES_LOCALES: { db: EtapesTypesEtapesStatuts.saisineDesCollectivitesLocales, mainStep: true },
RENDRE_AVIS_DES_COLLECTIVITES: { db: EtapesTypesEtapesStatuts.avisDesCollectivites, mainStep: true },
FAIRE_SAISINE_CONSEIL_GENERAL_CHARGE_DES_MINES: { db: EtapesTypesEtapesStatuts.saisineDuConseilGeneralDeLeconomie_CGE_, mainStep: true },
FAIRE_RAPPORT_CONSEIL_GENERAL_CHARGE_DES_MINES: { db: EtapesTypesEtapesStatuts.rapportDuConseilGeneralDeLeconomie_CGE_, mainStep: true },
Expand Down Expand Up @@ -341,19 +339,14 @@ const prmOctMachine = createMachine({
saisinesMachine: {
type: 'parallel',
states: {
saisineDesCollectivitesLocalesMachine: {
initial: 'saisineDesCollectivitesLocalesAFaire',
avisDesCollectivitesMachine: {
initial: 'avisDesCollectivitesARendre',
states: {
saisineDesCollectivitesLocalesAFaire: {
avisDesCollectivitesARendre: {
always: {
guard: ({ context }) => !isGuyane(context.paysId),
target: 'done',
},
on: {
FAIRE_SAISINE_DES_COLLECTIVITES_LOCALES: 'avisDesCollectivitesARendre',
},
},
avisDesCollectivitesARendre: {
on: {
RENDRE_AVIS_DES_COLLECTIVITES: 'done',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
{ id: etapeIdValidator.parse('idMcr'), typeId: 'mcr', statutId: 'fav', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2022-11-17'), ordre: 4 },
{ id: etapeIdValidator.parse('idAnf'), typeId: 'anf', statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2022-11-17'), ordre: 5 },
{ id: etapeIdValidator.parse('idAsc'), typeId: 'asc', statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2022-11-17'), ordre: 6 },
{ id: etapeIdValidator.parse('idScl'), typeId: 'scl', statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2022-11-17'), ordre: 7 },
{ id: etapeIdValidator.parse('idAdc'), typeId: 'adc', statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2022-11-17'), ordre: 7 },
{ id: etapeIdValidator.parse('idApo'), typeId: 'apo', statutId: 'fav', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2023-02-08'), ordre: 8 },
]
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* eslint-disable no-restricted-syntax */
/* eslint-disable sql/no-unsafe-query */

import { DemarcheId } from 'camino-common/src/demarche'
import { EtapeDocumentId, EtapeId } from 'camino-common/src/etape'
import { DocumentTypeId, DocumentsTypes } from 'camino-common/src/static/documentsTypes'
import { Knex } from 'knex'
import { LargeObjectId } from '../../database/largeobjects'
import { isNotNullNorUndefinedNorEmpty, isNullOrUndefined } from 'camino-common/src/typescript-tools'
import { CaminoDate } from 'camino-common/src/date'

export const up = async (knex: Knex): Promise<void> => {
const etapes: { rows: { id: EtapeId; titre_demarche_id: DemarcheId; archive: boolean; date: CaminoDate }[] } = await knex.raw(
`SELECT id, titre_demarche_id, archive, date FROM titres_etapes WHERE type_id = 'scl'`
)

type EtapeDocumentRow = {
id: EtapeDocumentId
etape_document_type_id: DocumentTypeId
etape_id: EtapeId
largeobject_id: LargeObjectId
}
const etapesDocuments: { rows: EtapeDocumentRow[] } = await knex.raw(
`SELECT id, etape_document_type_id, etape_id, largeobject_id
FROM etapes_documents
WHERE etape_id = ANY(?)`,
[etapes.rows.map(({ id }) => id)]
)
const demarchesAvecAdc: { rows: { id: EtapeId; titre_demarche_id: DemarcheId }[] } = await knex.raw(
`SELECT titre_demarche_id, id
FROM titres_etapes
WHERE type_id = 'adc' AND titre_demarche_id = ANY(?)`,
[etapes.rows.map(({ titre_demarche_id }) => titre_demarche_id)]
)

const indexDesDemarchesAvecAdc = demarchesAvecAdc.rows.reduce<Record<DemarcheId, EtapeId>>((acc, row) => {
acc[row.titre_demarche_id] = row.id

return acc
}, {})
const indexDesDocuments = etapesDocuments.rows.reduce<Record<EtapeId, EtapeDocumentRow[]>>((acc, row) => {
if (isNullOrUndefined(acc[row.etape_id])) {
acc[row.etape_id] = []
}

acc[row.etape_id].push(row)

return acc
}, {})

const etapesASupprimer: EtapeId[] = []
for (let i = 0; i < etapes.rows.length; i += 1) {
const etape = etapes.rows[i]

let etapeIdDesAvis = etape.id
if (etape.archive || isNullOrUndefined(indexDesDemarchesAvecAdc[etape.titre_demarche_id])) {
await knex.raw(`UPDATE titres_etapes SET type_id = 'adc' WHERE id = ?`, [etape.id])
} else {
etapeIdDesAvis = indexDesDemarchesAvecAdc[etape.titre_demarche_id]
etapesASupprimer.push(etape.id)
}

if (isNotNullNorUndefinedNorEmpty(indexDesDocuments[etape.id])) {
await Promise.all(
indexDesDocuments[etape.id].map(document =>
knex.raw(
`INSERT INTO etape_avis (id, avis_type_id, avis_statut_id, avis_visibility_id, etape_id, description, date, largeobject_id) VALUES (?, 'avisDUneCollectivite', 'Non renseigné', 'Administrations', ?, ?, ?, ?)`,
[document.id, etapeIdDesAvis, DocumentsTypes[document.etape_document_type_id].nom, etape.date, document.largeobject_id]
)
)
)
}
}

await knex.raw('DELETE FROM etapes_documents WHERE id = ANY(?)', [etapesDocuments.rows.map(({ id }) => id)])
await knex.raw('DELETE FROM titres_etapes WHERE id = ANY(?)', [etapesASupprimer])
}

export const down = (): void => {}
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,6 @@ const AdministrationsTitresTypesEtapesTypes: {
[ETAPES_TYPES.receptionDinformation]: { lectureInterdit: false, creationInterdit: false, modificationInterdit: false },
[ETAPES_TYPES.publicationDeDecisionAuRecueilDesActesAdministratifs]: { lectureInterdit: false, creationInterdit: true, modificationInterdit: true },
[ETAPES_TYPES.saisineDeLautoriteSignataire]: { lectureInterdit: false, creationInterdit: true, modificationInterdit: true },
[ETAPES_TYPES.saisineDesCollectivitesLocales]: { lectureInterdit: false, creationInterdit: true, modificationInterdit: true },
[ETAPES_TYPES.saisineDeLaCommissionDepartementaleDesMines_CDM_]: { lectureInterdit: false, creationInterdit: true, modificationInterdit: true },
},
[TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX]: {
Expand Down
1 change: 0 additions & 1 deletion packages/common/src/static/documentsTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export const DOCUMENTS_TYPES_IDS = {
arreteMinisteriel: 'arm',
arretePrefectoral: 'arp',
arrete: 'arr',

attestationFiscale: 'atf',
avisDeMiseEnConcurrence: 'avc',
avenant: 'ave',
Expand Down
Loading

0 comments on commit c177c80

Please sign in to comment.