microsoft / ALAppExtensions

Repository for collaboration on Microsoft AL application add-on and localization extensions for Microsoft Dynamics 365 Business Central.
MIT License
758 stars 601 forks source link

[Parameter Request] table 1237 "Transformation Rule" - OnBeforeIsDataFormatUpdateAllowed(Rec, ...) #8955

Closed fvet closed 3 years ago

fvet commented 3 years ago

We've created our own transformation rules

[EventSubscriber(ObjectType::Table, Database::"Transformation Rule", 'OnCreateTransformationRules', '', false, false)]
    local procedure OnCreateTransformationRules()
    var
        GLRoundingDesc: label 'Rouding (GL Setup)';
        GLCurrencyDesc: label 'LCY Code (GL Setup)';
        TransformationRule: Record "Transformation Rule";
        FormatDateDesc: label 'Format Date';
        AmountToTextDesc: label 'Amount > Text';
    begin
        with TransformationRule do begin
            InsertRec(GLRounding(), GLRoundingDesc, "transformation type"::Custom, 0, 0, '', '');
            InsertRec(GLCurrency(), GLCurrencyDesc, "transformation type"::Custom, 0, 0, '', '');
            InsertRec(FormatDate(), FormatDateDesc, "transformation type"::Custom, 0, 0, '<Day,2>/<Month,2>/<Year4>', ''); // This one is important
            InsertRec(AmountToText(), AmountToTextDesc, "transformation type"::Custom, 0, 0, '', '');
        end;
    end;

Upon creation of a new company, we get an error in the event viewer:

