The fifth milestone adds the second big part of the Kladde: public tenders. Public buyers in the EU publish their tenders in TED (Tenders Electronic Daily), and TED offers a search API that anyone can use without a key. In module 2.8 you built a client for it and a nightly import that reads for fixed CPV codes from the configuration. Now that becomes an import the office controls itself: Management decides what to search for, the import fetches only what’s new every night, it survives outages at TED, and everyone can see how the last run went.

The split from lesson 2.11.1, with the change recommended there in solution 3: The runs are recorded before the query needs the last successful run.

Pull request Branch Brings Where in this lesson
1 feature/m5-search-criteria CPV codes and countries, checked, saved, kept by management Exercise 1 and “Pull request 1”
2 feature/m5-import-runs every run recorded, the last one visible, new and changed counted “Pull request 2”
3 feature/m5-query-from-criteria the query from the criteria, from the last success on, all pages of the answer “Pull request 3”
4 feature/m5-retry-run at 3 a.m. local time, retried up to three times after an error, the client doesn’t repeat a POST Exercise 2 and “Pull request 4”

Where the Kladde stands

After module 2.8 and milestone 4, the solutions have this:

  • TedClient in the project Kladde.Ted of its own is a typed client (lesson 2.8.1) with AllowAutoRedirect = false and tests in tests/Kladde.Ted.Tests with a fake HttpMessageHandler for success, 500, redirect and broken JSON. TedQuery builds the query from a TenderSearch (CPV codes, countries, limit) from Kladde.Core.Tenders.
  • A background service imports the notices for the CPV codes and countries from the configuration (Tenders:Import, lesson 2.8.2) every night.
  • The import is idempotent: A unique index on the publication number prevents duplicates (lesson 2.8.3). The standard resilience handler doesn’t repeat a POST (DisableForUnsafeHttpMethods).
  • At /tenders there’s a simple list of the imported tenders.

This lesson’s examples give TenderSearch a factory method with the rules for management’s input and leave out the limit, because the import now reads all pages; TedQuery also gets the day of the last success. Change those two types from module 2.8 instead of putting new ones next to them. If your files, classes or folders are named differently, keep your names and carry the steps over.