Table des matières
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 . Le parser est capable de gérer les normes :
- 2022
- 2023
Bloc | Libellé | Méthode | Commentaire |
---|---|---|---|
S10.G00.00 | Entête | Méthode Dsn | |
S10.G00.01 | Emetteur | Méthode Emetteur | |
S10.G00.01 | Contact Emetteur | Méthode Emetteur | |
S20.G00.05 | Déclaration | Méthode statement | |
S20.G00.06 | Entreprise | Méthode Society | |
S20.G00.07 | Contact chez le déclaré | Méthode contact | |
S20.G00.08 | Identifiant de l'organisme destinataire | Non géré | En cours de développement |
S21.G00.06 | Entreprise | Méthode Society | |
S21.G00.11 | Etablissement | Méthode Establishment | |
S21.G00.12 | Coordonnées bancaires spécifiques | specificBankDetails | En cours de développemet |
S21.G00.13 | Complément OETH | complementOETH | En cours de développemet |
S21.G00.15 | Adhésion Prévoyance | Méthode Mutual | |
S21.G00.16 | Changements destinataire Adhésion Pré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 agrégée | Méthode cotisations | En cours de developpement |
S21.G00.30 | Individu | Méthode Employee | |
S21.G00.34 | Compte Professionnel de Prévention (Ex-Pénibilité) | Non géré | En cours de développement |
S21.G00.40 | Contrat (contrat de travail, convention, mandat) | Méthode WorkContract | |
S21.G00.41 | Changements Contrat | Méthode WorkContract | |
S21.G00.44 | Assujettissement fiscal | Non géré | En cours de développement |
S21.G00.45 | Données précédemment déclaré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 | Rémunération | Non géré | En cours de développement |
S21.G00.52 | Prime, gratification et indemnité | Non géré | En cours de développement |
S21.G00.54 | Autre élé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 | Régularisation de prélèvement à la source | Non géré | En cours de développement |
S21.G00.56 | Arrêt de travail | Méthode Arret de travail | |
S21.G00.62 | Fin du contrat | Non géré | En cours de développement |
S21.G00.63 | Préavis de fin de contrat | Non géré | En cours de développement |
S21.G00.65 | Autre suspension de l'exécution du contrat | Non géré | En cours de développement |
S21.G00.66 | Temps partiel Thérapeutique | Non géré | En cours de développement |
S21.G00.70 | Affiliation Prévoyance | Méthode MutuelEmployee | |
S21.G00.71 | Retraite complémentaire | Non géré | En cours de développement |
S21.G00.72 | Affiliation à tort à un ré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 établissement | Non géré | En cours de développement |
S21.G00.83 | Période d'affiliation à tort à un régime de retraite complémentaire | Non géré | En cours de développement |
S21.G00.84 | Base assujettie déclarée à tort pour un régime de retraite complémentaire | Non géré | En cours de développement |
S21.G00.85 | Lieu de travail ou établissement utilisateur | Non géré | En cours de développement |
S21.G00.86 | Ancienneté | Non géré | En cours de développement |
S21.G00.95 | Base assujettie déclarée à tort pour un régime de base risque maladie, AT/MP ou vieillesse | Non géré | En cours de développement |
S21.G00.98 | Saisie administrative à tiers détenteur | Non géré | En cours de développement |
npm i @fibre44/dsn-parser
Exemple dans un composant React avec le framework next Js.
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>
)
}
Fichier d'option par default.
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
}