Server instance: Install_BE_NL
Category: EventSubscription
ClientSessionId: ccdfdcbe-734a-4573-bc6c-c7fd774422c1
ClientActivityId: 3b3875ae-b51d-44b9-9eb2-8e3a3ac89f9c
ServerSessionUniqueId: 8d229087-89ac-4d38-aef2-57022aa4f5c6
ServerActivityId: 5f520084-0fe6-457f-9dc5-bc5f3ed5746d
EventTime: 09/29/2020 13:16:50
Message (NavTestFieldException): EventSignature failure: SubScriber assy = Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704, COD_2002704_C1FA106653E663232B76C71D4D8249098FFF8A4167A757EC7EC4B03134E7FAD9, Version=16.0.14073.14195, Culture=neutral, PublicKeyToken=null, target assy = Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704, COD_2002704_C1FA106653E663232B76C71D4D8249098FFF8A4167A757EC7EC4B03134E7FAD9, Version=16.0.14073.14195, Culture=neutral, PublicKeyToken=null, Subscriber signature = 'System.Void Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704.OnCreateTransformationRules()', target signature = 'Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704NVT Transformation Rule Mgt.[ID=2002704]()'
RootException: NavTestFieldException
Gegevensopmaak moet gelijk zijn aan  in Transformatieregel: Code=FORMAT_DATE. De huidige waarde is <Day,2>/<Month,2>/<Year4>.
ExceptionStackTrace:
   at Microsoft.Dynamics.Nav.Runtime.NavRecord.TestFieldError(NCLMetaField metaField, String shouldBeValue)
   at Microsoft.Dynamics.Nav.Runtime.NavRecord.TestFieldEquals(NCLMetaField metaField, String testValue)
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.Data_Format_a45_OnValidate_Scope.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.Data_Format_a45_OnValidate()
   at Microsoft.Dynamics.Nav.Runtime.NavRecord.ValidateField(FieldTriggerHandler`1 fieldEvent, NCLMetaField metaField, Boolean isUserInput, List`1 beforeHandlers, List`1 afterHandlers)
   at Microsoft.Dynamics.Nav.Runtime.NavRecord.Validate(NCLMetaField metaField, NavValue newValue, NavRecord callerRecord, Boolean isUserInput)
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.InsertRec_Scope_2129941236.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.InsertRec(NavCode newCode, NavText newDescription, Int32 newTransformationType, Int32 newStartPosition, Int32 newLength, NavText newDataFormat, NavText newDataFormattingCulture)
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704.OnCreateTransformationRules_Scope.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704.OnCreateTransformationRules()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriberInternal(NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)
CallerStackTrace:
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriberInternal(NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)
   at Microsoft.Dynamics.Nav.Runtime.NavRecord.TestFieldError(NCLMetaField metaField, String shouldBeValue)
   at Microsoft.Dynamics.Nav.Runtime.NavRecord.TestFieldEquals(NCLMetaField metaField, String testValue)
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.Data_Format_a45_OnValidate_Scope.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.Data_Format_a45_OnValidate()
   at Microsoft.Dynamics.Nav.Runtime.NavRecord.ValidateField(FieldTriggerHandler`1 fieldEvent, NCLMetaField metaField, Boolean isUserInput, List`1 beforeHandlers, List`1 afterHandlers)
   at Microsoft.Dynamics.Nav.Runtime.NavRecord.Validate(NCLMetaField metaField, NavValue newValue, NavRecord callerRecord, Boolean isUserInput)
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.InsertRec_Scope_2129941236.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.InsertRec(NavCode newCode, NavText newDescription, Int32 newTransformationType, Int32 newStartPosition, Int32 newLength, NavText newDataFormat, NavText newDataFormattingCulture)
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704.OnCreateTransformationRules_Scope.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704.OnCreateTransformationRules()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2002704.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriberInternal(NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriber(NavApplicationObjectBase callingApplicationObject, NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.ProcessCallToTypeAndManualSubscriptions(NavApplicationObjectBase callerApplicationObject, NavEventSubscription[] subscriptions, PrepareParametersCallBack prepareParameters)
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.OnRunEvent()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.OnCreateTransformationRules()
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.CreateDefaultTransformations_Scope_1444744758.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.CreateDefaultTransformations()
   at Microsoft.Dynamics.Nav.BusinessApplication.Record1237.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2.OnRun_Scope.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2.OnRun(INavRecordHandle εrec)
   at Microsoft.Dynamics.Nav.Runtime.NavCodeunit.DoRun(DataError errorLevel, NavRecord record)
   at Microsoft.Dynamics.Nav.Runtime.NavCodeunit.RunCodeunit(DataError errorLevel, Int32 objectId)
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit40.InitializeCompany_Scope_1598126349.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit40.InitializeCompany()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit40.LogInStart_Scope_1908188324.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit40.LogInStart()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit40.CompanyOpen_Scope_461255091.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit40.CompanyOpen()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit40.OnCompanyOpen()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit40.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriberInternal(NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriber(NavApplicationObjectBase callingApplicationObject, NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.ProcessCallToTypeAndManualSubscriptions(NavApplicationObjectBase callerApplicationObject, NavEventSubscription[] subscriptions, PrepareParametersCallBack prepareParameters)
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.OnRunEvent()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit150.OnAfterInitialization()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit150.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit151.Init_Scope.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit151.Init()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit151.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriberInternal(NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriber(NavApplicationObjectBase callingApplicationObject, NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)
   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.ProcessCallToTypeAndManualSubscriptions(NavApplicationObjectBase callerApplicationObject, NavEventSubscription[] subscriptions, PrepareParametersCallBack prepareParameters)
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.OnRunEvent()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2000000003.OnCompanyOpen()
   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit2000000003.OnInvoke(Int32 memberId, Object[] args)
   at Microsoft.Dynamics.Nav.Runtime.NavSystemCodeunit.Invoke(Int32 methodId, Object[] arguments)
   at Microsoft.Dynamics.Nav.Runtime.SessionTransactionManager.TransactionScope(Action code)
   at Microsoft.Dynamics.Nav.Diagnostic.NavDiagnostics.<>c__DisplayClass106_0.<SendTraceTagOnThreshold>b__0(Stopwatch watch)
   at Microsoft.Dynamics.Nav.Diagnostic.NavDiagnostics.SendTraceTagOnThreshold[T](String tag, Category category, Verbosity verbosity, Int32 threshold, Func`2 action, PrivacyClassification classification, Func`1 includedMessage, String message, Func`1 parameters)
   at Microsoft.Dynamics.Nav.Runtime.NavSession.OpenCompany(String companyName, Boolean updateUserPersonalization, Boolean openedForRenameOrDelete)
   at Microsoft.Dynamics.Nav.Service.NSService.OpenCompany(String companyName, Boolean overridePersonalization)
   at SyncInvokeOpenCompany(Object , Object[] , Object[] )
   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.ErrorMappingCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, MethodBase syncMethod, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass28_1.<Combine>b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.PushPopCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, MethodBase syncMethod, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass28_1.<Combine>b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationTracer.TraceScopeCombinator(Category telemetryCategory, ServiceOperation innerOperation, NSServiceBase serviceInstance, MethodBase syncMethod, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass28_1.<Combine>b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass10_0.<PerformanceCounterCombinator>b__0()
   at Microsoft.Dynamics.Nav.Runtime.NavPerformanceCounterSetter.UpdatePerformanceCountersWithAverageServiceOperationDuration(Stopwatch stopWatch, Action action)
   at Microsoft.Dynamics.Nav.Runtime.NavPerformanceCounterSetter.UpdatePerformanceCountersWithAverageServiceOperationAction(Action action, NavSession session)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.PerformanceCounterCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, MethodBase syncMethod, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass28_1.<Combine>b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.InitClientTelemetryIdsCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, MethodBase syncMethod, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass28_1.<Combine>b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.TlsClearCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, MethodBase syncMethod, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass28_1.<Combine>b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
   at System.ServiceModel.Dispatcher.MessageRpc.Wrapper.Resume(Boolean& alreadyResumedNoLock)
   at System.ServiceModel.Dispatcher.ThreadBehavior.ResumeProcessing(IResumeMessageRpc resume)
   at Microsoft.Dynamics.Nav.Runtime.NavSynchronizationContext.<>c__DisplayClass1_0.<ClearThreadLocalStorageDelegate>b__0(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

ProcessId: 45588
Tag: 000008Y
ThreadId: 201
CounterInformation: 
CustomParameters: {
}
GatewayCorrelationId: 3b3875ae-b51d-44b9-9eb2-8e3a3ac89f9c

Reason is this line

InsertRec(FormatDate(), FormatDateDesc, "transformation type"::Custom, 0, 0, '<Day,2>/<Month,2>/<Year4>', '');

Apparently, the IsDataFormatUpdateAllowed results in this error, so we should have made use of the new OnBeforeIsDataFormatUpdateAllowed publisher. However, the CurrFieldNo parameter is the publisher is not sufficient to decide if DataFormatUpdateAllowed can be set.

We'd like to get access to Rec in OnBeforeIsDataFormatUpdateAllowed, so I can test that my transformation rule with Code = 'FORMAT DATE' and "transformation type"::Custom can pass the OnBeforeIsDataFormatUpdateAllowed test.

bc-ghost commented 3 years ago

Thanks for reporting this. We agree, and we’ll publish a fix asap, either in an update for the current version or in the next major release. We will update this issue with information about availability.