Skip to content
Closed
Show file tree
Hide file tree
Changes from 81 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
1bd93cd
init commit
Jul 17, 2026
61b2627
phase 2
Jul 17, 2026
ad43c02
new phase changes
Jul 17, 2026
ff48b53
update
Jul 17, 2026
4c75db9
more changes
Jul 17, 2026
9fe2fe0
new
Jul 17, 2026
830b06a
remaining lifecycle hardening
Jul 17, 2026
c9a68a1
improvements
Jul 17, 2026
92b361d
init
github-actions[bot] Jul 21, 2026
9d7abd8
use standard comment table
github-actions[bot] Jul 21, 2026
2aa69d6
removed tooltips from pages
github-actions[bot] Jul 21, 2026
1f46ee3
added test
github-actions[bot] Jul 21, 2026
17b02fb
removed copy comments as standard works
github-actions[bot] Jul 21, 2026
02cc439
revert 1
github-actions[bot] Jul 21, 2026
3d236c4
"FR Regulatory Comment Type" extended and added more options
Jul 22, 2026
d07ae2d
update permissions
Jul 22, 2026
8f3d925
Fix AL0129 in InjectExtendedCTCFranceElements: introduce local XmlEle…
Copilot Jul 22, 2026
f1b4252
new update
Jul 27, 2026
fb05a47
fix for node
Jul 27, 2026
f40c964
payment means
Jul 27, 2026
00f027f
Revert "payment means"
Jul 27, 2026
954d554
updated tooltip for prefix comment
Jul 27, 2026
75e9f23
Merge remote-tracking branch 'origin/main' into bugs/master_442216_Pa…
Jul 27, 2026
f6127a6
added missing using
Jul 27, 2026
99f9a7b
typo
Jul 27, 2026
2932ad5
Fix AA0477: sort using statements alphabetically
Jul 28, 2026
c2c9850
new test update
Jul 29, 2026
69783c8
new
Jul 29, 2026
558c555
Fix E-Reporting FR analyzer warnings
Jul 30, 2026
8c662c3
Address E-Reporting FR review feedback
Jul 30, 2026
1415fce
Test regulatory comments on credit memos
Jul 30, 2026
5616cf2
Fix French electronic address validation
Jul 30, 2026
bf3623e
corrections
Jul 30, 2026
2a0e1b7
fix for vat reg. no in tests
Jul 30, 2026
29038d0
peppol test fix
Jul 30, 2026
f537de9
new
Jul 30, 2026
ac3cc63
NEW
Jul 30, 2026
a472b8c
new changes for shipments
Jul 31, 2026
bbabfed
Apply suggestion from @github-actions[bot]
djukicmilica Aug 4, 2026
b35af92
new changes
Aug 4, 2026
3c049c4
Merge branch 'djukicmilica/fr-extended-ctc' of https://github.com/mic…
Aug 4, 2026
234f301
correction
Aug 4, 2026
121b808
update
Aug 4, 2026
129115e
extended billing mode
Aug 4, 2026
900be70
BillingMode
Aug 4, 2026
897bd33
added .xml file extension
Aug 4, 2026
b965f37
optimizations
Aug 4, 2026
bdb6afd
update tests
Aug 5, 2026
e92887b
PR comments changes
Aug 5, 2026
7978a24
Merge branch 'main' into bugs/master_442216_Payments
Aug 5, 2026
d7c0a5e
Merge branch 'djukicmilica/fr-extended-ctc' into bugs/master_442216_P…
Aug 5, 2026
3facb2a
new
Aug 5, 2026
f1a78dd
changed internal procedures
Aug 5, 2026
af0e365
add CreateMessage public
Aug 5, 2026
fde55a7
FrenchLifecycle visibility
Aug 5, 2026
4d309b7
testing changes
Aug 5, 2026
1b1854b
test update + remaing files
Aug 5, 2026
9980d73
tests update
Aug 6, 2026
ec0ed78
PR review changes
Aug 8, 2026
788f105
bb changes
Aug 8, 2026
b82be2c
fix tests
Aug 8, 2026
24a6fc0
fix tests
Aug 9, 2026
ed1f6e7
typo
Aug 9, 2026
d4437dc
new tests changes
Aug 10, 2026
8efbd16
tests updates
Aug 11, 2026
fad76f7
PR review comments
github-actions[bot] Aug 11, 2026
e61151f
PR comments fixes
github-actions[bot] Aug 11, 2026
7136c8e
compile errs
Aug 11, 2026
651c790
new tests
Aug 12, 2026
c3889fa
currency fix
Aug 12, 2026
f16546d
fix
Aug 12, 2026
1d6b65b
cleantag
Aug 13, 2026
785dbaf
fix
Aug 13, 2026
12e77fb
fixes
Aug 13, 2026
e3afb87
new PR comments
Aug 14, 2026
4a34336
new
Aug 14, 2026
991cdd7
more fixes
Aug 14, 2026
2e2409c
Merge branch 'main' into bugs/master_442216_Payments
Aug 14, 2026
6a2ead0
fix object ID
Aug 14, 2026
e53bb79
removed tablerelations
Aug 15, 2026
96b4383
currency changes
Aug 15, 2026
3d4bab7
error changed
Aug 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ codeunit 10978 "CII XML Builder"
exit('0009');
ElecAddressScheme::"0002":
exit('0002');
ElecAddressScheme::"0225":
Comment thread
djukicmilica marked this conversation as resolved.
exit('0225');
ElecAddressScheme::"9957":
exit('9957');
else
exit(Format(ElecAddressScheme));
end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,71 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.eServices.EDocument.Formats;

using Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.Service.Participant;
using Microsoft.Foundation.Company;
using Microsoft.Sales.Customer;
using Microsoft.Utilities;

codeunit 10991 "EDoc. Helpers"
{
Access = Internal;
Permissions = tabledata "E-Document" = m,
tabledata "E-Document Service Status" = m;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Data Classification Eval. Data", 'OnCreateEvaluationDataOnAfterClassifyTablesToNormal', '', false, false)]
local procedure ClassifyDataSensitivity()
var
DataClassificationEvalData: Codeunit "Data Classification Eval. Data";
begin
DataClassificationEvalData.SetTableFieldsToNormal(Database::"FR E-Invoice Lifecycle");
DataClassificationEvalData.SetTableFieldsToNormal(Database::"FR E-Invoice Lifecycle VAT");
end;

[EventSubscriber(ObjectType::Table, Database::"E-Document", 'OnBeforeModifyEvent', '', false, false)]
Comment thread
djukicmilica marked this conversation as resolved.
Comment thread
djukicmilica marked this conversation as resolved.
local procedure SetClearanceDateOnModify(var Rec: Record "E-Document"; var xRec: Record "E-Document"; RunTrigger: Boolean)
var
EDocumentServiceStatus: Record "E-Document Service Status";
EDocumentService: Record "E-Document Service";
begin
if not GetFrenchEDocumentService(Rec, EDocumentService, EDocumentServiceStatus) then
exit;

case EDocumentServiceStatus.Status of
Comment thread
djukicmilica marked this conversation as resolved.
EDocumentServiceStatus.Status::Approved,
EDocumentServiceStatus.Status::Cleared:
if Rec."Clearance Date" = 0DT then
Rec."Clearance Date" := CurrentDateTime();
EDocumentServiceStatus.Status::Rejected,
EDocumentServiceStatus.Status::"Not Cleared":
Rec."Clearance Date" := 0DT;
end;
end;

local procedure IsFrenchElectronicDocumentFormat(EDocumentFormat: Enum "E-Document Format"): Boolean
begin
exit(
EDocumentFormat in
[EDocumentFormat::"E-Reporting FR", EDocumentFormat::"Peppol BIS 3.0 FR", EDocumentFormat::"Factur-X FR"]);
end;

procedure GetFrenchEDocumentService(EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status"): Boolean
begin
EDocumentService.SetLoadFields("Document Format");
if (EDocument.Service <> '') and EDocumentService.Get(EDocument.Service) then
if IsFrenchElectronicDocumentFormat(EDocumentService."Document Format") then
exit(EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code));

EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No");
if EDocumentServiceStatus.FindSet() then
repeat
if EDocumentService.Get(EDocumentServiceStatus."E-Document Service Code") then
if IsFrenchElectronicDocumentFormat(EDocumentService."Document Format") then
exit(true);
until EDocumentServiceStatus.Next() = 0;

exit(false);
end;

procedure FindFieldByName(RecRef: RecordRef; FieldName: Text; var FieldRefResult: FieldRef): Boolean
var
Expand Down Expand Up @@ -46,7 +105,9 @@ codeunit 10991 "EDoc. Helpers"
begin
CompanyInformation.Get();
if CompanyInformation."Registration No." = '' then
Error(SIRENRequiredErr);
RaiseCompanyInformationError(
CompanyInformation,
StrSubstNo(SIRENRequiredErr, CompanyInformation.FieldCaption("Registration No."), CompanyInformation.TableCaption()));
end;

procedure CheckSIRETNotEmpty()
Expand All @@ -55,7 +116,33 @@ codeunit 10991 "EDoc. Helpers"
begin
CompanyInformation.Get();
if CompanyInformation."SIRET No." = '' then
Error(SIRETRequiredErr);
RaiseCompanyInformationError(
CompanyInformation,
StrSubstNo(SIRETRequiredErr, CompanyInformation.FieldCaption("SIRET No."), CompanyInformation.TableCaption()));
end;

procedure CheckSellerElectronicAddress(EDocumentServiceCode: Code[20])
Comment thread
djukicmilica marked this conversation as resolved.
var
CompanyInformation: Record "Company Information";
ServiceParticipant: Record "Service Participant";
begin
if HasServiceParticipantAddress(EDocumentServiceCode, Enum::"E-Document Source Type"::Company, '') then
exit;

CompanyInformation.Get();
if CompanyInformation."SIRET No." <> '' then
exit;
if CompanyInformation."Registration No." <> '' then
exit;
if CompanyInformation.GetVATRegistrationNumber() <> '' then
exit;

RaiseCompanyInformationError(
CompanyInformation,
StrSubstNo(
SellerElectronicAddressRequiredErr, CompanyInformation.FieldCaption("SIRET No."),
CompanyInformation.FieldCaption("Registration No."), CompanyInformation.FieldCaption("VAT Registration No."),
ServiceParticipant.TableCaption()));
end;

procedure CheckSellerCountryCode()
Expand All @@ -64,12 +151,20 @@ codeunit 10991 "EDoc. Helpers"
begin
CompanyInformation.Get();
if CompanyInformation."Country/Region Code" = '' then
Error(SellerCountryCodeRequiredErr);
RaiseCompanyInformationError(
CompanyInformation,
StrSubstNo(SellerCountryCodeRequiredErr, CompanyInformation.FieldCaption("Country/Region Code"), CompanyInformation.TableCaption()));
end;

procedure CheckBuyerElectronicAddress(var SourceDocumentHeader: RecordRef)
begin
CheckBuyerElectronicAddress(SourceDocumentHeader, '');
end;

procedure CheckBuyerElectronicAddress(var SourceDocumentHeader: RecordRef; EDocumentServiceCode: Code[20])
var
Customer: Record Customer;
ServiceParticipant: Record "Service Participant";
FRCIIXMLBuilder: Codeunit "CII XML Builder";
CustomerNoFieldRef: FieldRef;
CustomerNo: Code[20];
Expand All @@ -81,16 +176,97 @@ codeunit 10991 "EDoc. Helpers"
if CustomerNo = '' then
exit;

if HasServiceParticipantAddress(EDocumentServiceCode, Enum::"E-Document Source Type"::Customer, CustomerNo) then
exit;

Customer.SetLoadFields("FR Electronic Address", "FR Elec. Address Scheme", "VAT Registration No.");
Comment thread
djukicmilica marked this conversation as resolved.
if not Customer.Get(CustomerNo) then
exit;

if Customer."FR Electronic Address" = '' then
Error(BuyerElectronicAddressRequiredErr, Customer."No.");
if Customer."FR Electronic Address" <> '' then begin
Comment thread
djukicmilica marked this conversation as resolved.
Comment thread
djukicmilica marked this conversation as resolved.
Comment thread
djukicmilica marked this conversation as resolved.
if Customer."FR Elec. Address Scheme" = Customer."FR Elec. Address Scheme"::" " then
RaiseCustomerError(
Customer, StrSubstNo(BuyerElectronicAddressSchemeRequiredErr, Customer.FieldCaption("FR Elec. Address Scheme")));
exit;
end;
if Customer."VAT Registration No." <> '' then
exit;

RaiseCustomerError(
Customer,
StrSubstNo(
BuyerElectronicAddressRequiredErr, Customer.FieldCaption("FR Electronic Address"),
Customer.FieldCaption("VAT Registration No."), ServiceParticipant.TableCaption()));
end;

procedure HasServiceParticipantAddress(EDocumentServiceCode: Code[20]; ParticipantType: Enum "E-Document Source Type"; ParticipantNo: Code[20]): Boolean
var
ServiceParticipant: Record "Service Participant";
begin
exit(HasServiceParticipantAddress(EDocumentServiceCode, ParticipantType, ParticipantNo, ServiceParticipant));
end;

procedure HasServiceParticipantAddress(EDocumentServiceCode: Code[20]; ParticipantType: Enum "E-Document Source Type"; ParticipantNo: Code[20]; var ServiceParticipant: Record "Service Participant"): Boolean
var
ParticipantAddressErrorInfo: ErrorInfo;
HasIdentifier: Boolean;
HasScheme: Boolean;
begin
if EDocumentServiceCode = '' then
exit(false);
if not ServiceParticipant.Get(EDocumentServiceCode, ParticipantType, ParticipantNo) then
exit(false);

HasIdentifier := ServiceParticipant."Participant Identifier" <> '';
HasScheme := ServiceParticipant."FR Identifier Scheme" <> ServiceParticipant."FR Identifier Scheme"::" ";
if HasIdentifier <> HasScheme then begin
ParticipantAddressErrorInfo.Title(StrSubstNo(SetupIncompleteTitleLbl, ServiceParticipant.TableCaption()));
ParticipantAddressErrorInfo.Message(
Comment thread
djukicmilica marked this conversation as resolved.
StrSubstNo(ServiceParticipantAddressIncompleteErr, ServiceParticipant.FieldCaption("Participant Identifier"), ServiceParticipant.FieldCaption("FR Identifier Scheme")));
ParticipantAddressErrorInfo.DetailedMessage(ParticipantAddressErrorInfo.Message());
ParticipantAddressErrorInfo.RecordId(ServiceParticipant.RecordId());
ParticipantAddressErrorInfo.PageNo(Page::"Service Participants");
ParticipantAddressErrorInfo.AddNavigationAction(StrSubstNo(ShowRecordLbl, ServiceParticipant.TableCaption()));
Error(ParticipantAddressErrorInfo);
end;

exit(HasIdentifier);
end;

local procedure RaiseCompanyInformationError(CompanyInformation: Record "Company Information"; ErrorMessage: Text)
var
CompanyInformationErrorInfo: ErrorInfo;
begin
CompanyInformationErrorInfo.Title(StrSubstNo(SetupIncompleteTitleLbl, CompanyInformation.TableCaption()));
CompanyInformationErrorInfo.Message(ErrorMessage);
CompanyInformationErrorInfo.DetailedMessage(ErrorMessage);
CompanyInformationErrorInfo.RecordId(CompanyInformation.RecordId());
CompanyInformationErrorInfo.PageNo(Page::"Company Information");
CompanyInformationErrorInfo.AddNavigationAction(StrSubstNo(ShowRecordLbl, CompanyInformation.TableCaption()));
Error(CompanyInformationErrorInfo);
end;

local procedure RaiseCustomerError(Customer: Record Customer; ErrorMessage: Text)
Comment thread
djukicmilica marked this conversation as resolved.
var
CustomerErrorInfo: ErrorInfo;
begin
CustomerErrorInfo.Title(StrSubstNo(SetupIncompleteTitleLbl, Customer.TableCaption()));
CustomerErrorInfo.Message(ErrorMessage);
Comment thread
djukicmilica marked this conversation as resolved.
CustomerErrorInfo.DetailedMessage(ErrorMessage);
CustomerErrorInfo.RecordId(Customer.RecordId());
CustomerErrorInfo.PageNo(Page::"Customer Card");
CustomerErrorInfo.AddNavigationAction(StrSubstNo(ShowRecordLbl, Customer.TableCaption()));
Error(CustomerErrorInfo);
end;

var
SIRENRequiredErr: Label 'Registration No. must be specified in Company Information for French e-invoicing.';
SIRETRequiredErr: Label 'SIRET No. must be specified in Company Information for French e-invoicing.';
BuyerElectronicAddressRequiredErr: Label 'Electronic Address must be specified for Customer %1 for French e-invoicing.', Comment = '%1 = Customer No.';
SellerCountryCodeRequiredErr: Label 'Country/Region Code must be specified in Company Information for French e-invoicing.';
SetupIncompleteTitleLbl: Label '%1 setup is incomplete', Comment = '%1 = table caption';
ShowRecordLbl: Label 'Show %1', Comment = '%1 = table caption';
SIRENRequiredErr: Label '%1 must be specified in %2 for French e-invoicing.', Comment = '%1 = Registration No. field caption, %2 = Company Information table caption';
SIRETRequiredErr: Label '%1 must be specified in %2 for French e-invoicing.', Comment = '%1 = SIRET No. field caption, %2 = Company Information table caption';
SellerElectronicAddressRequiredErr: Label '%1, %2, %3, or a %4 identifier must be specified for the company for French e-invoicing.', Comment = '%1 = SIRET No. field caption, %2 = Registration No. field caption, %3 = VAT Registration No. field caption, %4 = Service Participant table caption';
BuyerElectronicAddressRequiredErr: Label '%1, %2, or a %3 identifier must be specified for the customer for French e-invoicing.', Comment = '%1 = Electronic Address field caption, %2 = VAT Registration No. field caption, %3 = Service Participant table caption';
BuyerElectronicAddressSchemeRequiredErr: Label '%1 must be specified for the customer for French e-invoicing.', Comment = '%1 = Electronic Address Scheme field caption';
SellerCountryCodeRequiredErr: Label '%1 must be specified in %2 for French e-invoicing.', Comment = '%1 = Country/Region Code field caption, %2 = Company Information table caption';
ServiceParticipantAddressIncompleteErr: Label '%1 and %2 must both be specified for French electronic invoicing.', Comment = '%1 = Participant Identifier field caption, %2 = French Identifier Scheme field caption';
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,16 @@ enum 10976 "Electronic Address Scheme"
{
Caption = 'SIREN (0002)';
}
value(3; " ")
{
Caption = ' ';
}
value(4; "0225")
{
Caption = 'FRCTC electronic address (0225)';
}
value(5; "9957")
{
Caption = 'French VAT number (9957)';
}
}
Loading
Loading