Skip to content

fix(etl): хващай стотинки грешката и по прогнозата на позицията (#247) - #304

Open
todorkolev wants to merge 1 commit into
mainfrom
fix/stotinki-lot-estimate
Open

fix(etl): хващай стотинки грешката и по прогнозата на позицията (#247)#304
todorkolev wants to merge 1 commit into
mainfrom
fix/stotinki-lot-estimate

Conversation

@todorkolev

Copy link
Copy Markdown
Collaborator

Довършва #247. Първата половина беше #298; това е втората.

Проблемът

Лентата от #298 мери спрямо процедурната прогноза, тъй че вижда изтървания десетичен знак само когато процедурата е с една позиция. При процедура с няколко позиции грешката пак стои на точно 100x прогнозата на позицията, а съотношението към целия процедурен таван пада там, където го отвежда делът на позицията.

Вторият договор от доклада, 00621-2020-0008, е точно такъв: стои на 89,8x процедурната прогноза, минава под лентата и се сервира като 14 212 416 € при реални около 142 000 €.

Защо не просто смяна на знаменателя

Защото docs/etl.md отдавна записва обратното, и с основание: при рамковите и unit-price процедури (гориво, храни, лекарства) прогнозата на реда е единична цена, а цял call-off законно я надхвърля десетки пъти. Флаговете „твърде високо" ползват процедурната прогноза именно за да не изядат такъв договор.

Затова новото рамо е съюз:

95-105x собствената прогноза И поне 10x процедурната

Десетократното не е ново число - това е съществуващият праг за review, който вече значи „неправдоподобно голямо за тази процедура". Call-off по единична цена стои на около 1x процедурната и се пощадява.

Ефект

Премерено през прогнозите на позициите: 7 договора, 40,3 млн. € показвани падат на 1,75 млн. Прегледани са поединично и всичките са безспорни:

x позиция x процедура показвано прогноза на позицията предмет
101,6 46,8 17 608 296 173 328 горива за МПС
99,8 17,2 14 166 674 141 983 ремонт на хотел „Олимп"
100 10,0 4 527 587 45 276 хранителни продукти
99,9 59,1 2 016 427 20 177 работно облекло
99,8 40,8 1 393 428 13 966 работно облекло
100 20,5 293 778 2 938 учебници
100 16,8 265 262 2 652 учебници

Учебници с прогноза 2 938 € показани като 293 778 € - сигнатурата е недвусмислена.

Две уговорки, за да е честно измерването:

  1. Докладваният 00621-2020-0008 не е в таблицата, защото няма ред в lots и заместителят, с който мерих, не го вижда. Аритметиката обаче го потвърждава: 14 212 416 / 100 = 277 970,6 лв, което е точно прогнозата, цитирана в доклада. Тоест реалният брой засегнати е над 7 и ще се уточни при зареждане.
  2. Един от седемте стои точно на пода от 10x (хранителните продукти). Прагът върши работа, а не е украса; ако решим, че е твърде нисък, този случай изпада, но останалите шест не зависят от него.

Реализация и тестове

Ново own_est_eur в петте флагови пътя (2 в normalize-raw.sql, 3 в refresh-slice.sql), плюс рамото в самите CASE-ове. В reconciliation паса се ползва вече наличната classifier_estimated_value - собствената прогноза на реда с процедурната като резервен вариант.

Тестът кара истинските скриптове по двата derive пътя срещу истинска sqlite и покрива и трите неща:

  • хваща докладваната форма (100x позиционната при 89,8x процедурната);
  • не пипа call-off при 100x единичната цена и 0,2x процедурната - това е тестът, който щеше да липсва при проста смяна на знаменателя;
  • заковава пода на съюза: точно 10x минава, 8,9x не.

packages/db минава изцяло (единственото падане в средата е предсъществуващият артефакт с глобалния wrangler в ship-domain.test.ts, файл, който не е пипан).

Какво остава извън обхвата

Поправката връща стойността към процедурната прогноза, установената котва за value_suspect. При тези договори тя е малко над позиционната - за докладвания случай 158 347 € вместо 142 124 €. По-точно би било да се връща към позиционната, когато е пламнало позиционното рамо, но това е втора котва на пет места и заслужава отделно решение.

Лентата от #298 мери спрямо процедурната прогноза, тъй че вижда грешката само
когато процедурата е с една позиция. При процедура с няколко позиции изтърваният
десетичен знак пак стои на точно 100x прогнозата НА ПОЗИЦИЯТА, а съотношението
към целия процедурен таван пада там, където го отвежда делът на позицията.
Докладваният 00621-2020-0008 стои на 89,8x и се сервира като 14 212 416 EUR
вместо около 142 000.

Само смяна на знаменателя обаче е опасна и docs/etl.md го казва отдавна: при
рамковите и unit-price процедури прогнозата на реда е ЕДИНИЧНА цена, а цял
call-off законно я надхвърля многократно. Затова рамото е съюз - 95-105x
собствената прогноза И поне 10x процедурната, прагът, който вече значи
"неправдоподобно голямо за тази процедура". Call-off по единична цена стои на
около 1x процедурната и се пощадява.

Премерено през прогнозите на позициите: 7 договора, 40,3 млн. EUR показвани
падат на 1,75 млн. Всичките са прегледани поединично и са безспорни - учебници
за 2 938 EUR прогноза, показани като 293 778. Докладваният договор няма ред в
lots, тъй че не влиза в тази бройка, но аритметиката го потвърждава:
14 212 416 / 100 = 277 970,6 лв, точно прогнозата от доклада.

Тестът кара истинските скриптове по двата derive пътя и покрива и трите неща:
хваща докладваната форма, НЕ пипа call-off при 100x единичната цена, и заковава
пода на съюза - точно 10x минава, 8,9x не.
@github-actions

Copy link
Copy Markdown

Test coverage

Workspace Lines Δ Branches Δ Functions Statements
apps/etl 75.43% +1.43pp 63.52% +5.32pp 70.00% 74.11%
apps/web 91.02% +1.32pp 82.50% +0.70pp 91.19% 89.73%
packages/config 92.85% +0.05pp 72.22% +0.02pp 92.85% 89.18%
packages/db 94.54% +0.34pp 79.38% +0.38pp 87.19% 91.55%
packages/ingest 88.17% +2.37pp 82.81% +2.81pp 80.17% 86.36%
packages/shared 95.50% +0.10pp 80.83% +0.83pp 92.30% 89.56%
Total (informational) 91.23% 80.80% 86.95% 89.08%

✅ No workspace dropped below its baseline (tolerance 0.5pp).

📈 Coverage rose by more than 1pp — run node scripts/check-coverage.mjs --update locally and commit coverage-baseline.json to ratchet the threshold up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant