Sist endret: 10. nov. 2024

Dataprosessering

Hvordan legge til kalkuleringer og annen dataprosessering?

Dataprosessering kjøres på serveren, og er basert på input fra sluttbruker/skjemadata. Dataprosessering kan være kan være rent matematiske kalkuleringer, det kan også være å overføre verdier mellom felter, resultater av API-kall, osv.

Dataprosessering kjøres hver gang data lagres, og dermed hver gang en bruker har gjort en endring.

For å sikre optimal opplevelse og kontroll er applikasjonstemplaten to forskjellige hendelser hvor logikk kan plasseres.

  • ProcessDataWrite kjøres når data lagres
  • ProcessDataRead kjøres når data leses fra databasen
VIKTIG
For versjon 4-7: Når en dataprosessering som har oppdatert dataene på server er kjørt, må front-end få beskjed om dette sånn at de oppdaterte dataene kan lastes inn. For at det skal skje, må ProcessDataWrite-metoden returnere true om det er noen av dataene som har blitt oppdatert. Hvis dette ikke gjøres, vil de oppdaterte dataen ikke være synlig for sluttbruker før de ev. laster inn siden på nytt.

Fra og med versjon 8 trenger du ikke returnere noe fra ProcessDataWrite. For å oppdatere dataen trenger du bare å endre på dataen som kommer inn til metoden, som før.
    1. Opprett en klasse som implementerer IDataProcessor grensesnittet som ligger i Altinn.App.Core.Features.DateProcessing navnerommet.
      Du kan navngi og plassere filene i den mappestrukturen du selv ønsker i prosjektet ditt. Men vi anbefaler at du benytter meningsfulle navnerom som i et hvilket som helst annet .Net prosjekt. Eksempel på kode fra app som prosesserer og populerer forskjellige data under lagring.

      public async Task<bool> ProcessDataWrite(Instance instance, Guid? dataId, object data, object? previousData, string? language)
      {
          if (data is SoknadUnntakKaranteneHotellVelferd model)
          {
              string org = instance.Org;
              string app = instance.AppId.Split("/")[1];
              int partyId = int.Parse(instance.InstanceOwner.PartyId);
              Guid instanceGuid = Guid.Parse(instance.Id.Split("/")[1]);
      
              // handling mapping of multiple choice velferdsgrunner
              if (!string.IsNullOrEmpty(model.velferdsgrunner?.sammenstilling))
              {
                  model.velferdsgrunner.helseproblemer = model.velferdsgrunner.sammenstilling.Contains("helseproblemer");
                  model.velferdsgrunner.barnefodsel = model.velferdsgrunner.sammenstilling.Contains("barnefodsel");
                  model.velferdsgrunner.begravelse = model.velferdsgrunner.sammenstilling.Contains("begravelse");
                  model.velferdsgrunner.naerstaaende = model.velferdsgrunner.sammenstilling.Contains("naerstaaende");
                  model.velferdsgrunner.adopsjon = model.velferdsgrunner.sammenstilling.Contains("adopsjon");
                  model.velferdsgrunner.sarligeOmsorg = model.velferdsgrunner.sammenstilling.Contains("sarligeOmsorg");
                  model.velferdsgrunner.barnAlene = model.velferdsgrunner.sammenstilling.Contains("barnAlene");
                  model.velferdsgrunner.hjemmeeksamen = model.velferdsgrunner.sammenstilling.Contains("hjemmeeksamen");
                  model.velferdsgrunner.arbeidunntak = model.velferdsgrunner.sammenstilling.Contains("arbeidunntak");
                  model.velferdsgrunner.andreVelferdshensyn = model.velferdsgrunner.sammenstilling.Contains("annet");
                  model.velferdsgrunner.andreVelferdshensynBeskrivelse = model.velferdsgrunner.sammenstilling.Contains("annet") ? model.velferdsgrunner.andreVelferdshensynBeskrivelse : null;
              }
              else
              {
                  model.velferdsgrunner = null;
              }
      
              // set data for receipt if not set
              if (string.IsNullOrEmpty(model.applogic?.altinnRef))
              {
                  model.applogic ??= new Applogic();
      
                  Party party = await _registerService.GetParty(
                      int.Parse(instance.InstanceOwner.PartyId));
                  model.applogic.avsender =
                      $"{instance.InstanceOwner.PersonNumber}-{party.Name}";
                  model.applogic.altinnRef = instance.Id.Split("-")[4];
              }
          }
      }
      
    2. Registrer din implementering i Program.cs klassen

      services.AddTransient<IDataProcessor, DataProcessor>();
      

      Dette sørger for at din kode er kjent for applikasjonen og at koden blir kjørt når den skal.

    I versjon 7 har vi endret måten preutfylling med egendefinert kode gjøres på. Vi benytter nå dependency injection i stedet for overstyring av metoder. Hvis du tidligere plasserte koden din i ProcessDataRead og ProcessDataWrite metodene in DataProcessingHandler.cs klassen så vil du erfare at det er mer eller mindre det samme som nå gjøres.

    1. Opprett en klasse som implementerer IDataProcessor grensesnittet som ligger i Altinn.App.Core.Features.DateProcessing navnerommet. Du kan navngi og plassere filene i den mappestrukturen du selv ønsker i prosjektet ditt. Men vi anbefaler at du benytter meningsfulle navnerom som i et hvilket som helst annet .Net prosjekt. Eksempel på kode fra app som prosesserer og populerer forskjellige data under lagring.

      public async Task<bool> ProcessDataWrite(
          Instance instance, Guid? dataId, object data)
      {
          bool edited = false;
      
          if (data is SoknadUnntakKaranteneHotellVelferd model)
          {
              string org = instance.Org;
              string app = instance.AppId.Split("/")[1];
              int partyId = int.Parse(instance.InstanceOwner.PartyId);
              Guid instanceGuid = Guid.Parse(instance.Id.Split("/")[1]);
      
              // handling mapping of multiple choice velferdsgrunner
              if (!string.IsNullOrEmpty(model.velferdsgrunner?.sammenstilling))
              {
                  model.velferdsgrunner.helseproblemer = model.velferdsgrunner.sammenstilling.Contains("helseproblemer");
                  model.velferdsgrunner.barnefodsel = model.velferdsgrunner.sammenstilling.Contains("barnefodsel");
                  model.velferdsgrunner.begravelse = model.velferdsgrunner.sammenstilling.Contains("begravelse");
                  model.velferdsgrunner.naerstaaende = model.velferdsgrunner.sammenstilling.Contains("naerstaaende");
                  model.velferdsgrunner.adopsjon = model.velferdsgrunner.sammenstilling.Contains("adopsjon");
                  model.velferdsgrunner.sarligeOmsorg = model.velferdsgrunner.sammenstilling.Contains("sarligeOmsorg");
                  model.velferdsgrunner.barnAlene = model.velferdsgrunner.sammenstilling.Contains("barnAlene");
                  model.velferdsgrunner.hjemmeeksamen = model.velferdsgrunner.sammenstilling.Contains("hjemmeeksamen");
                  model.velferdsgrunner.arbeidunntak = model.velferdsgrunner.sammenstilling.Contains("arbeidunntak");
                  model.velferdsgrunner.andreVelferdshensyn = model.velferdsgrunner.sammenstilling.Contains("annet");
                  model.velferdsgrunner.andreVelferdshensynBeskrivelse = model.velferdsgrunner.sammenstilling.Contains("annet") ? model.velferdsgrunner.andreVelferdshensynBeskrivelse : null;
      
                  edited = true;
              }
              else
              {
                  model.velferdsgrunner = null;
              }
      
              // set data for receipt if not set
              if (string.IsNullOrEmpty(model.applogic?.altinnRef))
              {
                  model.applogic ??= new Applogic();
      
                  Party party = await _registerService.GetParty(
                      int.Parse(instance.InstanceOwner.PartyId));
                  model.applogic.avsender =
                      $"{instance.InstanceOwner.PersonNumber}-{party.Name}";
                  model.applogic.altinnRef = instance.Id.Split("-")[4];
              }
          }
      
          return await Task.FromResult(edited);
      }
      
    2. Registrer din implementering i Program.cs klassen

      services.AddTransient<IDataProcessor, DataProcessor>();
      

      Dette sørger for at din kode er kjent for applikasjonen og at koden blir kjørt når den skal.

    Dataprosessering kodes i C#, i filen DataProsessingHandler.cs. Denne filen kan redigeres enklest ved å laste ned kildekoden til app’en og redigere på egen maskin, f.eks. i Visual Studio Code. Datamodellen med skjemadata er tilgjengelig og kan redigeres/oppdateres etter ønske/behov.

    Eksempel på kode fra app som prosesserer og populerer forskjellige data under lagring.

    public async Task<bool> ProcessDataWrite(
        Instance instance, Guid? dataId, object data)
    {
        bool edited = false;
    
        if (data is SoknadUnntakKaranteneHotellVelferd model)
        {
            string org = instance.Org;
            string app = instance.AppId.Split("/")[1];
            int partyId = int.Parse(instance.InstanceOwner.PartyId);
            Guid instanceGuid = Guid.Parse(instance.Id.Split("/")[1]);
    
            // handling mapping of multiple choice velferdsgrunner
            if (!string.IsNullOrEmpty(model.velferdsgrunner?.sammenstilling))
            {
                model.velferdsgrunner.helseproblemer = model.velferdsgrunner.sammenstilling.Contains("helseproblemer");
                model.velferdsgrunner.barnefodsel = model.velferdsgrunner.sammenstilling.Contains("barnefodsel");
                model.velferdsgrunner.begravelse = model.velferdsgrunner.sammenstilling.Contains("begravelse");
                model.velferdsgrunner.naerstaaende = model.velferdsgrunner.sammenstilling.Contains("naerstaaende");
                model.velferdsgrunner.adopsjon = model.velferdsgrunner.sammenstilling.Contains("adopsjon");
                model.velferdsgrunner.sarligeOmsorg = model.velferdsgrunner.sammenstilling.Contains("sarligeOmsorg");
                model.velferdsgrunner.barnAlene = model.velferdsgrunner.sammenstilling.Contains("barnAlene");
                model.velferdsgrunner.hjemmeeksamen = model.velferdsgrunner.sammenstilling.Contains("hjemmeeksamen");
                model.velferdsgrunner.arbeidunntak = model.velferdsgrunner.sammenstilling.Contains("arbeidunntak");
                model.velferdsgrunner.andreVelferdshensyn = model.velferdsgrunner.sammenstilling.Contains("annet");
                model.velferdsgrunner.andreVelferdshensynBeskrivelse = model.velferdsgrunner.sammenstilling.Contains("annet") ? model.velferdsgrunner.andreVelferdshensynBeskrivelse : null;
    
                edited = true;
            }
            else
            {
                model.velferdsgrunner = null;
            }
    
            // set data for receipt if not set
            if (string.IsNullOrEmpty(model.applogic?.altinnRef))
            {
                model.applogic ??= new Applogic();
    
                Party party = await _registerService.GetParty(
                    int.Parse(instance.InstanceOwner.PartyId));
                model.applogic.avsender =
                    $"{instance.InstanceOwner.PersonNumber}-{party.Name}";
                model.applogic.altinnRef = instance.Id.Split("-")[4];
            }
        }
    
        return await Task.FromResult(edited);
    }