DanglIT customers have a powerful tool with the GAEB & AVA .Net Libraries to create simple, fast and reliable integrations for the tendering process (German: AVA) in their products. No matter the system - classic ERP applications or specialized tools - when using the GAEB Data Exchange Format, you're at maximum compatibility with customers and suppliers throughout the whole tendering process.
In this article, you'll learn how to read GAEB files, calculate project prices and then submit via GAEB in a tendering process, from the perspective of a bidder. The shown workflow uses the .NET modules, but the AVACloud web service can be used in the same way - for example, to create GAEB support in Java, TypeScript, Rust and many more programming languages. DanglIT customers with support contract find the code and example files in the Dangl.AVA.Converter.Tests.Utilities project.
To start, you'll need a GAEB file with data exchange phase 83 - offer request. You can download the example project from the GAEB introduction right here. To recap, here's how the finished project should look like:
When you explore the GAEB file, you'll notice that phase 83 - offer request does not contain any prices:
<Item ID="ID_a71d8ec9-e92c-4fca-b097-511a329fd4ec" RNoPart="02" RNoIndex="5">
<Qty>240</Qty>
<QU>m²</QU>
<Description>
<OutlineText>
<OutlTSA>No</OutlTSA>
<OutlTxt>
<TextOutlTxt>
<span>Concrete Walls</span>
</TextOutlTxt>
</OutlTxt>
</OutlineText>
</Description>
</Item>
The source file does only contain information about quantities, the unit type and text descriptions of the positions.
The following snippet shows the basic steps required to create a fully functional offer in the GAEB format. It's written in the form of a unit test.
[Fact]
public void ReadOfferRequestThenCalculatePricesThenExportOffer()
{
// First, get the GAEB file as System.IO.Stream.
// It can be anything - directly from a file, from a web request
// or read from your database.
var gaebFileStream = GetGaebFileStream();
// The GAEB file can be any GAEB format - GAEB 90, GAEB 2000 or GAEB XML
var gaebFile = Dangl.GAEB.Reader.GAEBReader.ReadGaeb(gaebFileStream);
// In this case, it's GAEB XML
Assert.Equal(Dangl.GAEB.GaebFileVersion.GaebXml, gaebFile.Version);
// Dangl.AVA.Converter can convert all GAEB formats to Dangl.AVA.Projects
var importedProject = Dangl.AVA.Converter.Converter.ConvertFromGaeb(gaebFile);
// The project can now be edited, for example by setting prices
var projectWithPrices = CalculatePricesForOffer(importedProject);
Assert.Equal(0m, importedProject.ServiceSpecifications[0].TotalPrice);
// projectWithPrices should have a TotalPrice set now
Assert.Equal(57_550m, projectWithPrices.ServiceSpecifications[0].TotalPrice);
// This project can now be converted again to a GAEB Stream
using (var gaebExportStream = ExportProjectAsGaebXmlOffer(projectWithPrices))
{
// Now the Stream can be saved as file,
// returned in a web request,
// stored in the database...
}
}
Step by step, the following happens:
- GetGaebFileStream() is used to import a GAEB file as Stream. It can come from any source, e.g. from a local file or from a web request.
- Dangl.GAEB reads the Stream and creates a native GAEB element. It's Version property can be used to find out that it's actually a GAEB XML file in this case.
- The Dangl.AVA.Converter module creates an element importedProject from the GAEB file. The input type doesn't matter in this case - the converter works fully automatic.
- The prices can now be calculated in the unified Dangl.AVA project.
- Finally, the project is exported again to GAEB. The resulting Stream can be saved, for example in a local file.
Normally, DanglIT customers have their own software systems with a dedicated UI for price calculation, so the following step may differ.
Example code could look like this:
public Project CalculatePricesForOffer(Project sourceProject)
{
// We make a copy of the project so we don't change the input object
var project = sourceProject.Copy(keepId: true);
// First, we set the VAT Tax Rate for the project
project.ServiceSpecifications[0].ProjectTaxRate = .19m; // 19 % tax rate
// GetPositionByItemNumber() is an extension method in Dangl.AVA.Extensions
var sitePreparationPosition = project.GetPositionByItemNumber("01.01.001");
// In the site preparation, we simply set a price without any calculations
// via the SetUnitPrice() extension method
sitePreparationPosition.SetUnitPrice(800m);
// The project defines two price components:
// 1. Material
// 2. Gear, such as tools & machinery
// Additionally, Dangl.AVA allows to set a price-per-hour of manual labour and a time component
// for position prices
// For the walls, we want to do a more detailed price calculation
var concreteWallsPosition = project.GetPositionByItemNumber("02.02.005");
var formulaForMaterial = "0.25\"Wall thickness in meter\" * 80\"EUR/m3\""; // Formulas support comments
var formulaForLabour = "1.20\"Hours per m³\" * 0.25\"Wall thickness in meter\"";
concreteWallsPosition.PriceComponents
.First(comp => comp.Label == "Material") // Select the Price Component for "Material"
.Values.Add(new Calculation { Formula = formulaForMaterial });
concreteWallsPosition
.LabourComponents
.Values.Add(new Calculation { Formula = formulaForLabour });
// Also, we define the cost-per-hour of labour as 50 currency units
project.ServiceSpecifications[0].PriceInformation.HourlyWage = 50m;
// All other positions simply get a price set
project.GetPositionByItemNumber("02.02.001").SetUnitPrice(9);
project.GetPositionByItemNumber("02.02.002").SetUnitPrice(6);
project.GetPositionByItemNumber("02.02.003").SetUnitPrice(12);
project.GetPositionByItemNumber("02.02.004").SetUnitPrice(40);
return project;
}
The calculation method first creates a copy of the project. This ensures that other references to this project are not altered. The VAT rate is set to 19% for the whole project.
We'll not calculate the price for sitePreparationPosition extensively - with the SetUnitPrice() extension method, it's simply set to 800,-.
It's different for concreteWallsPosition: Here, we're using the features of Dangl.Calculator to create a comprehensible price calculation with multiple components.
Tip: In the Docs for Dangl.AVA you'll finde more detailed information and examples about working with prices. Please contact DanglIT if you don't yet have access to the internal sections of DanglDocu.
To determine the price of the materials per m² wall, we multiply the price per volume concrete with the thickness of the wall in the following formula: 0.25"Wall thickness in meter" * 80"EUR/m3".
The labour price for the position is calculated in a similar way - with the difference that we're calculating the time it takes, not a finished price. This is typically done in GAEB this way. You can then either set your calculated wages globally for the project or different rates per position. The price is then calculated automatically. We will set HourlyWage to 50,-.
Now all that is left is the export to GAEB to finish the bidding process:
public Stream ExportProjectAsGaebXmlOffer(Project projectWithPrices)
{
// We want to make sure that for the export:
// 1. The format is GAEB XML
// 2. The export phase is 84 - Offer
var gaebFileOffer = Dangl.AVA.Converter.Converter.ConvertToGaeb(projectWithPrices,
destinationType: DestinationGAEBType.GAEBXML_V3_2,
targetExchangePhase: GAEBTargetExchangePhase.Offer); // Phase "Offer" is GAEB Phase 84
// The GAEB file object is now converted to a Stream
var gaebStream = Dangl.GAEB.Writer.GAEBWriter.GetStream(gaebFileOffer);
return gaebStream;
}
At first, the project is converted to a GAEB file. In the conversion, we'll set the destination type to GAEB XML V3.2 and specify Phase Offer (84). Basically, offers in GAEB contain only item references and prices. Texts, quantities and other information is not exported in this phase.
The GAEB file contains the quantity (Qty), the unit price (UP) and the total price(IT):
<Item ID="ID_a71d8ec9-e92c-4fca-b097-511a329fd4ec" RNoPart="02" RNoIndex="5">
<Qty>240</Qty>
<UP>35.0</UP>
<IT>8400.0</IT>
</Item>
You can download the created file right here.
Do you have further questions? Please contact DanglIT! We're happy to help you with fast & proven ways to integrate GAEB features in your processes and tools.