npm package: @fibre44/dsn-parser
Description: Un parser pour la Déclaration Sociale Nominative
Author: DENIS Nicolas
Latest version: 1.1.0

# DSN Parser #

*******
Table des matières  

* [Description](#description)
* [Installation](#instal)
* [Exemple](#example)

*******

<div id='description'>  

## Description ##

Cette librairie permet d'extraire les données d'un fichier au format de la Déclaration Sociale Nominative (DSN). 

La librairie se base sur le [cahier technique 2023 ](https://www.net-entreprises.fr/media/documentation/dsn-cahier-technique-2023.1.pdf "norme DSN 2022"). Le parser est capable de gérer les normes :
* 2022
* 2023

## Tableau récapitulatif des données exportées ##

| Bloc       | Libellé                                                                                    | Méthode                                 | Commentaire |
| ---------- | ------------------------------------------------------------------------------------------ | --------------------------------------- | -------     |
| S10.G00.00 | Entête                                                                                     | [Méthode Dsn](#dsn)                     |         |
| S10.G00.01 | Emetteur                                                                                   | [Méthode Emetteur](#sender)                     |         |
| S10.G00.01 | Contact Emetteur                                                                           | [Méthode Emetteur](#contactSender)                     |         |
| S20.G00.05 | Déclaration                                                                                | [Méthode statement](#contact)                                        |           |
| S20.G00.06 | Entreprise                                                                                 | [Méthode Society](#contact)             ||
| S20.G00.07 | Contact chez le déclaré                                                                    | [Méthode contact](#contact)             ||
| S20.G00.08 | Identifiant de l'organisme destinataire                                                    |Non géré                                | En cours de développement         |
| S21.G00.06 | Entreprise                                                                                 | [Méthode Society](#society)             |          |
| S21.G00.11 | Etablissement                                                                              | [Méthode Establishment](#establishment) |          |
| S21.G00.12 | Coordonnées bancaires spécifiques                                                          | specificBankDetails                     | En cours de développemet         |
| S21.G00.13 | Complément OETH                                                                            | complementOETH                                | En cours de développemet         |
| S21.G00.15 | Adhésion Prévoyance                                                                        | [Méthode Mutual](#mutual)               |          |
| S21.G00.16 | Changements destinataire Adhésion Prévoyance                                               | Non géré                                | En cours de développemet         |
| S21.G00.20 | Versement organisme de protection sociale                                                  | SocialPayment                               |          |
| S21.G00.22 | Bordereau de cotisation due                                                                | Non géré                                | En cours de developpement         |
| S21.G00.23 | Cotisation agrégée                                                                         | [Méthode cotisations](#aggregate)       | En cours de developpement         |
| S21.G00.30 | Individu                                                                                   | [Méthode Employee](#employee)           |          |
| S21.G00.34 | Compte Professionnel de Prévention (Ex-Pénibilité)                                         | Non géré                                |En cours de développement         |
| S21.G00.40 | Contrat (contrat de travail, convention, mandat)                                           | [Méthode WorkContract](#workContract)   |         |
| S21.G00.41 | Changements Contrat                                                                        |[Méthode WorkContract](#workContract)    |          |
| S21.G00.44 | Assujettissement fiscal                                                                    | Non géré                                |En cours de développement           |
| S21.G00.45 | Données précédemment déclarées                                                             | Non géré                                |En cours de développement           |
| S21.G00.50 | Versement individu                                                                         | Non géré                                |En cours de développement           |
| S21.G00.51 | Rémunération                                                                               | Non géré                                |En cours de développement           |
| S21.G00.52 | Prime, gratification et indemnité                                                          | Non géré                                |En cours de développement           |
| S21.G00.54 | Autre élément de revenu brut                                                               | Non géré                                |En cours de développement           |
| S21.G00.55 | Composant de versement                                                                     | Non géré                                |En cours de développement        |
| S21.G00.56 | Régularisation de prélèvement à la source                                                  | Non géré                                |En cours de développement           |
| S21.G00.56 | Arrêt de travail                                                                           |[Méthode Arret de travail](#workStopping)|           |
| S21.G00.62 | Fin du contrat                                                                             | Non géré                                |En cours de développement        |
| S21.G00.63 | Préavis de fin de contrat                                                                  | Non géré                                |En cours de développement           |
| S21.G00.65 | Autre suspension de l'exécution du contrat                                                 | Non géré                                |En cours de développement           |
| S21.G00.66 | Temps partiel Thérapeutique                                                                | Non géré                                |En cours de développement           |
| S21.G00.70 | Affiliation Prévoyance                                                                     |[Méthode MutuelEmployee](#mutualEmployee)|      |
| S21.G00.71 | Retraite complémentaire                                                                    | Non géré                                |En cours de développement                                         |
| S21.G00.72 | Affiliation à tort à un régime de retraite                                                 | Non géré                                |En cours de développement           |
| S21.G00.73 | Ayant-droit                                                                                | Non géré                                |En cours de développement           |
| S21.G00.78 | Base assujettie                                                                            | Non géré                                |En cours de développement           |
| S21.G00.79 | Composant de base assujettie                                                               | Non géré                                |En cours de développement            |
| S21.G00.81 | Cotisation individuelle                                                                    | Non géré                                |En cours de développement           |
| S21.G00.82 | Cotisation établissement                                                                   | Non géré                                |En cours de développement           |
| S21.G00.83 | Période d'affiliation à tort à un régime de retraite complémentaire                        | Non géré                                |En cours de développement           |
| S21.G00.84 | Base assujettie déclarée à tort pour un régime de retraite complémentaire                  | Non géré                                |En cours de développement           |
| S21.G00.85 | Lieu de travail ou établissement utilisateur                                               | Non géré                                |En cours de développement           |
| S21.G00.86 | Ancienneté                                                                                 | Non géré                                |En cours de développement           |
| S21.G00.95 | Base assujettie déclarée à tort pour un régime de base risque maladie, AT/MP ou vieillesse | Non géré                                |En cours de développement           |
| S21.G00.98 | Saisie administrative à tiers détenteur                                                    | Non géré                                |En cours de développement           |

<div id='instal'>  


## Installation ##

```bash
    npm i @fibre44/dsn-parser
```
<div id='example'>  


## Exemples d'utilisation ##

Exemple dans un composant React avec le framework next Js.

```jsx
import { DsnParser } from "@fibre44/dsn-parser";
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';


export default function UploadFileDsn() {
    const router = useRouter()
    const addDSnData: Dsn[] = []

    const [loading, setLoading] = useState(false)
    const [progress, setProgress] = useState(0)
    const parseFile = async (file: File, random: string) => {
        return new Promise((resolve, reject) => {
            const dsnRows: any = []
            const dsnRowsObject: { id: string, value: string }[] = []
            const reader = new FileReader()
            reader.readAsText(file, 'ISO-8859-1');
            reader.onload = function (e: any) {
                // Le contenu du fichier est dans e.target.result
                dsnRows.splice(0, dsnRows.length)
                //On récupère le texte dans la variable dsnRows
                if (e.target && e.target.result) {
                    const text = e.target.result as string; //Une structure DSN ressemble à ca S10.G00.00.003,'11.0.9.0.2'
                    const lines = text.split('\n'); //On split le texte en lignes
                    dsnRows.push(...lines);
                    for (const row of dsnRows) {
                        let lineSplit = row.split(`,'`) //On split chaque ligne en colonnes
                        let id = lineSplit.at(0)
                        let value = lineSplit.at(1).replace(/'/g, "").replace(/\r/g, "")
                        dsnRowsObject.push({
                            id,
                            value
                        });
                    }
                }
                resolve(dsnRowsObject);

            }//Fin boucle lecture
            reader.onerror = function (e) {
                reject(new Error("Erreur de lecture du fichier : " + e));
            };
        })
    }
    const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault()
        setLoading(true)
        const dsn = (e.target as HTMLFormElement).elements[0] as HTMLInputElement
        const files = dsn.files ? Array.from(dsn.files) : []
        for (let file of files) {
            const random = Math.random().toString(36).substring(7)
            const dsnRows = await parseFile(file, random) as { id: string, value: string }[]
            addDSnData.push({ dsnId: random, dsnRows: dsnRows })
        }

        try {
            let totalFiles = files.length
            let progressIncrement = 0
            for (const dsn of addDSnData) {
                progressIncrement = progressIncrement + 1
                setProgress(() => progressIncrement / totalFiles * 100)
                const extraction = await extractionData(dsn)
                //uploadFileDsn is server action
                const action = await uploadFileDsn({
                    dsnData: extraction
                }
                )
                if (action?.serverError) {
                    setLoading(false);
                    toast(`${action.serverError}`, {
                        description: new Date().toLocaleDateString(),
                        action: {
                            label: "fermer",
                            onClick: () => console.log("fermeture"),
                        },
                    });
                }
            }

        } catch (err) {
            setLoading(false);
            toast(`${err}`, {
                description: new Date().toLocaleDateString(),
                action: {
                    label: "fermer",
                    onClick: () => console.log("fermeture"),
                },
            });
            console.error(err);
        }
        router.push(`/project/`)
        setLoading(false);

    }

    const extractionData = async (dsnData: Dsn): Promise<ExtractionDsn> => {
        let dsnId = dsnData.dsnId
        const parser = new DsnParser(dsnData.dsnRows)
        const dsnDetail = parser.dsn
        const society = parser.society
        const establishment = parser.establishment
        const bank = parser.bank
        const jobs = parser.job
        const idcc = parser.idcc
        const employees = parser.employees
        const workContracts = parser.workContracts
        const mutuals = parser.mutual
        const mutualEmployees = parser.mutualEmployee
        return {
            dsnId: dsnId,
            dsn: dsnDetail,
            society: society,
            establishment: establishment,
            jobs: jobs,
            idcc: idcc,
            employees: employees,
            workContracts: workContracts,
            mutuals: mutuals,
            mutualEmployees: mutualEmployees
        }
    }

    return (
        <form onSubmit={handleSubmit}>
            <Label htmlFor="dsn">DSN</Label>
            <Input id="dsn" name="dsn" type="file" accept=".dsn" required multiple />
            {!loading && <Button type="submit">Envoyer</Button>}
            {loading && <Progress value={progress} />}
        </form>
    )
}
```
## Les options ##
Fichier d'option par default.
 ```javascript
  options = {
        controleDsnVersion: true,//Controle que le fichier utilise bien la dernière norme de la DSN
        deleteFile: false //Autorise la suppression du fichier après le traitement
    }
 ```