64 lines
2.6 KiB
Python
64 lines
2.6 KiB
Python
"""Проверка схемы среза ЕХ ex-payload-v1 (docs #208): примеры проходят, типовые ошибки — нет.
|
||
|
||
Запуск: .venv/bin/python -I scripts/kfo_contract/test_ex_payload.py
|
||
"""
|
||
import copy
|
||
import json
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
from jsonschema import Draft202012Validator
|
||
|
||
ROOT = Path(__file__).resolve().parents[2]
|
||
SCHEMA = ROOT / "contracts" / "ex-payload-v1.schema.json"
|
||
EXAMPLES = sorted((ROOT / "contracts" / "examples").glob("ex-payload-*.json"))
|
||
REQUIRED_TYPES = {"summary_osv", "vgo_pairs", "chess", "kfo_balance", "kfo_income", "goodwill", "corrections",
|
||
"version_card"}
|
||
|
||
|
||
def main():
|
||
schema = json.loads(SCHEMA.read_text(encoding="utf-8"))
|
||
Draft202012Validator.check_schema(schema)
|
||
v = Draft202012Validator(schema)
|
||
by_type = {}
|
||
for p in EXAMPLES:
|
||
doc = json.loads(p.read_text(encoding="utf-8"))
|
||
errs = list(v.iter_errors(doc))
|
||
assert not errs, f"{p.name}: {errs[0].message[:200]}"
|
||
by_type[doc["item_type"]] = doc
|
||
missing = REQUIRED_TYPES - set(by_type)
|
||
assert not missing, f"нет примеров: {sorted(missing)}"
|
||
|
||
def rejected(doc, why):
|
||
assert list(v.iter_errors(doc)), f"схема пропустила: {why}"
|
||
|
||
# 1. item_type конверта не совпадает с формой data
|
||
bad = copy.deepcopy(by_type["kfo_balance"])
|
||
bad["data"] = copy.deepcopy(by_type["goodwill"]["data"])
|
||
rejected(bad, "kfo_balance с данными гудвилла")
|
||
# 2. kfo_balance без сводки корректировок в реквизитах
|
||
bad = copy.deepcopy(by_type["kfo_balance"])
|
||
del bad["data"]["requisites"]["corrections_balance"]
|
||
rejected(bad, "нет requisites.corrections_balance")
|
||
# 4. деньги числом
|
||
bad = copy.deepcopy(by_type["kfo_balance"])
|
||
bad["data"]["balance"]["lines"][0]["bank_amount"] = 2500.0
|
||
rejected(bad, "деньги числом")
|
||
# конверт: лишнее поле и неизвестная единица
|
||
bad = copy.deepcopy(by_type["version_card"])
|
||
bad["extra"] = 1
|
||
rejected(bad, "лишнее поле конверта")
|
||
bad = copy.deepcopy(by_type["summary_osv"])
|
||
bad["units"] = "mln_rub"
|
||
rejected(bad, "неизвестная единица")
|
||
# единица не соответствует типу
|
||
bad = copy.deepcopy(by_type["summary_osv"])
|
||
bad["units"] = "thousand_rub"
|
||
rejected(bad, "summary_osv в тысячах")
|
||
print(f"OK: примеров {len(EXAMPLES)}, отрицательных случаев 6")
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|