Jetzt gibt es auch ein Beispiel Projekt mit folgenden Features:
1)
XML laden und Kontrollrechnung ausführen
2)
XML laden um Rechnungsdaten vorzubelegen (Adresse etc)
3) Aus Rechnungsdaten neue
XML erzeugen
4) Geladene oder erzeugte Daten als Pascal Quellcode abspeichern
Dies ist der implementation code des Demo Projekts:
Code:
{ TInvoiceCompanyData }
procedure TInvoiceCompanyData.ReadFromStrings(str: TStrings);
begin
Name := str.Values['Name'];
PostcodeCode := str.Values['PostcodeCode'];
Addres := str.Values['Addres'];
CityName := str.Values['CityName'];
CountryIDText := str.Values['CountryID'];
// Optional
DepartmentName := str.Values['DepartmentName'];
// Required for Seller
TAXId := str.Values['TAXId'];
// Required for EU Sales
VATID := str.Values['VATID'];
// Optional: Full text, several lines for Seller!
ContactInfo := str.Values['ContactInfo'];
// Optional
ID := str.Values['ID'];
GlobalID := str.Values['GlobalID'];
GlobalIDScheme := str.Values['GlobalIDScheme'];
// Optional, Reg Nr
SpecifiedLegalOrganization := str.Values['SpecifiedLegalOrganization'];
end;
procedure TInvoiceCompanyData.WriteToStrings(str: TStrings);
begin
str.Values['Name'] := Name;
str.Values['PostcodeCode'] := PostcodeCode;
str.Values['Addres'] := Addres;
str.Values['CityName'] := CityName;
str.Values['CountryID'] := CountryIDText;
// Optional
str.Values['DepartmentName'] := DepartmentName;
// Required for Seller
str.Values['TAXId'] := TAXId;
// Required for EU Sales
str.Values['VATID'] := VATID;
// Optional: Full text, several lines for Seller!
str.Values['ContactInfo'] := ContactInfo;
// Optional
str.Values['ID'] := ID;
str.Values['GlobalID'] := GlobalID;
str.Values['GlobalIDScheme'] := GlobalIDScheme;
// Optional, Reg Nr
str.Values['SpecifiedLegalOrganization'] := SpecifiedLegalOrganization;
end;
procedure TInvoiceForm.SaveasDelphiCode1Click(Sender: TObject);
begin
SaveDialog1.FilterIndex := 1;
if SaveDialog1.Execute then
WPXFactur1.SaveToFile(SaveDialog1.FileName, TWPXOrderDumpMode.DelphiCodeCompact);
end;
procedure TInvoiceForm.SaveXML1Click(Sender: TObject);
begin
SaveDialog1.FilterIndex := 0;
if SaveDialog1.Execute then
WPXFactur1.SaveToFile(SaveDialog1.FileName);
end;
procedure TInvoiceForm.btnCalculateClick(Sender: TObject);
begin
WPXFactur1.VerifySummation;
outText.Lines := WPXFactur1.Messages;
end;
procedure TInvoiceForm.btnGenerateInvoiceClick(Sender: TObject);
var i : Integer;
begin
WPXPaymentData.DueDateDateTime := Now;
WPXPaymentData.TAXCategory := TTaxCategory(taxCombo.ItemIndex);
WPXFactur1.StartInvoice(
TDocumentCode.c380_Commercial_invoice,
WPXPaymentData.DueDateDateTime,
edREID.Text,
edREName.Text,
WPXSeller, WPXBuyer, nil,
nil, // from Order
WPXOrderData,
nil,
WPXPaymentData
);
for I := 1 to ItemGrid.RowCount-1 do
if ItemGrid.Cells[1,i]<>'' then
begin
WPXFactur1.AddSale(
ItemGrid.Cells[1,i],
WPXCurrencyStrToFloat( ItemGrid.Cells[2,i] ),
WPXCurrencyStrToFloat( ItemGrid.Cells[3,i] ),
WPXCurrencyStrToFloat( ItemGrid.Cells[5,i] ),
WPXPaymentData.TAXCategory );
end;
WPXFactur1.FinalizeInvoice(true,TCurrencyCode.EUR,0,WPXPaymentData);
outText.Lines.Assign(WPXFactur1.Messages);
end;
procedure TInvoiceForm.FormCreate(Sender: TObject);
begin
WPXFactur1 := TWPXFactur.Create(Self);
WPXSeller := TInvoiceCompanyData.Create;
WPXBuyer := TInvoiceCompanyData.Create;
WPXShipTo := TInvoiceCompanyData.Create;
WPXPaymentData := TPaymentData.Create;
WPXOrderData := TOrderData.Create;
ReadItems;
end;
procedure TInvoiceForm.FormDestroy(Sender: TObject);
begin
WPXFactur1.Free;
WPXSeller.Free;
WPXBuyer.Free;
WPXShipTo.Free;
WPXPaymentData.Free;
WPXOrderData.Free;
end;
procedure TInvoiceForm.LoadXML1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
WPXFactur1.LoadFromFile(OpenDialog1.FileName);
WPXFactur1.ReadCompanyData(WPXSeller,TReadCompanyDataMode.Seller);
WPXFactur1.ReadCompanyData(WPXBuyer,TReadCompanyDataMode.Buyer);
WPXFactur1.ReadCompanyData(WPXShipTo,TReadCompanyDataMode.ShipTo);
// WPXFactur1.ReadCompanyData(xxx,TReadCompanyDataMode.Payee);
WPXSeller.WriteToStrings(valSeller.Strings);
WPXBuyer.WriteToStrings(valBuyer.Strings);
ReadItems;
end;
end;
procedure TInvoiceForm.ReadItems;
var i : Integer;
item : TSupplyChainTradeItem;
begin
ItemGrid.RowCount := 0;
ItemGrid.RowCount := WPXFactur1.Transaction.Items.Count + 4;
ItemGrid.ColCount := 7;
ItemGrid.Cells[0,0] := 'LineID';
ItemGrid.Cells[1,0] := 'Name';
ItemGrid.Cells[2,0] := 'Net Charge';
ItemGrid.Cells[3,0] := 'Quantity';
ItemGrid.Cells[4,0] := 'TAX Category';
ItemGrid.Cells[5,0] := 'RateApplicablePercent';
ItemGrid.Cells[6,0] := 'LineTotalAmount';
for i := 1 to WPXFactur1.Transaction.Items.Count do
begin
item := WPXFactur1.Transaction.Items[i-1];
with item.Line do
begin
ItemGrid.Cells[0,i] := AssociatedDocumentLineDocument.LineID.ValueStr;
ItemGrid.Cells[1,i] := SpecifiedTradeProduct.Name.ValueStr;
ItemGrid.Cells[2,i] := SpecifiedLineTradeAgreement.NetPriceProductTradePrice.ChargeAmount.ValueStr;
ItemGrid.Cells[3,i] := SpecifiedLineTradeAgreement.NetPriceProductTradePrice.BasisQuantity.ValueStr;
if ItemGrid.Cells[3,i]='' then ItemGrid.Cells[3,i] := '1';
ItemGrid.Cells[4,i] := SpecifiedLineTradeSettlement.ApplicableTradeTax.CategoryCode.ValueStr;
ItemGrid.Cells[5,i] := SpecifiedLineTradeSettlement.ApplicableTradeTax.RateApplicablePercent.ValueStr;
ItemGrid.Cells[6,i] := SpecifiedLineTradeSettlement.SpecifiedTradeSettlementLineMonetarySummation.LineTotalAmount.ValueStr;
// ItemGrid.Cells[7,i] := SpecifiedLineTradeDelivery.BilledQuantity.ValueStr;
// ItemGrid.Cells[8,i] := SpecifiedLineTradeSettlement.ApplicableTradeTax.TypeCode.ValueStr;
end;
end;
end;
In der
unit WPXFactur befindet sich der code zum erzeugen und auslesen der
XML Daten sowie zur Berechnung. Hier kann man ganz gut sehen, wie
XML Daten ausgelesen werden können, insbesondere die Funktion die die Adressen ausliest.
Code:
procedure TCompanyData.AssignFrom(Source: TTradeParty);
var val : TWPXElement;
begin
if Source<>nil then
begin
// This code reads the value of properties but does not create the elements
// If they are not existing.
Source.ReadElementValue([Integer(TXTradeParty.Name)], Name);
if Source.ReadElementValue([Integer(TXTradeParty.DefinedTradeContact),
Integer(TXTradeContact.DepartmentName)], val) then
DepartmentName := val.ValueStr else DepartmentName := '';
// This code first checks the property exists and then read the values
Source.ReadElementValue([Integer(TXTradeParty.PostalTradeAddress),
Integer(TXTradeAddress.PostcodeCode)], PostcodeCode);
Source.ReadElementValue([Integer(TXTradeParty.PostalTradeAddress),
Integer(TXTradeAddress.LineOne)], Addres);
Source.ReadElementValue([Integer(TXTradeParty.PostalTradeAddress),
Integer(TXTradeAddress.CityName)], CityName);
if Source.ReadElementValue([Integer(TXTradeParty.PostalTradeAddress),
Integer(TXTradeAddress.CountryID)], val) then
CountryIDText := val.ValueStr else CountryID := TCountryID.UNDEFINED;
Source.ReadElementValue([Integer(TXTradeParty.ID)], ID);
Source.ReadElementValue([Integer(TXTradeParty.GlobalID)], GlobalID);
if Source.ReadElementValue([Integer(TXTradeParty.SpecifiedTaxRegistration),
Integer(TXTaxRegistration.ID)], val) then
VATID := val.ValueStr else VATID := '';
if Source.ReadElementValue([Integer(TXTradeParty.SpecifiedLegalOrganization),
Integer(TXLegalOrganization.ID)], val) then
SpecifiedLegalOrganization := val.ValueStr else SpecifiedLegalOrganization := '';
end;
end;
Sie verwendet die Methode ReadElementValue welche auf ein Rechnungsobjekt angewendet, benutzt werden kann ein bestimmtes Unterelement auszulesen, ohne dass diese erzeugt wird, wenn es nicht existiert.
Da der Übergabeparameter ein Array ist, kann man hier auch ein unter-unter Element auslesen.
So liest dieser Code das Element aus:
Code:
if Source.ReadElementValue([Integer(TXTradeParty.DefinedTradeContact),
Integer(TXTradeContact.DepartmentName)], val) then
DepartmentName := val.ValueStr else DepartmentName := '';
Welches so geschrieben wird:
TTradeParty(Dest).
DefinedTradeContact.DepartmentName.SetValue(DepartmentName);
geschrieben wird. Ohne die Verwendung vom ReadElementValue würde das Unterobjekt DefinedTradeContact und DepartmentName automatisch angelegt, wenn man also einfach auf Source.DefinedTradeContact.DepartmentName.ValueStr zugreifen würde.
Ich hoffe dies erklärt etwas, wie die automatische Erzeugung der Eigenschaften funktioniert.
Übrigens: Viele Eigenschaften in der Rechnung können mehrfach auftreten. Mit Aussnahme der Rechnungsposten (lines), welche durch eine eigene Collection verwaltet werden, wird dies durch eine default Array property von ausgewählten Klassen implementiert.
IncludedNote[1].ContentCode...
greift hier auf die erste Notiz zu,
IncludedNote[2].ContentCode... auf die zweite usw. Der Zugriff muss in der richtigen, aufsteigenden Reihenfolge erfolgen. Zu auslesen kann man 'Count' abfragen. Zum sequentiellen Hinzufügen ohne index gibt es ListAdd.