# Аналіз конфігурації 1С та план інтеграції особистого кабінету

> Документ фіксує результат вивчення бази 1С (репозиторій `kazum0ra/konfig`)
> і описує, як особистий кабінет абонента отримує з неї дані.

> **Рішення щодо інтеграції.** Замовник не працює з порталом `gkh.in.ua`,
> тому наявний сервіс `HTTPService.GkhInUa` використовуємо лише як
> **перевірений зразок логіки запитів**, а для кабінету створюємо
> **власний HTTP-сервіс `Cabinet`** (JSON, окремий об'єкт/розширення) —
> повністю під контролем замовника. Код і інструкція — у каталозі `onec-1c/`.
> Розділи 2–3 нижче документують наявний сервіс (джерело логіки); розділ 4 —
> цільову архітектуру з власним сервісом.

## 1. Ідентифікація конфігурації

| Параметр | Значення |
|---|---|
| Ім'я | `УчетВЕРЦКУдляУкраины` |
| Синонім (uk) | «Облік в ОСББ, розрахунки квартплати в Україні», редакція 1.0 |
| Вендор | ТОВ «ХВОЯ Iнтегра», ФОП «Дєдов О.О.» |
| Версія / платформа | 1.0.9.2 / 8.3.19 |
| Мова вбудованої мови | російська (імена метаданих кирилицею) |
| Фактичне застосування | біллінг водоканалу (ЄДРПОУ `03362560`, Миргородщина): холодна вода, водовідведення, абонплата |

## 2. Готовий REST-API всередині 1С — `HTTPService.GkhInUa`

У конфігурації вже реалізований HTTP-сервіс для віддачі даних зовнішньому
порталу ЖКГ (`gkh.in.ua`). Кабінет перевикористовує саме його — не треба
писати запити до OData чи лізти у файл бази.

- **RootURL:** `gkh.in.ua`
- **Шаблон URL:** `/{class}/{entity}` (наразі підтримується лише `class = hbt`)
- **Публікація (типово):** `http(s)://<хост>/<база>/hs/gkh.in.ua/hbt/<entity>`
- **Обробники:** `GET → getData`, `POST → postData`
  (реалізація — `CommonModule.GkhInUaHbt`)
- **Формат обміну:** CSV (кома-роздільник, рядковий заголовок з іменами
  колонок; числа з `.`, дати `yyyy-MM-dd`)
- **Автентифікація:** на рівні публікації 1С (HTTP Basic, службовий
  користувач) — облікові дані тримає бекенд кабінету, абонент їх не бачить.

### 2.1. Читання: `GET /hbt/{entity}?CODE={GUID_ЛС}`

`CODE` — це GUID елемента `Справочник.ЛицевыеСчета`
(`Строка(ЛицевойСчет.УникальныйИдентификатор())`). **Якщо `CODE` не задано —
повертаються дані по всіх особових рахунках** (використовуємо для побудови
індексів).

| entity | Функція 1С | Ключові колонки CSV |
|---|---|---|
| `state` | `getState` | `STATE` (=`ready`) — health-check |
| `accounts` | `getAccounts` | `ACCOUNT_CODE` (GUID), `ACCOUNT_NUMB` (№ ЛС), `LOCALITY_CODE` (КОАТУУ), `STREET_NAME`, `BUILDING_NUMB`, `ADDRESS_NUMB` (кв.), `HABITATION_TYPE`, `DELEGATE_LAST` (ПІБ відп. власника), `DELEGATE_TAXID`, `DELEGATE_BIRTH` |
| `contacts` | `getContacts` | `ACCOUNT_CODE`, `CONTACT_TYPE` (=`phone`), `CONTACT_DATA` (**номер телефону**), `LOCALITY_PSTN` |
| `services` | `getServices` | `ACCOUNT_CODE`, `PROVIDER_CODE`, `SERVICE_TYPE`, `SERVICE_UNIT` |
| `rates` | `getRates` | тарифи по послугах/будинку |
| `norms` | `getNorms` | норми споживання |
| `balances` | `getBalances` | `ACCOUNT_CODE`, `PERIOD_YEAR`, `PERIOD_MONTH`, `CALC_START`, `CALC_ACCRUAL`, `CALC_PENALTY`, `CALC_PAYMENT`, `CALC_SUBSIDY`, `CALC_RECALC`, `CALC_INVOICE`, `CALC_FINISH` (сальдо на кінець) — з 2020-05 |
| `finances` | `getFinances` | детальні нарахування: `SERVICE_CODE`, `PERIOD_*`, `RATE_VALUE`, `CALC_TYPE` (`accrual`/`payment`/`penalty`/`subsidy`/`recalc`), `CALC_VOLUME`, `CALC_CSUM` |
| `consumpts` | `getConsumpts` | об'єми споживання по місяцях |
| `payments` | `getPayments` | `ACCOUNT_CODE`, `PERIOD_*`, `PAYMENT_CODE` (№), `PAYMENT_DATE`, `PAYMENT_CSUM`, `PAYMENT_AGENT` (банк) |
| `meters` | `getMeters` | `ACCOUNT_CODE`, `METER_CODE` (GUID приладу), `METER_TYPE` (`water.cold`/`water.hot`), `METER_SERIAL`, `METER_MODEL`, `METER_PLACE`, `METER_CONFIRMED`/`METER_NCONFIRMD` (повірки), `INDICATOR_TYPE`, `INDICATOR_UNIT` (`m3`), `INDICATOR_COEFFICIENT` |
| `indications` | `getIndications` | `ACCOUNT_CODE`, `INDICATOR_CODE` (GUID приладу), `PACKAGE_INDICATED` (дата), `INDICATION_PREV`, `INDICATION_CURR`, `PACKAGE_TYPE` |
| `seals` | `getSeals` | (порожньо) |
| `isrels` | `getISRels` | зв'язки послуга↔прилад |

### 2.2. Запис показань: `POST /hbt/ipes`

Тіло — CSV із рядками показань. Обробник `putIPEs` створює записи в
`РегистрСведений.ПоказанияПриборовУчетаССайта` (окремий регістр «показання
з сайту», щоб оператор потім підтвердив їх у 1С). Потрібні колонки:

| Колонка | Значення |
|---|---|
| `ACCOUNT_CODE` | GUID особового рахунку |
| `INDICATOR_CODE` | GUID приладу обліку (`METER_CODE` з `meters`) |
| `INDICATION_CURR` | нове (поточне) показання |
| `INDICATION_PREV` | попереднє показання |
| `INDICATOR_TYPE` | `water.cold.consumption` → послуга «000000048», інше → «000000020» |
| `PACKAGE_CODE` | ідентифікатор пакета (група показань) |

> Інші POST-сутності (`cces`, `ndes`, `mdfs`) наразі — заглушки
> (`putCCEs/putNDEs/putMDFs` повертають порожньо). Для кабінету
> використовуємо тільки `ipes`.

## 3. Сценарій входу за номером телефону

1. Телефон зберігається у `Справочник.ЛицевыеСчета`, поля **`МобТелефон`**
   та **`Телефон`**. `getContacts` без `CODE` повертає всі непорожні пари
   «телефон → ЛС».
2. Бекенд кабінету періодично (напр. щогодини) тягне `contacts` + `accounts`,
   нормалізує телефони й будує індекс **номер → [GUID ЛС, …]**.
   Це реалізує вимогу «один номер → декілька особових рахунків, перевірка
   по номеру».
3. Оператор видає абоненту тимчасовий пароль (адмін-панель кабінету). Вхід:
   логін = номер телефону, пароль = тимчасовий → примусова зміна пароля →
   далі перегляд даних.

⚠️ **Ризик, який треба врахувати:** ідентичність прив'язана до номера
телефону. Якщо один номер вказано на кількох власників — усі їхні ЛС будуть
видні тому, хто володіє номером. Це відповідає описаному ручному сценарію
(оператор голосом підтверджує особу перед видачею тимчасового пароля), але
варто пам'ятати.

## 4. Архітектура кабінету

```
Абонент (браузер)
      │  HTTPS
      ▼
Особистий кабінет — FastAPI (сервер замовника)
  ├─ власна БД (PostgreSQL): користувачі, тимчасові/постійні паролі (хеш),
  │  індекс телефон→ЛС, кеш карток ЛС, журнал переданих показань, аудит
  └─ інтеграційний шар — JSON-клієнт до власного сервісу 1С
      │  HTTPS + Basic Auth (server-to-server), доступ лише з IP кабінету
      ▼
1C · HTTPService.Cabinet  (/hs/cabinet/*)   ← власний об'єкт, див. onec-1c/
```

Кабінет має **два режими** (перемикач у конфізі):
- `demo` — вбудовані тестові дані, працює без 1С (розробка/демо);
- `http` — реальні виклики до власного HTTP-сервісу `Cabinet`.

## 5. Що потрібно від адміністратора 1С для «бойового» запуску

1. **Опублікувати** (або підтвердити публікацію) HTTP-сервіс `GkhInUa`
   на веб-сервері (Apache/IIS). Базовий URL: `https://<хост>/<база>/hs/gkh.in.ua`.
2. Створити **службового користувача** 1С з правами лише на цей сервіс і
   передати бекенду його логін/пароль (Basic).
3. Забезпечити доступ VPS → 1С (HTTPS; бажано VPN або обмеження по IP).
4. Перевірити, що у `ЛицевыеСчета` **заповнені телефони** (`МобТелефон`/`Телефон`).
5. Домовитись, хто і як **підтверджує** показання, що надійшли в регістр
   `ПоказанияПриборовУчетаССайта`.

## 6. Відповідність полів API → екрани кабінету

| Екран кабінету | Джерело (entity) |
|---|---|
| Список особових рахунків | `accounts` (+ індекс `contacts`) |
| Баланс / борг | `balances` (`CALC_FINISH`) |
| Нарахування | `finances`, `consumpts` |
| Історія платежів | `payments` |
| Лічильники | `meters` |
| Історія показань | `indications` |
| Передати показання | `POST ipes` |
