Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

resmi-poz

CI

Parser and Turkish-aware ranked search for Turkey's official construction unit-price lists ("poz" / birim fiyat listeleri) published by public institutions such as ÇŞB (Ministry of Environment and Urbanization), DSİ, and MSB.

Anyone building construction software for the Turkish market — procurement, tender preparation (ihale), progress payments (hakediş), quantity surveying (metraj) — eventually needs these lists in a database with a fast autocomplete on top. Getting from the officially published PDFs to that point involves a handful of non-obvious pitfalls. This library is the distilled, dependency-free core that solves them, extracted from a production procurement system that manages 22,000+ poz records.

The pitfalls it handles

  1. Turkish price formatting. ÇŞB prices arrive as "310,00" and "1.712,50" (thousands dot + decimal comma). parseTurkishDecimal converts them to dot-decimal strings — safe to feed into Postgres numeric / Prisma Decimal without float round-trips.

  2. Units glued to descriptions. In the ÇŞB price book the unit is not a separate column — it is the last word of the description: "Taşcı ustası Sa". splitTrailingUnit separates it fail-closed: only allowlisted tokens are treated as units, so delivery-place suffixes ("İşbaşında") or technical tokens ("kA", "V") never get chopped off a description.

  3. Broken JS lowercasing for Turkish. "ISITMA".toLowerCase() is "isitma", but Turkish lowercases I to dotless ı. toLowerTurkish and the double-key matcher (matchesQuery) get this right and tolerate missing diacritics in both query and data — "tas yunu" finds "Taş yünü", "taş" finds "TASYUNU".

  4. Duplicate item numbers in official PDFs. dedupeByPozNo (last-record-wins) also protects bulk upserts from Postgres' ON CONFLICT cannot affect row a second time.

  5. Autocomplete ranking. searchPoz orders candidates the way a data entry form wants them: exact poz number → poz number prefix → description tokens (AND semantics, most specific record first).

Install

npm install resmi-poz

Usage

import {
 parseCsbRecord,
 parseUnifiedRecord,
 dedupeByPozNo,
 searchPoz,
} from "resmi-poz";
// 1. Normalize raw extracted data (two common shapes supported)
const csb = parseCsbRecord({
 poz: "10.100.1001",
 tanim: "Taşcı ustası Sa",
 fiyat: "310,00",
});
// → { pozNo: "10.100.1001", description: "Taşcı ustası", unit: "Sa",
// unitPrice: "310.00", year: 2026, source: "CSB" }
const dsi = parseUnifiedRecord({
 pozNo: "56.520.1000",
 tanim: "Temel Sondaj Deliğinin Açılması",
 birim: "m",
 birimFiyat: 5335.48,
 kaynak: "DSI",
});
// 2. Deduplicate before a bulk upsert
const rows = dedupeByPozNo([csb!, dsi!]);
// 3. Ranked autocomplete over any candidate set
searchPoz("taşcı", rows); // Turkish-aware, diacritic-tolerant
searchPoz("10.100", rows); // poz-number prefix

The search layer is pure: fetch a candidate set however you like (full in-memory list, an ILIKE-prefiltered DB slice) and let searchPoz order it.

Data

This library ships parsers, not price data. The official lists are published by the respective institutions (e.g. ÇŞB's yearly İnşaat ve Tesisat Birim Fiyatları book); obtain them from the official sources and extract to JSON in either supported shape. Small anonymized samples for testing live in data/.

API

Function Purpose
parseTurkishDecimal(raw) "1.712,50""1712.50", invalid → null
splitTrailingUnit(text, unitMap?) Fail-closed unit extraction from ÇŞB descriptions
parseCsbRecord(raw, options?) ÇŞB-shape record → PozRecord | null
parseUnifiedRecord(raw, options?) Unified-shape record → PozRecord | null
dedupeByPozNo(records) Last-wins dedupe on poz number
searchPoz(query, records, limit?) Ranked autocomplete search
toLowerTurkish / foldDiacritics / matchesQuery Turkish-aware text matching primitives
DEFAULT_UNIT_MAP Extendable unit allowlist

Türkçe özet

Resmi birim fiyat (poz) listelerini veritabanına almak ve üzerine hızlı bir otomatik tamamlama koymak için gereken çekirdek: TR fiyat biçimi ("1.712,50"), tanımın sonuna gömülü birim ("Taşcı ustası Sa", fail-closed ayıklama), Türkçe küçük harf / diakritik sorunları (İ/ı, "tas yunu""taş yünü"), PDF'lerdeki mükerrer poz numaraları ve poz-no → tanım öncelikli sıralama. Bağımlılıksız, saf fonksiyonlar; üretimde 22.000+ poz kaydıyla çalışan bir satın alma sisteminden çıkarılmıştır.

License

MIT

About

Parser and Turkish-aware ranked search for Turkey's official construction unit-price (poz) lists.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /