From 011de0e6a2c9bda368579f943f93e7a9b1a8f014 Mon Sep 17 00:00:00 2001 From: Daniel Skovli Date: Fri, 22 May 2026 14:24:24 +0200 Subject: [PATCH 1/6] feat(fiks-arkiv): configurable case file classifications and document format codes - Optional CaseFileClassifications on FiksArkivMetadataSettings. - Optional FormatCode override per document (e.g. PDF/A). - Variantformat changed from Produksjonsformat (P) to Arkivformat (A). - IFiksArkivConfigResolver: GetInstanceOwnerClassification replaced with GetCaseFileClassifications (breaking). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../FiksArkivClassificationExtensions.cs | 16 +++ .../FiksArkiv/FiksArkivConfigResolver.cs | 38 ++++-- .../FiksArkivDefaultPayloadGenerator.cs | 19 ++- .../FiksArkiv/IFiksArkivConfigResolver.cs | 6 +- .../FiksArkiv/Models/FiksArkivSettings.cs | 74 +++++++++++ .../FiksArkiv/Models/MessagePayloadWrapper.cs | 14 +- .../Extensions/ListExtensionsTests.cs | 3 +- ...KnownAuthenticationTypes.Org.verified.txt} | 0 ...enticationTypes.ServiceOwner.verified.txt} | 0 ...thenticationTypes.SystemUser.verified.txt} | 0 ...nownAuthenticationTypes.User.verified.txt} | 0 ...oad_GeneratesCorrectPayload.1.verified.txt | 8 +- ...oad_GeneratesCorrectPayload.2.verified.txt | 20 +-- ...oad_GeneratesCorrectPayload.3.verified.txt | 4 +- ...oad_GeneratesCorrectPayload.4.verified.txt | 4 +- ...oad_GeneratesCorrectPayload.5.verified.txt | 125 ++++++++++++++++++ .../FiksArkiv/FiksArkivConfigResolverTest.cs | 83 +++++++++++- .../FiksArkivDefaultPayloadGeneratorTest.cs | 82 +++++++++--- .../Models/FiksArkivDocumentsTest.cs | 2 +- .../FiksArkiv/Models/FiksArkivSettingsTest.cs | 92 +++++++++++++ .../Models/MessagePayloadWrapperTest.cs | 58 ++++++++ ...ouldNotChange_Unintentionally.verified.txt | 18 ++- 22 files changed, 601 insertions(+), 65 deletions(-) create mode 100644 src/Altinn.App.Clients.Fiks/Extensions/FiksArkivClassificationExtensions.cs rename test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/{FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.Org.verified.txt => FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.Org.verified.txt} (100%) rename test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/{FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.ServiceOwner.verified.txt => FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.ServiceOwner.verified.txt} (100%) rename test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/{FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.SystemUser.verified.txt => FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.SystemUser.verified.txt} (100%) rename test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/{FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.User.verified.txt => FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.User.verified.txt} (100%) create mode 100644 test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt create mode 100644 test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/MessagePayloadWrapperTest.cs diff --git a/src/Altinn.App.Clients.Fiks/Extensions/FiksArkivClassificationExtensions.cs b/src/Altinn.App.Clients.Fiks/Extensions/FiksArkivClassificationExtensions.cs new file mode 100644 index 0000000000..5e4d5f56d1 --- /dev/null +++ b/src/Altinn.App.Clients.Fiks/Extensions/FiksArkivClassificationExtensions.cs @@ -0,0 +1,16 @@ +using Altinn.App.Clients.Fiks.FiksArkiv.Models; +using KS.Fiks.Arkiv.Models.V1.Arkivering.Arkivmelding; + +namespace Altinn.App.Clients.Fiks.Extensions; + +internal static class FiksArkivClassificationExtensions +{ + public static Klassifikasjon ToKlassifikasjon(this FiksArkivClassification classification) => + new() + { + KlassifikasjonssystemID = classification.SystemId, + KlasseID = classification.ClassificationId, + Tittel = classification.Title, + ErSkjermet = classification.IsRestricted, + }; +} diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivConfigResolver.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivConfigResolver.cs index 130aa626e5..434f34e82b 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivConfigResolver.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivConfigResolver.cs @@ -212,23 +212,16 @@ public Korrespondansepart GetRecipientParty(Instance instance, FiksArkivRecipien ); /// - public async Task GetInstanceOwnerClassification( + public async Task> GetCaseFileClassifications( Authenticated auth, CancellationToken cancellationToken = default ) { - cancellationToken.ThrowIfCancellationRequested(); - - return auth switch - { - Authenticated.User user => await KlassifikasjonFactory.CreateUser(user), // Note: Doesn't accept cancellation token.. yet - Authenticated.SystemUser systemUser => KlassifikasjonFactory.CreateSystemUser(systemUser), - Authenticated.ServiceOwner serviceOwner => KlassifikasjonFactory.CreateServiceOwner(serviceOwner), - Authenticated.Org org => KlassifikasjonFactory.CreateOrganization(org), - _ => throw new FiksArkivException( - $"Could not determine submitter details from authentication context: {auth}" - ), - }; + return + [ + await GetInstanceOwnerClassification(auth, cancellationToken: cancellationToken), + .. _fiksArkivSettings.Metadata?.CaseFileClassifications?.Select(x => x.ToKlassifikasjon()) ?? [], + ]; } /// @@ -300,6 +293,25 @@ private async Task GetLayoutState(Instance instance) return await _layoutStateInitializer.Init(unitOfWork, null); } + private static async Task GetInstanceOwnerClassification( + Authenticated auth, + CancellationToken cancellationToken = default + ) + { + cancellationToken.ThrowIfCancellationRequested(); + + return auth switch + { + Authenticated.User user => await KlassifikasjonFactory.CreateUser(user), // Note: Doesn't accept cancellation token.. yet + Authenticated.SystemUser systemUser => KlassifikasjonFactory.CreateSystemUser(systemUser), + Authenticated.ServiceOwner serviceOwner => KlassifikasjonFactory.CreateServiceOwner(serviceOwner), + Authenticated.Org org => KlassifikasjonFactory.CreateOrganization(org), + _ => throw new FiksArkivException( + $"Could not determine submitter details from authentication context: {auth}" + ), + }; + } + private static async Task GetBindableConfigValue( LayoutEvaluatorState layoutState, Instance instance, diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs index 7cf2008fe1..36b8d2124f 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs @@ -74,7 +74,7 @@ public async Task> GeneratePayload( var documentMetadata = await _fiksArkivConfigResolver.GetArchiveDocumentMetadata(instance, cancellationToken); var recipientParty = _fiksArkivConfigResolver.GetRecipientParty(instance, recipient); var instanceOwnerParty = await _fiksArkivConfigResolver.GetInstanceOwnerParty(instance, cancellationToken); - var instanceOwnerClassification = await _fiksArkivConfigResolver.GetInstanceOwnerClassification( + var caseFileClassifications = await _fiksArkivConfigResolver.GetCaseFileClassifications( _authenticationContext.Current, cancellationToken ); @@ -93,7 +93,10 @@ public async Task> GeneratePayload( }, }; - caseFile.Klassifikasjon.Add(instanceOwnerClassification); + foreach (var classification in caseFileClassifications) + { + caseFile.Klassifikasjon.Add(classification); + } var journalEntry = new Journalpost { @@ -170,6 +173,7 @@ private async Task GetArchiveDocuments( primaryDataElement, primaryDocumentSettings.Filename, DokumenttypeKoder.Dokument, + primaryDocumentSettings.FormatCode, instanceId, cancellationToken ); @@ -191,6 +195,7 @@ await GetPayload( x, attachmentSetting.Filename, DokumenttypeKoder.Vedlegg, + attachmentSetting.FormatCode, instanceId, cancellationToken ) @@ -206,6 +211,7 @@ private async Task GetPayload( DataElement dataElement, string? filename, Kode fileTypeCode, + string? fileFormatCode, InstanceIdentifier instanceId, CancellationToken cancellationToken = default ) @@ -225,7 +231,8 @@ await _dataClient.GetDataBytes( cancellationToken: cancellationToken ) ), - fileTypeCode + fileTypeCode, + fileFormatCode ); } @@ -267,11 +274,11 @@ private Dokumentbeskrivelse GetDocumentDescription(MessagePayloadWrapper payload }, Filnavn = payloadWrapper.Payload.Filename, ReferanseDokumentfil = payloadWrapper.Payload.Filename, - Format = new Format { KodeProperty = payloadWrapper.Payload.GetDotlessFileExtension() }, + Format = payloadWrapper.GetFileFormat(), Variantformat = new Variantformat { - KodeProperty = VariantformatKoder.Produksjonsformat.Verdi, - Beskrivelse = VariantformatKoder.Produksjonsformat.Beskrivelse, + KodeProperty = VariantformatKoder.Arkivformat.Verdi, + Beskrivelse = VariantformatKoder.Arkivformat.Beskrivelse, }, } ); diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/IFiksArkivConfigResolver.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/IFiksArkivConfigResolver.cs index 406bcd7e1d..ab5bad2450 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/IFiksArkivConfigResolver.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/IFiksArkivConfigResolver.cs @@ -54,9 +54,11 @@ public interface IFiksArkivConfigResolver Task GetInstanceOwnerParty(Instance instance, CancellationToken cancellationToken = default); /// - /// Gets the classification of the instance owner (klassifikasjon). + /// Gets the case file classifications (klassifikasjoner) for the shipment. + /// Always includes the instance owner classification derived from , followed by any + /// classifications configured in . /// - Task GetInstanceOwnerClassification( + Task> GetCaseFileClassifications( Authenticated auth, CancellationToken cancellationToken = default ); diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/FiksArkivSettings.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/FiksArkivSettings.cs index ef05ded3e1..fc29a21ad9 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/FiksArkivSettings.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/FiksArkivSettings.cs @@ -122,6 +122,13 @@ public sealed record FiksArkivMetadataSettings [JsonPropertyName("caseFileTitle")] public FiksArkivBindableValue? CaseFileTitle { get; set; } + /// + /// Optional classifications (klassifikasjon) to attach to the generated saksmappe (case file) element in the arkivmelding.xml. + /// These are appended in order after the implicit instance-owner classification. + /// + [JsonPropertyName("caseFileClassifications")] + public IReadOnlyList? CaseFileClassifications { get; set; } + /// /// The title to use for the generated journalpost (journal entry) element in the arkivmelding.xml. /// If no title is provided, the value will default to the application title as defined in applicationmetadata.json. @@ -141,6 +148,11 @@ internal void Validate(IReadOnlyList dataTypes, IAppModel appModelReso CaseFileId?.Validate($"{propertyName}.{nameof(CaseFileId)}", dataTypes, appModelResolver); CaseFileTitle?.Validate($"{propertyName}.{nameof(CaseFileTitle)}", dataTypes, appModelResolver); JournalEntryTitle?.Validate($"{propertyName}.{nameof(JournalEntryTitle)}", dataTypes, appModelResolver); + + foreach (var classification in CaseFileClassifications ?? []) + { + classification.Validate($"{propertyName}.{nameof(CaseFileClassifications)}"); + } } } @@ -411,6 +423,13 @@ public sealed record FiksArkivDataTypeSettings [JsonPropertyName("filename")] public string? Filename { get; set; } + /// + /// Optional override for the document format code (e.g. PDF/A) recorded in the arkivmelding.xml + /// (dokumentobjekt.format.kode). If not specified, the dotless file extension is used. + /// + [JsonPropertyName("formatCode")] + public string? FormatCode { get; set; } + /// /// Internal validation based on the requirements of /// @@ -429,6 +448,11 @@ internal void Validate(string propertyName, IReadOnlyList dataTypes, b throw new FiksArkivConfigurationException( $"{propertyName}.{nameof(Filename)} configuration is required, but missing." ); + + if (FormatCode is not null && string.IsNullOrWhiteSpace(FormatCode)) + throw new FiksArkivConfigurationException( + $"{propertyName}.{nameof(FormatCode)} cannot be empty or whitespace if specified." + ); } /// @@ -437,3 +461,53 @@ internal void Validate(string propertyName, IReadOnlyList dataTypes, b public string GetFilenameOrDefault(string defaultExtension = "xml") => !string.IsNullOrWhiteSpace(Filename) ? Filename : $"{DataType}.{defaultExtension.TrimStart('.')}"; } + +/// +/// Represents a single classification (klassifikasjon) entry attached to the saksmappe (case file) +/// in the generated arkivmelding.xml. +/// +public sealed record FiksArkivClassification +{ + /// + /// The identifier of the classification system this entry belongs to (klassifikasjonssystemID). + /// + [JsonPropertyName("systemId")] + public required string SystemId { get; set; } + + /// + /// The identifier of the class within the classification system (klasseID). + /// + [JsonPropertyName("classificationId")] + public required string ClassificationId { get; set; } + + /// + /// A human-readable title for the classification entry (tittel). + /// + [JsonPropertyName("title")] + public required string Title { get; set; } + + /// + /// Optional flag indicating that the classification is restricted (erSkjermet). + /// Leave null to omit the property from the resulting XML. + /// + [JsonPropertyName("isRestricted")] + public bool? IsRestricted { get; set; } + + internal void Validate(string propertyName) + { + if (string.IsNullOrWhiteSpace(SystemId)) + throw new FiksArkivConfigurationException( + $"{propertyName}.{nameof(SystemId)} configuration is required, but missing." + ); + + if (string.IsNullOrWhiteSpace(ClassificationId)) + throw new FiksArkivConfigurationException( + $"{propertyName}.{nameof(ClassificationId)} configuration is required, but missing." + ); + + if (string.IsNullOrWhiteSpace(Title)) + throw new FiksArkivConfigurationException( + $"{propertyName}.{nameof(Title)} configuration is required, but missing." + ); + } +} diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/MessagePayloadWrapper.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/MessagePayloadWrapper.cs index 18e451320a..1756c79d14 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/MessagePayloadWrapper.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/MessagePayloadWrapper.cs @@ -1,6 +1,16 @@ using Altinn.App.Clients.Fiks.FiksIO.Models; -using KS.Fiks.Arkiv.Models.V1.Kodelister; +using KS.Fiks.Arkiv.Models.V1.Metadatakatalog; +using Kode = KS.Fiks.Arkiv.Models.V1.Kodelister.Kode; namespace Altinn.App.Clients.Fiks.FiksArkiv.Models; -internal sealed record MessagePayloadWrapper(FiksIOMessagePayload Payload, Kode FileTypeCode); +internal sealed record MessagePayloadWrapper(FiksIOMessagePayload Payload, Kode FileTypeCode, string? FileFormatCode) +{ + public Format GetFileFormat() => + new() + { + KodeProperty = !string.IsNullOrWhiteSpace(FileFormatCode) + ? FileFormatCode + : Payload.GetDotlessFileExtension(), + }; +} diff --git a/test/Altinn.App.Clients.Fiks.Tests/Extensions/ListExtensionsTests.cs b/test/Altinn.App.Clients.Fiks.Tests/Extensions/ListExtensionsTests.cs index 615178fce5..9ce64af0ca 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/Extensions/ListExtensionsTests.cs +++ b/test/Altinn.App.Clients.Fiks.Tests/Extensions/ListExtensionsTests.cs @@ -12,7 +12,8 @@ private static IReadOnlyList GetPayloads(params string[] return filenames .Select(filename => new MessagePayloadWrapper( new FiksIOMessagePayload(filename, Stream.Null), - new Kode(".", string.Empty) + new Kode(".", string.Empty), + FileFormatCode: null )) .ToList(); } diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.Org.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.Org.verified.txt similarity index 100% rename from test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.Org.verified.txt rename to test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.Org.verified.txt diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.ServiceOwner.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.ServiceOwner.verified.txt similarity index 100% rename from test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.ServiceOwner.verified.txt rename to test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.ServiceOwner.verified.txt diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.SystemUser.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.SystemUser.verified.txt similarity index 100% rename from test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.SystemUser.verified.txt rename to test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.SystemUser.verified.txt diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.User.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.User.verified.txt similarity index 100% rename from test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes.User.verified.txt rename to test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.User.verified.txt diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt index c05767faa9..c285097741 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt @@ -47,8 +47,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat XML @@ -75,8 +75,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat PDF diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt index 862512b2fb..2be98894db 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt @@ -48,8 +48,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat XML @@ -76,8 +76,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat PDF @@ -104,8 +104,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat PDF @@ -132,8 +132,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat DOCX @@ -160,8 +160,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat JPG diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt index ac24e3402e..3f3b183869 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt @@ -47,8 +47,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat XML diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt index e643c82339..92c402392b 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt @@ -46,8 +46,8 @@ f41af07b-47c3-4d3a-9a34-1baa0f575101 - P - Produksjonsformat + A + Arkivformat XML diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt new file mode 100644 index 0000000000..1afe93223c --- /dev/null +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt @@ -0,0 +1,125 @@ + + + Altinn Studio + 2 + + Test app + Test app + + Fødselsnummer + 12345678901 + Test Testesen + + + custom-system + custom-class + Custom Classification + + + custom-system-2 + custom-class-2 + Restricted Classification + true + + + ttd/test-app + 12345/88d9baf8-2f9f-4e66-9a2f-7d345e60ed90 + + 2025 + 2025-10-24 + + ttd + + + + ttd + ttd + + + ttd/test-app + 12345/88d9baf8-2f9f-4e66-9a2f-7d345e60ed90 + + + + + DOKUMENT + Dokument + + + F + Dokumentet er ferdigstilt + + Form.pdf + 2025-10-24T09:58:00 + + H + Hoveddokument + + + f41af07b-47c3-4d3a-9a34-1baa0f575101 + + A + Arkivformat + + + PDF/A + + Form.pdf + Form.pdf + + + + + VEDLEGG + Vedlegg + + + F + Dokumentet er ferdigstilt + + ref-data-as-pdf.pdf + 2025-10-24T09:58:00 + + V + Vedlegg + + + f41af07b-47c3-4d3a-9a34-1baa0f575101 + + A + Arkivformat + + + PDF + + ref-data-as-pdf.pdf + ref-data-as-pdf.pdf + + + Test app + Test app + + recipient-id + + EM + Mottaker + + Recipient Name + + + ttd/test-app + 12345/88d9baf8-2f9f-4e66-9a2f-7d345e60ed90 + + 2025 + + I + Inngående dokument + + + J + Journalført + + 2025-10-24 + 2025-10-24T09:58:00 + + \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivConfigResolverTest.cs b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivConfigResolverTest.cs index 02a29b5326..92c3c0e694 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivConfigResolverTest.cs +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivConfigResolverTest.cs @@ -455,7 +455,7 @@ public async Task GetRecipientParty_ReturnsExpectedValue( [InlineData(typeof(Authenticated.SystemUser))] [InlineData(typeof(Authenticated.ServiceOwner))] [InlineData(typeof(Authenticated.Org))] - public async Task GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAuthenticationTypes(Type authType) + public async Task GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes(Type authType) { // Arrange Authenticated auth = authType switch @@ -469,20 +469,24 @@ public async Task GetInstanceOwnerClassification_ReturnsExpectedValue_ForKnownAu _ => throw new NotSupportedException(), }; - await using var fixture = TestFixture.Create(services => services.AddFiksArkiv()); + await using var fixture = TestFixture.Create( + services => services.AddFiksArkiv(), + useDefaultFiksArkivSettings: false + ); // Act - var result = await fixture.FiksArkivConfigResolver.GetInstanceOwnerClassification(auth); + var result = await fixture.FiksArkivConfigResolver.GetCaseFileClassifications(auth); // Assert Assert.NotNull(result); - var serialized = result.SerializeXml(indent: true); + Assert.Single(result); + var serialized = result[0].SerializeXml(indent: true); var xml = Encoding.UTF8.GetString(serialized.Span); await Verify(xml).UseDefaultSettings(authType.Name.Split("+").Last()); } [Fact] - public async Task GetInstanceOwnerClassification_ThrowsException_ForUnknownAuthenticationTypes() + public async Task GetCaseFileClassifications_ThrowsException_ForUnknownAuthenticationTypes() { // Arrange var auth = TestAuthentication.GetNoneAuthentication(); @@ -490,10 +494,77 @@ public async Task GetInstanceOwnerClassification_ThrowsException_ForUnknownAuthe // Act await Assert.ThrowsAsync(() => - fixture.FiksArkivConfigResolver.GetInstanceOwnerClassification(auth) + fixture.FiksArkivConfigResolver.GetCaseFileClassifications(auth) ); } + [Fact] + public async Task GetCaseFileClassifications_AppendsConfiguredClassifications_AfterOwnerClassification() + { + // Arrange + var fiksArkivSettingsOverride = new FiksArkivSettings + { + Metadata = new FiksArkivMetadataSettings + { + CaseFileClassifications = + [ + new FiksArkivClassification + { + SystemId = "configured-system-1", + ClassificationId = "configured-class-1", + Title = "Configured 1", + }, + new FiksArkivClassification + { + SystemId = "configured-system-2", + ClassificationId = "configured-class-2", + Title = "Configured 2", + IsRestricted = true, + }, + ], + }, + }; + await using var fixture = TestFixture.Create( + services => services.AddFiksArkiv().WithFiksArkivConfig("CustomFiksArkivSettings"), + [("CustomFiksArkivSettings", fiksArkivSettingsOverride)], + useDefaultFiksArkivSettings: false + ); + + // Act + var result = await fixture.FiksArkivConfigResolver.GetCaseFileClassifications( + TestAuthentication.GetServiceOwnerAuthentication() + ); + + // Assert + Assert.Equal(3, result.Count); + Assert.Equal("configured-system-1", result[1].KlassifikasjonssystemID); + Assert.Equal("configured-class-1", result[1].KlasseID); + Assert.Equal("Configured 1", result[1].Tittel); + Assert.Null(result[1].ErSkjermet); + Assert.Equal("configured-system-2", result[2].KlassifikasjonssystemID); + Assert.Equal("configured-class-2", result[2].KlasseID); + Assert.Equal("Configured 2", result[2].Tittel); + Assert.True(result[2].ErSkjermet); + } + + [Fact] + public async Task GetCaseFileClassifications_ReturnsOwnerOnly_WhenNoConfiguredClassifications() + { + // Arrange + await using var fixture = TestFixture.Create( + services => services.AddFiksArkiv(), + useDefaultFiksArkivSettings: false + ); + + // Act + var result = await fixture.FiksArkivConfigResolver.GetCaseFileClassifications( + TestAuthentication.GetServiceOwnerAuthentication() + ); + + // Assert + Assert.Single(result); + } + // csharpier-ignore-start [Theory] [InlineData(1, PartyType.None, null, null, null, null, null, null, null, null)] diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs index bd337b75a6..a16142e719 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs @@ -29,16 +29,19 @@ public class FiksArkivDefaultPayloadGeneratorTest private static readonly Guid _fiksIOSenderAccount = Guid.Parse("f41af07b-47c3-4d3a-9a34-1baa0f575101"); private static readonly DateTimeOffset _now = DateTimeOffset.Parse("2025-10-24T09:58:00.000000Z"); - private static readonly Instance _defaultInstance = Factories.Instance( - "12345/88d9baf8-2f9f-4e66-9a2f-7d345e60ed90", - [ - Factories.DataElement("model", null, "application/xml"), - Factories.DataElement("ref-data-as-pdf", null, "application/pdf"), - Factories.DataElement("something-uploaded", "receipt2.pdf", null), - Factories.DataElement("something-uploaded", "letter.docx", null), - Factories.DataElement("something-uploaded", "drawing_1a.jpg", null), - ] - ); + // Built fresh per test invocation because the production code mutates DataElement.Filename; + // reusing a static instance leaks state across test cases. + private static Instance NewDefaultInstance() => + Factories.Instance( + "12345/88d9baf8-2f9f-4e66-9a2f-7d345e60ed90", + [ + Factories.DataElement("model", null, "application/xml"), + Factories.DataElement("ref-data-as-pdf", null, "application/pdf"), + Factories.DataElement("something-uploaded", "receipt2.pdf", null), + Factories.DataElement("something-uploaded", "letter.docx", null), + Factories.DataElement("something-uploaded", "drawing_1a.jpg", null), + ] + ); private static class Auth { @@ -130,6 +133,27 @@ private static class Auth ), instanceOwnerClassification: Factories.InstanceOwnerClassification(Auth.Org) ), + TestCase.Create( + testIdentifier: "5", + fiksArkivMessageType: FiksArkivConstants.MessageTypes.CreateArchiveRecord, + expectedAttachmentFilenames: ["Form.pdf", "ref-data-as-pdf.pdf"], + primaryDocumentSettings: Factories.DocumentSettings("model", "Form.pdf", formatCode: "PDF/A"), + attachmentSettings: [Factories.DocumentSettings("ref-data-as-pdf")], + archiveDocumentMetadata: null, + recipientParty: Factories.RecipientParty("recipient-id", "Recipient Name"), + instanceOwnerParty: null, + instanceOwnerClassification: Factories.InstanceOwnerClassification(Auth.User), + additionalClassifications: + [ + Factories.ConfiguredClassification("custom-system", "custom-class", "Custom Classification"), + Factories.ConfiguredClassification( + "custom-system-2", + "custom-class-2", + "Restricted Classification", + isRestricted: true + ), + ] + ), ]; [Theory] @@ -141,7 +165,7 @@ internal async Task GeneratePayload_GeneratesCorrectPayload(TestCase testCase) // Act var result = await fixture.GeneratePayload( - _defaultInstance, + NewDefaultInstance(), FiksArkivConstants.MessageTypes.CreateArchiveRecord ); @@ -189,6 +213,7 @@ public static TestCase Create( Korrespondansepart recipientParty, Korrespondansepart? instanceOwnerParty, Klassifikasjon instanceOwnerClassification, + IReadOnlyList? additionalClassifications = null, string applicationTitle = "Test app", string appId = "ttd/test-app" ) @@ -201,6 +226,7 @@ public static TestCase Create( recipientParty, instanceOwnerParty, instanceOwnerClassification, + additionalClassifications, applicationTitle, appId ), @@ -242,6 +268,7 @@ public static PayloadGeneratorFixture Create( Korrespondansepart recipientParty, Korrespondansepart? instanceOwnerParty, Klassifikasjon instanceOwnerClassification, + IReadOnlyList? additionalClassifications = null, string applicationTitle = "Test app", string appId = "ttd/test-app" ) @@ -272,8 +299,10 @@ public static PayloadGeneratorFixture Create( .Setup(x => x.GetInstanceOwnerParty(It.IsAny(), It.IsAny())) .ReturnsAsync(instanceOwnerParty); configResolverMock - .Setup(x => x.GetInstanceOwnerClassification(It.IsAny(), It.IsAny())) - .ReturnsAsync(instanceOwnerClassification); + .Setup(x => x.GetCaseFileClassifications(It.IsAny(), It.IsAny())) + .ReturnsAsync( + (IReadOnlyList)[instanceOwnerClassification, .. additionalClassifications ?? []] + ); var payloadGenerator = new FiksArkivDefaultPayloadGenerator( appMetadataMock.Object, @@ -325,8 +354,31 @@ public static Instance Instance(string id, IEnumerable dataElements public static FiksArkivRecipient Recipient() => new(Guid.NewGuid(), "-", "-", "-"); - public static FiksArkivDataTypeSettings DocumentSettings(string dataType, string? filename = null) => - new() { DataType = dataType, Filename = filename }; + public static FiksArkivDataTypeSettings DocumentSettings( + string dataType, + string? filename = null, + string? formatCode = null + ) => + new() + { + DataType = dataType, + Filename = filename, + FormatCode = formatCode, + }; + + public static Klassifikasjon ConfiguredClassification( + string systemId, + string classificationId, + string title, + bool? isRestricted = null + ) => + new FiksArkivClassification + { + SystemId = systemId, + ClassificationId = classificationId, + Title = title, + IsRestricted = isRestricted, + }.ToKlassifikasjon(); public static FiksArkivDocumentMetadata Metadata( string? systemId, diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/FiksArkivDocumentsTest.cs b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/FiksArkivDocumentsTest.cs index fb1df82e0f..be7107b7f8 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/FiksArkivDocumentsTest.cs +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/FiksArkivDocumentsTest.cs @@ -11,7 +11,7 @@ public class FiksArkivDocumentsTest private static FiksIOMessagePayload CreatePayload(string filename) => new(filename, Stream.Null); private MessagePayloadWrapper CreateMessagePayloadWrapper(string filename, Kode? code = null) => - new(CreatePayload(filename), code ?? _dummyCode); + new(CreatePayload(filename), code ?? _dummyCode, FileFormatCode: null); [Fact] public void ToPaylods_ContainsAllDocuments_InTheCorrectOrder() diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/FiksArkivSettingsTest.cs b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/FiksArkivSettingsTest.cs index f5e06d6858..5fea883b1d 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/FiksArkivSettingsTest.cs +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/FiksArkivSettingsTest.cs @@ -1,4 +1,5 @@ using Altinn.App.Clients.Fiks.Exceptions; +using Altinn.App.Clients.Fiks.Extensions; using Altinn.App.Clients.Fiks.FiksArkiv.Models; using Altinn.Platform.Storage.Interface.Models; @@ -6,6 +7,71 @@ namespace Altinn.App.Clients.Fiks.Tests.FiksArkiv.Models; public class FiksArkivSettingsTest { + [Theory] + [InlineData("sys", "cls", "title", null, null)] + [InlineData("sys", "cls", "title", true, null)] + [InlineData("sys", "cls", "title", false, null)] + [InlineData("", "cls", "title", null, "SystemId configuration is required")] + [InlineData(" ", "cls", "title", null, "SystemId configuration is required")] + [InlineData("sys", "", "title", null, "ClassificationId configuration is required")] + [InlineData("sys", "cls", "", null, "Title configuration is required")] + public void FiksArkivClassification_ValidatesCorrectly( + string systemId, + string classificationId, + string title, + bool? isRestricted, + string? expectedErrorMessage + ) + { + // Arrange + var classification = new FiksArkivClassification + { + SystemId = systemId, + ClassificationId = classificationId, + Title = title, + IsRestricted = isRestricted, + }; + + // Act + var ex = Record.Exception(() => classification.Validate("TestSetting")); + + // Assert + if (expectedErrorMessage is null) + { + Assert.Null(ex); + return; + } + + Assert.NotNull(ex); + Assert.IsType(ex); + Assert.Contains(expectedErrorMessage, ex.Message); + } + + [Theory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void FiksArkivClassification_ToKlassifikasjon_MapsAllFields(bool? isRestricted) + { + // Arrange + var classification = new FiksArkivClassification + { + SystemId = "system-1", + ClassificationId = "class-1", + Title = "The Title", + IsRestricted = isRestricted, + }; + + // Act + var result = classification.ToKlassifikasjon(); + + // Assert + Assert.Equal("system-1", result.KlassifikasjonssystemID); + Assert.Equal("class-1", result.KlasseID); + Assert.Equal("The Title", result.Tittel); + Assert.Equal(isRestricted, result.ErSkjermet); + } + [Theory] [InlineData("datatype1", "customfile.xml", null, "customfile.xml")] [InlineData("datatype2", null, ".pdf", "datatype2.pdf")] @@ -58,4 +124,30 @@ public void FiksArkivDataTypeSettings_ValidatesCorrectly( Assert.IsType(ex); Assert.Contains(expectedErrorMessage, ex.Message); } + + [Theory] + [InlineData(null, null)] + [InlineData("PDF/A", null)] + [InlineData("anything goes verbatim", null)] + [InlineData("", "FormatCode cannot be empty or whitespace")] + [InlineData(" ", "FormatCode cannot be empty or whitespace")] + public void FiksArkivDataTypeSettings_ValidatesFormatCode(string? formatCode, string? expectedErrorMessage) + { + // Arrange + var settings = new FiksArkivDataTypeSettings { DataType = "valid-datatype", FormatCode = formatCode }; + + // Act + var ex = Record.Exception(() => settings.Validate("TestSetting", [new DataType { Id = "valid-datatype" }])); + + // Assert + if (expectedErrorMessage is null) + { + Assert.Null(ex); + return; + } + + Assert.NotNull(ex); + Assert.IsType(ex); + Assert.Contains(expectedErrorMessage, ex.Message); + } } diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/MessagePayloadWrapperTest.cs b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/MessagePayloadWrapperTest.cs new file mode 100644 index 0000000000..b8c8f97f21 --- /dev/null +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/Models/MessagePayloadWrapperTest.cs @@ -0,0 +1,58 @@ +using Altinn.App.Clients.Fiks.FiksArkiv.Models; +using Altinn.App.Clients.Fiks.FiksIO.Models; +using KS.Fiks.Arkiv.Models.V1.Kodelister; + +namespace Altinn.App.Clients.Fiks.Tests.FiksArkiv.Models; + +public class MessagePayloadWrapperTest +{ + private static readonly Kode _dummyCode = new(".", string.Empty); + + [Theory] + [InlineData("PDF/A")] + [InlineData("XML")] + [InlineData("anything-goes")] + public void GetFileFormat_UsesOverride_WhenFormatCodeIsProvided(string formatCode) + { + var wrapper = new MessagePayloadWrapper( + new FiksIOMessagePayload("document.pdf", Stream.Null), + _dummyCode, + FileFormatCode: formatCode + ); + + var result = wrapper.GetFileFormat(); + + Assert.Equal(formatCode, result.KodeProperty); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void GetFileFormat_FallsBackToFileExtension_WhenFormatCodeIsMissing(string? formatCode) + { + var wrapper = new MessagePayloadWrapper( + new FiksIOMessagePayload("report.pdf", Stream.Null), + _dummyCode, + FileFormatCode: formatCode + ); + + var result = wrapper.GetFileFormat(); + + Assert.Equal("PDF", result.KodeProperty); + } + + [Fact] + public void GetFileFormat_FallsBackToUppercasedFilename_WhenNoExtensionAndNoOverride() + { + var wrapper = new MessagePayloadWrapper( + new FiksIOMessagePayload("extensionless", Stream.Null), + _dummyCode, + FileFormatCode: null + ); + + var result = wrapper.GetFileFormat(); + + Assert.Equal("EXTENSIONLESS", result.KodeProperty); + } +} diff --git a/test/Altinn.App.Clients.Fiks.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt index 393181c7b5..7ead0b6e75 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt @@ -68,8 +68,8 @@ namespace Altinn.App.Clients.Fiks.FiksArkiv Altinn.App.Clients.Fiks.FiksArkiv.Models.FiksArkivDataTypeSettings PrimaryDocumentSettings { get; } System.Threading.Tasks.Task GetApplicationTitle(System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task GetArchiveDocumentMetadata(Altinn.Platform.Storage.Interface.Models.Instance instance, System.Threading.CancellationToken cancellationToken = default); + System.Threading.Tasks.Task> GetCaseFileClassifications(Altinn.App.Core.Features.Auth.Authenticated auth, System.Threading.CancellationToken cancellationToken = default); string GetCorrelationId(Altinn.Platform.Storage.Interface.Models.Instance instance); - System.Threading.Tasks.Task GetInstanceOwnerClassification(Altinn.App.Core.Features.Auth.Authenticated auth, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task GetInstanceOwnerParty(Altinn.Platform.Storage.Interface.Models.Instance instance, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task GetRecipient(Altinn.Platform.Storage.Interface.Models.Instance instance, System.Threading.CancellationToken cancellationToken = default); KS.Fiks.Arkiv.Models.V1.Arkivering.Arkivmelding.Korrespondansepart GetRecipientParty(Altinn.Platform.Storage.Interface.Models.Instance instance, Altinn.App.Clients.Fiks.FiksArkiv.Models.FiksArkivRecipient recipient); @@ -99,6 +99,18 @@ namespace Altinn.App.Clients.Fiks.FiksArkiv.Models [System.Text.Json.Serialization.JsonPropertyName("value")] public T Value { get; set; } } + public sealed class FiksArkivClassification : System.IEquatable + { + public FiksArkivClassification() { } + [System.Text.Json.Serialization.JsonPropertyName("classificationId")] + public required string ClassificationId { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("isRestricted")] + public bool? IsRestricted { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("systemId")] + public required string SystemId { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("title")] + public required string Title { get; set; } + } public sealed class FiksArkivDataModelBinding : System.IEquatable { public FiksArkivDataModelBinding() { } @@ -115,6 +127,8 @@ namespace Altinn.App.Clients.Fiks.FiksArkiv.Models public required string DataType { get; set; } [System.Text.Json.Serialization.JsonPropertyName("filename")] public string? Filename { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("formatCode")] + public string? FormatCode { get; set; } public string GetFilenameOrDefault(string defaultExtension = "xml") { } } public sealed class FiksArkivDocumentMetadata : System.IEquatable @@ -145,6 +159,8 @@ namespace Altinn.App.Clients.Fiks.FiksArkiv.Models public sealed class FiksArkivMetadataSettings : System.IEquatable { public FiksArkivMetadataSettings() { } + [System.Text.Json.Serialization.JsonPropertyName("caseFileClassifications")] + public System.Collections.Generic.IReadOnlyList? CaseFileClassifications { get; set; } [System.Text.Json.Serialization.JsonPropertyName("caseFileId")] public Altinn.App.Clients.Fiks.FiksArkiv.Models.FiksArkivBindableValue? CaseFileId { get; set; } [System.Text.Json.Serialization.JsonPropertyName("caseFileTitle")] From 0f4f1b3eeed82987967c7021413ca777fbd18ac8 Mon Sep 17 00:00:00 2001 From: Daniel Skovli Date: Fri, 22 May 2026 14:32:24 +0200 Subject: [PATCH 2/6] Removes redundant cast --- .../FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs index a16142e719..4f1f2ef87d 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs @@ -300,9 +300,7 @@ public static PayloadGeneratorFixture Create( .ReturnsAsync(instanceOwnerParty); configResolverMock .Setup(x => x.GetCaseFileClassifications(It.IsAny(), It.IsAny())) - .ReturnsAsync( - (IReadOnlyList)[instanceOwnerClassification, .. additionalClassifications ?? []] - ); + .ReturnsAsync([instanceOwnerClassification, .. additionalClassifications ?? []]); var payloadGenerator = new FiksArkivDefaultPayloadGenerator( appMetadataMock.Object, From 3681fbdd48afc9012f136ca8de4466cc076a71f6 Mon Sep 17 00:00:00 2001 From: Daniel Skovli Date: Sat, 23 May 2026 18:45:11 +0200 Subject: [PATCH 3/6] refine(fiks-arkiv): arkivmelding correctness and metadata cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Classification: use canonical NOARK5 short code "PNR" sourced from KlassifikasjonstypeKoder.Foedselsnummer.Verdi (was "Fødselsnummer"), and set ErSkjermet=true on fnr-based classifications per KS guidance. - ClassificationId constants: align with conventional Norwegian short codes ("ORGNR") and Altinn-scoped naming ("AltinnSystembrukerId"). - Timestamps: SendtDato and OpprettetDato now serialize with local timezone offset (use DateTimeOffset.LocalDateTime instead of .DateTime, which strips Kind to Unspecified and drops the offset). - Dokumentobjekt: omit SystemID and let the archive assign canonical UUIDs (matches KS forenklet helper convention; the previous value was the Fiks IO account UUID, identical across every shipment). - Drop now-unused FiksIOSettings dependency and related test helpers. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Constants/FiksArkivConstants.cs | 13 ++++++++++--- .../Factories/KlassifikasjonFactory.cs | 1 + .../FiksArkivDefaultPayloadGenerator.cs | 13 ++----------- ...rKnownAuthenticationTypes.Org.verified.txt | 2 +- ...henticationTypes.ServiceOwner.verified.txt | 2 +- ...uthenticationTypes.SystemUser.verified.txt | 2 +- ...KnownAuthenticationTypes.User.verified.txt | 3 ++- ...oad_GeneratesCorrectPayload.1.verified.txt | 11 +++++------ ...oad_GeneratesCorrectPayload.2.verified.txt | 19 +++++++------------ ...oad_GeneratesCorrectPayload.3.verified.txt | 7 +++---- ...oad_GeneratesCorrectPayload.4.verified.txt | 7 +++---- ...oad_GeneratesCorrectPayload.5.verified.txt | 11 +++++------ .../FiksArkivDefaultPayloadGeneratorTest.cs | 12 ------------ 13 files changed, 41 insertions(+), 62 deletions(-) diff --git a/src/Altinn.App.Clients.Fiks/Constants/FiksArkivConstants.cs b/src/Altinn.App.Clients.Fiks/Constants/FiksArkivConstants.cs index 3026c63d71..f1e330a834 100644 --- a/src/Altinn.App.Clients.Fiks/Constants/FiksArkivConstants.cs +++ b/src/Altinn.App.Clients.Fiks/Constants/FiksArkivConstants.cs @@ -1,3 +1,5 @@ +using Altinn.App.Clients.Fiks.FiksArkiv.Models; +using KS.Fiks.Arkiv.Models.V1.Kodelister; using KS.Fiks.Arkiv.Models.V1.Meldingstyper; namespace Altinn.App.Clients.Fiks.Constants; @@ -37,11 +39,16 @@ public static class MessageTypes public const string ArchiveRecordCreationReceipt = FiksArkivMeldingtype.ArkivmeldingOpprettKvittering; } + /// + /// Classification IDs for Fiks Arkiv messages. + /// + /// Callers can also specify their own, additional, classifications via + /// . internal static class ClassificationId { - public const string NationalIdentityNumber = "Fødselsnummer"; - public const string OrganizationNumber = "Organisasjonsnummer"; + public static readonly string NationalIdentityNumber = KlassifikasjonstypeKoder.Foedselsnummer.Verdi; + public const string OrganizationNumber = "ORGNR"; public const string AltinnUserId = "AltinnBrukerId"; - public const string SystemUserId = "SystembrukerId"; + public const string SystemUserId = "AltinnSystembrukerId"; } } diff --git a/src/Altinn.App.Clients.Fiks/Factories/KlassifikasjonFactory.cs b/src/Altinn.App.Clients.Fiks/Factories/KlassifikasjonFactory.cs index 525a61c851..b2bda3f491 100644 --- a/src/Altinn.App.Clients.Fiks/Factories/KlassifikasjonFactory.cs +++ b/src/Altinn.App.Clients.Fiks/Factories/KlassifikasjonFactory.cs @@ -25,6 +25,7 @@ public static async Task CreateUser(Authenticated.User user) .Party.SSN.ToString(CultureInfo.InvariantCulture) .EnsureNotNullOrEmpty("Classification.Id"), Tittel = userProfile.Party.Name.EnsureNotEmpty("Classification.Title"), + ErSkjermet = true, } : new Klassifikasjon { diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs index 36b8d2124f..744d5f2da1 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs @@ -14,7 +14,6 @@ using KS.Fiks.Arkiv.Models.V1.Metadatakatalog; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Kode = KS.Fiks.Arkiv.Models.V1.Kodelister.Kode; namespace Altinn.App.Clients.Fiks.FiksArkiv; @@ -27,7 +26,6 @@ internal sealed class FiksArkivDefaultPayloadGenerator : IFiksArkivPayloadGenera private readonly ILogger _logger; private readonly IHostEnvironment _hostEnvironment; private readonly IFiksArkivConfigResolver _fiksArkivConfigResolver; - private readonly FiksIOSettings _fiksIOSettings; private readonly TimeProvider _timeProvider; private bool _indentXmlSerialization => !_hostEnvironment.IsProduction(); @@ -39,7 +37,6 @@ public FiksArkivDefaultPayloadGenerator( ILogger logger, IHostEnvironment hostEnvironment, IFiksArkivConfigResolver fiksArkivConfigResolver, - IOptions fiksIOSettings, TimeProvider? timeProvider = null ) { @@ -49,7 +46,6 @@ public FiksArkivDefaultPayloadGenerator( _logger = logger; _hostEnvironment = hostEnvironment; _fiksArkivConfigResolver = fiksArkivConfigResolver; - _fiksIOSettings = fiksIOSettings.Value; _timeProvider = timeProvider ?? TimeProvider.System; } @@ -102,7 +98,7 @@ public async Task> GeneratePayload( { Journalaar = _timeProvider.GetLocalNow().Year, DokumentetsDato = _timeProvider.GetLocalNow().DateTime, - SendtDato = _timeProvider.GetLocalNow().DateTime, + SendtDato = _timeProvider.GetLocalNow().LocalDateTime, Tittel = documentMetadata?.JournalEntryTitle ?? defaultDocumentTitle, OffentligTittel = documentMetadata?.JournalEntryTitle ?? defaultDocumentTitle, OpprettetAv = documentCreator, @@ -261,17 +257,12 @@ private Dokumentbeskrivelse GetDocumentDescription(MessagePayloadWrapper payload KodeProperty = documentClassification.Verdi, Beskrivelse = documentClassification.Beskrivelse, }, - OpprettetDato = _timeProvider.GetLocalNow().DateTime, + OpprettetDato = _timeProvider.GetLocalNow().LocalDateTime, }; metadata.Dokumentobjekt.Add( new Dokumentobjekt { - SystemID = new SystemID - { - Value = _fiksIOSettings.AccountId.ToString(), - Label = FiksArkivConstants.AltinnSystemId, - }, Filnavn = payloadWrapper.Payload.Filename, ReferanseDokumentfil = payloadWrapper.Payload.Filename, Format = payloadWrapper.GetFileFormat(), diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.Org.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.Org.verified.txt index df1b4569ab..c54df44b7b 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.Org.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.Org.verified.txt @@ -1,5 +1,5 @@  - Organisasjonsnummer + ORGNR 405003309 \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.ServiceOwner.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.ServiceOwner.verified.txt index 1b26e0750b..3375594991 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.ServiceOwner.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.ServiceOwner.verified.txt @@ -1,6 +1,6 @@  - Organisasjonsnummer + ORGNR 405003309 tdd \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.SystemUser.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.SystemUser.verified.txt index b5e8b61a20..30b064600f 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.SystemUser.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.SystemUser.verified.txt @@ -1,6 +1,6 @@  - SystembrukerId + AltinnSystembrukerId f58fe166-bc22-4899-beb7-c3e8e3332f43 310702641 \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.User.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.User.verified.txt index 412d42207f..83334a6882 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.User.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivConfigResolverTest.GetCaseFileClassifications_ReturnsOwnerClassification_ForKnownAuthenticationTypes.User.verified.txt @@ -1,6 +1,7 @@  - Fødselsnummer + PNR 12345678901 Test Testesen + true \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt index c285097741..24d6bbdb8a 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt @@ -6,9 +6,10 @@ Test app Test app - Fødselsnummer + PNR 12345678901 Test Testesen + true ttd/test-app @@ -39,13 +40,12 @@ Dokumentet er ferdigstilt model.xml - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 H Hoveddokument - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -67,13 +67,12 @@ Dokumentet er ferdigstilt ref-data-as-pdf.pdf - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 V Vedlegg - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -109,6 +108,6 @@ Journalført 2025-10-24 - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt index 2be98894db..05b35b8194 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt @@ -7,7 +7,7 @@ Custom Case File Title Custom Case File Title - SystembrukerId + AltinnSystembrukerId f58fe166-bc22-4899-beb7-c3e8e3332f43 310702641 @@ -40,13 +40,12 @@ Dokumentet er ferdigstilt Form.xml - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 H Hoveddokument - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -68,13 +67,12 @@ Dokumentet er ferdigstilt Form.pdf - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 V Vedlegg - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -96,13 +94,12 @@ Dokumentet er ferdigstilt receipt2.pdf - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 V Vedlegg - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -124,13 +121,12 @@ Dokumentet er ferdigstilt letter.docx - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 V Vedlegg - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -152,13 +148,12 @@ Dokumentet er ferdigstilt drawing_1a.jpg - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 V Vedlegg - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -194,6 +189,6 @@ Journalført 2025-10-24 - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt index 3f3b183869..7ee95e635f 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt @@ -6,7 +6,7 @@ Test app Test app - Organisasjonsnummer + ORGNR 405003309 tdd @@ -39,13 +39,12 @@ Dokumentet er ferdigstilt Form.xml - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 H Hoveddokument - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -97,6 +96,6 @@ Journalført 2025-10-24 - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt index 92c402392b..3b4d5d3dec 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt @@ -6,7 +6,7 @@ Custom Case File Title Custom Case File Title - Organisasjonsnummer + ORGNR 405003309 @@ -38,13 +38,12 @@ Dokumentet er ferdigstilt Form.xml - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 H Hoveddokument - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -91,6 +90,6 @@ Journalført 2025-10-24 - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt index 1afe93223c..557442bddf 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt @@ -6,9 +6,10 @@ Test app Test app - Fødselsnummer + PNR 12345678901 Test Testesen + true custom-system @@ -50,13 +51,12 @@ Dokumentet er ferdigstilt Form.pdf - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 H Hoveddokument - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -78,13 +78,12 @@ Dokumentet er ferdigstilt ref-data-as-pdf.pdf - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 V Vedlegg - f41af07b-47c3-4d3a-9a34-1baa0f575101 A Arkivformat @@ -120,6 +119,6 @@ Journalført 2025-10-24 - 2025-10-24T09:58:00 + 2025-10-24T11:58:00+02:00 \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs index 4f1f2ef87d..b77f671836 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultPayloadGeneratorTest.cs @@ -15,7 +15,6 @@ using KS.Fiks.Arkiv.Models.V1.Arkivering.Arkivmelding; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Microsoft.Extensions.Time.Testing; using Moq; @@ -26,7 +25,6 @@ public class FiksArkivDefaultPayloadGeneratorTest //Example Instance ID = "12345/88d9baf8-2f9f-4e66-9a2f-7d345e60ed90" private static readonly XsdValidator _xsdValidator = new(); - private static readonly Guid _fiksIOSenderAccount = Guid.Parse("f41af07b-47c3-4d3a-9a34-1baa0f575101"); private static readonly DateTimeOffset _now = DateTimeOffset.Parse("2025-10-24T09:58:00.000000Z"); // Built fresh per test invocation because the production code mutates DataElement.Filename; @@ -309,7 +307,6 @@ public static PayloadGeneratorFixture Create( loggerMock.Object, Mock.Of(x => x.EnvironmentName == Environments.Development), configResolverMock.Object, - Options.Create(Factories.FiksIOSettings(_fiksIOSenderAccount)), fakeTime ); @@ -338,15 +335,6 @@ public static PayloadGeneratorFixture Create( private static class Factories { - public static FiksIOSettings FiksIOSettings(Guid accountId) => - new() - { - AccountId = accountId, - IntegrationId = Guid.Empty, - IntegrationPassword = "-", - AccountPrivateKeyBase64 = "-", - }; - public static Instance Instance(string id, IEnumerable dataElements) => new() { Id = id, Data = [.. dataElements] }; From 285bff0dd03bc4a3fb48a3ca0a11cc4f39519121 Mon Sep 17 00:00:00 2001 From: Daniel Skovli Date: Tue, 26 May 2026 09:45:18 +0200 Subject: [PATCH 4/6] Unifies all timstamps in payload generator --- .../FiksArkivDefaultPayloadGenerator.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs index 744d5f2da1..d72473dd71 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs @@ -63,6 +63,7 @@ public async Task> GeneratePayload( $"Unsupported message type: {messageType}. {nameof(FiksArkivDefaultPayloadGenerator)} can only handle {FiksArkivConstants.MessageTypes.CreateArchiveRecord} requests." ); + var now = _timeProvider.GetLocalNow(); var appMetadata = await _appMetadata.GetApplicationMetadata(); var documentCreator = appMetadata.AppIdentifier.Org; var archiveDocuments = await GetArchiveDocuments(instance, cancellationToken); @@ -80,8 +81,8 @@ public async Task> GeneratePayload( Tittel = documentMetadata?.CaseFileTitle ?? defaultDocumentTitle, OffentligTittel = documentMetadata?.CaseFileTitle ?? defaultDocumentTitle, AdministrativEnhet = new AdministrativEnhet { Navn = documentCreator }, - Saksaar = _timeProvider.GetLocalNow().Year, - Saksdato = _timeProvider.GetLocalNow().DateTime, + Saksaar = now.Year, + Saksdato = now.DateTime, ReferanseEksternNoekkel = new EksternNoekkel { Fagsystem = appMetadata.AppIdentifier.ToString(), @@ -96,9 +97,9 @@ public async Task> GeneratePayload( var journalEntry = new Journalpost { - Journalaar = _timeProvider.GetLocalNow().Year, - DokumentetsDato = _timeProvider.GetLocalNow().DateTime, - SendtDato = _timeProvider.GetLocalNow().LocalDateTime, + Journalaar = now.Year, + DokumentetsDato = now.DateTime, + SendtDato = now.LocalDateTime, Tittel = documentMetadata?.JournalEntryTitle ?? defaultDocumentTitle, OffentligTittel = documentMetadata?.JournalEntryTitle ?? defaultDocumentTitle, OpprettetAv = documentCreator, @@ -130,12 +131,12 @@ public async Task> GeneratePayload( } // Main form data file - journalEntry.Dokumentbeskrivelse.Add(GetDocumentDescription(archiveDocuments.PrimaryDocument)); + journalEntry.Dokumentbeskrivelse.Add(GetDocumentDescription(archiveDocuments.PrimaryDocument, now)); // Attachments foreach (var attachment in archiveDocuments.AttachmentDocuments) { - journalEntry.Dokumentbeskrivelse.Add(GetDocumentDescription(attachment)); + journalEntry.Dokumentbeskrivelse.Add(GetDocumentDescription(attachment, now)); } // Archive record @@ -232,7 +233,7 @@ await _dataClient.GetDataBytes( ); } - private Dokumentbeskrivelse GetDocumentDescription(MessagePayloadWrapper payloadWrapper) + private static Dokumentbeskrivelse GetDocumentDescription(MessagePayloadWrapper payloadWrapper, DateTimeOffset now) { var documentClassification = payloadWrapper.FileTypeCode == DokumenttypeKoder.Dokument @@ -257,7 +258,7 @@ private Dokumentbeskrivelse GetDocumentDescription(MessagePayloadWrapper payload KodeProperty = documentClassification.Verdi, Beskrivelse = documentClassification.Beskrivelse, }, - OpprettetDato = _timeProvider.GetLocalNow().LocalDateTime, + OpprettetDato = now.LocalDateTime, }; metadata.Dokumentobjekt.Add( From 5c17abb72026bc48c387fed2ff961b7cbcd789dd Mon Sep 17 00:00:00 2001 From: Daniel Skovli Date: Tue, 26 May 2026 10:12:05 +0200 Subject: [PATCH 5/6] UTC datetimes --- .../FiksArkiv/FiksArkivDefaultPayloadGenerator.cs | 8 ++++---- ...atePayload_GeneratesCorrectPayload.1.verified.txt | 6 +++--- ...atePayload_GeneratesCorrectPayload.2.verified.txt | 12 ++++++------ ...atePayload_GeneratesCorrectPayload.3.verified.txt | 4 ++-- ...atePayload_GeneratesCorrectPayload.4.verified.txt | 4 ++-- ...atePayload_GeneratesCorrectPayload.5.verified.txt | 6 +++--- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs index d72473dd71..e41889ea94 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs @@ -82,7 +82,7 @@ public async Task> GeneratePayload( OffentligTittel = documentMetadata?.CaseFileTitle ?? defaultDocumentTitle, AdministrativEnhet = new AdministrativEnhet { Navn = documentCreator }, Saksaar = now.Year, - Saksdato = now.DateTime, + Saksdato = now.UtcDateTime, ReferanseEksternNoekkel = new EksternNoekkel { Fagsystem = appMetadata.AppIdentifier.ToString(), @@ -98,8 +98,8 @@ public async Task> GeneratePayload( var journalEntry = new Journalpost { Journalaar = now.Year, - DokumentetsDato = now.DateTime, - SendtDato = now.LocalDateTime, + DokumentetsDato = now.UtcDateTime, + SendtDato = now.UtcDateTime, Tittel = documentMetadata?.JournalEntryTitle ?? defaultDocumentTitle, OffentligTittel = documentMetadata?.JournalEntryTitle ?? defaultDocumentTitle, OpprettetAv = documentCreator, @@ -258,7 +258,7 @@ private static Dokumentbeskrivelse GetDocumentDescription(MessagePayloadWrapper KodeProperty = documentClassification.Verdi, Beskrivelse = documentClassification.Beskrivelse, }, - OpprettetDato = now.LocalDateTime, + OpprettetDato = now.UtcDateTime, }; metadata.Dokumentobjekt.Add( diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt index 24d6bbdb8a..7d4ecc35dd 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.1.verified.txt @@ -40,7 +40,7 @@ Dokumentet er ferdigstilt model.xml - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z H Hoveddokument @@ -67,7 +67,7 @@ Dokumentet er ferdigstilt ref-data-as-pdf.pdf - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z V Vedlegg @@ -108,6 +108,6 @@ Journalført 2025-10-24 - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt index 05b35b8194..ec3829b7e1 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.2.verified.txt @@ -40,7 +40,7 @@ Dokumentet er ferdigstilt Form.xml - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z H Hoveddokument @@ -67,7 +67,7 @@ Dokumentet er ferdigstilt Form.pdf - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z V Vedlegg @@ -94,7 +94,7 @@ Dokumentet er ferdigstilt receipt2.pdf - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z V Vedlegg @@ -121,7 +121,7 @@ Dokumentet er ferdigstilt letter.docx - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z V Vedlegg @@ -148,7 +148,7 @@ Dokumentet er ferdigstilt drawing_1a.jpg - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z V Vedlegg @@ -189,6 +189,6 @@ Journalført 2025-10-24 - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt index 7ee95e635f..3a01d9b5dd 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.3.verified.txt @@ -39,7 +39,7 @@ Dokumentet er ferdigstilt Form.xml - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z H Hoveddokument @@ -96,6 +96,6 @@ Journalført 2025-10-24 - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt index 3b4d5d3dec..15767f0c05 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.4.verified.txt @@ -38,7 +38,7 @@ Dokumentet er ferdigstilt Form.xml - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z H Hoveddokument @@ -90,6 +90,6 @@ Journalført 2025-10-24 - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z \ No newline at end of file diff --git a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt index 557442bddf..9b7b4f2587 100644 --- a/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt +++ b/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/.Verify/FiksArkivDefaultPayloadGeneratorTest.GeneratePayload_GeneratesCorrectPayload.5.verified.txt @@ -51,7 +51,7 @@ Dokumentet er ferdigstilt Form.pdf - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z H Hoveddokument @@ -78,7 +78,7 @@ Dokumentet er ferdigstilt ref-data-as-pdf.pdf - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z V Vedlegg @@ -119,6 +119,6 @@ Journalført 2025-10-24 - 2025-10-24T11:58:00+02:00 + 2025-10-24T09:58:00Z \ No newline at end of file From 118534e9ce0413b9941479c5159f198ce8cda7eb Mon Sep 17 00:00:00 2001 From: Daniel Skovli Date: Tue, 26 May 2026 11:08:49 +0200 Subject: [PATCH 6/6] now=utcnow for consistency --- .../FiksArkiv/FiksArkivDefaultPayloadGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs index e41889ea94..ad28b0d5cf 100644 --- a/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs +++ b/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultPayloadGenerator.cs @@ -63,7 +63,7 @@ public async Task> GeneratePayload( $"Unsupported message type: {messageType}. {nameof(FiksArkivDefaultPayloadGenerator)} can only handle {FiksArkivConstants.MessageTypes.CreateArchiveRecord} requests." ); - var now = _timeProvider.GetLocalNow(); + var now = _timeProvider.GetUtcNow(); var appMetadata = await _appMetadata.GetApplicationMetadata(); var documentCreator = appMetadata.AppIdentifier.Org; var archiveDocuments = await GetArchiveDocuments(instance, cancellationToken);