114 lines
6.6 KiB
Python
114 lines
6.6 KiB
Python
"""
|
||
pools.py — Пулы данных для генератора тестовых документов.
|
||
|
||
Схема Опуса: 10 компаний, пул из ~12 услуг, цены ±20% от базовых,
|
||
вариативность дат, номеров, названий.
|
||
|
||
Все данные основаны на реальных файлах из примеры_договоров_для_ИИ/.
|
||
"""
|
||
|
||
import random
|
||
|
||
# ── Компании ─────────────────────────────────────────────────
|
||
|
||
COMPANIES = [
|
||
{"prefix": "XXX001", "legal": 'ЗАО "XXX001"', "dir": "Генерального директора"},
|
||
{"prefix": "XXX002", "legal": 'ООО "XXX002"', "dir": "Генерального директора"},
|
||
{"prefix": "XXX003", "legal": 'АО "XXX003"', "dir": "Директора"},
|
||
{"prefix": "XXX004", "legal": 'ПАО "XXX004"', "dir": "Генерального директора"},
|
||
{"prefix": "XXX005", "legal": 'ООО "XXX005"', "dir": "Директора"},
|
||
{"prefix": "XXX006", "legal": 'ЗАО "XXX006"', "dir": "Генерального директора"},
|
||
{"prefix": "XXX007", "legal": 'АО "XXX007"', "dir": "Директора"},
|
||
{"prefix": "XXX008", "legal": 'ООО "XXX008"', "dir": "Генерального директора"},
|
||
{"prefix": "XXX009", "legal": 'ИП "XXX009"', "dir": "Индивидуального предпринимателя"},
|
||
{"prefix": "XXX010", "legal": 'ПАО "XXX010"', "dir": "Генерального директора"},
|
||
# Кириллический edge (уже есть в примерах)
|
||
{"prefix": "ХХХ002", "legal": 'ООО "ХХХ002"', "dir": "Генерального директора"},
|
||
]
|
||
|
||
PROVIDER = 'ООО "НУБЕС"'
|
||
PROVIDER_DIR = "Генерального директора Степаненко В.И."
|
||
CITY = "г. Москва"
|
||
ADDRESS = "115404, г. Москва, 1-я Стекольная 7с5"
|
||
|
||
# ── Номера договоров ─────────────────────────────────────────
|
||
|
||
# Базовые номера из примеров + вариации
|
||
BASE_NUMBERS = ["03700", "01200", "01300", "04100", "05200", "06800", "07400", "08100", "09900", "10500"]
|
||
|
||
def contract_number(company_idx, variant=0):
|
||
"""Сгенерировать номер договора: БАЗА[_суффикс]."""
|
||
base = BASE_NUMBERS[company_idx % len(BASE_NUMBERS)]
|
||
if variant > 0:
|
||
return f"{base}_{variant}"
|
||
return base
|
||
|
||
# ── Даты ─────────────────────────────────────────────────────
|
||
|
||
def random_date(base_year=2025, base_month=12, spread_months=7):
|
||
"""Случайная дата ±spread_months от базовой. Возвращает DD.MM.YYYY."""
|
||
import datetime
|
||
base = datetime.date(base_year, base_month, 1)
|
||
offset = random.randint(0, spread_months * 30)
|
||
d = base + datetime.timedelta(days=offset)
|
||
return d.strftime("%d.%m.%Y")
|
||
|
||
# ── Пул услуг и базовых цен (из реальных файлов) ────────────
|
||
|
||
# (наименование, базовая_цена, мин_объём, макс_объём, категория)
|
||
# категория: 'rack' | 'power' | 'network' | 'cloud' | 'ip' | 'cross'
|
||
|
||
SERVICES = [
|
||
("Аренда стойко-места", 213905.44, 1, 5, "rack"),
|
||
("Аренда PDU: 3Ф 32А вертикальный", 2511.17, 1, 5, "power"),
|
||
("Организация L2 канала без резерва, в составе:\n Скорость порта: 1 Гбит/с", 11016.36, 1, 3, "network"),
|
||
("Организация L2 канала без резерва, в составе:\n Скорость порта: 10 Гбит/с", 28300.00, 1, 2, "network"),
|
||
("Next Generation Cloud (Intel 3.0 ГГц), в составе:\n Количество vCPU: 8, RAM: 32 ГБ", 76704.00, 1, 3, "cloud"),
|
||
("Next Generation Cloud (AMD 4.0 ГГц), в составе:\n Количество vCPU: 4, RAM: 16 ГБ", 123823.00, 1, 2, "cloud"),
|
||
("Аренда IPv4 адреса /32", 157.28, 1, 16, "ip"),
|
||
("Аренда IPv4 подсети /30", 629.10, 1, 4, "ip"),
|
||
("Организация cross-connect: ВОЛС, 2×SMF", 4192.40, 1, 5, "cross"),
|
||
("Организация cross-connect: UTP", 840.94, 1, 5, "cross"),
|
||
("Интернет без защиты от DDoS, в составе:\n Полоса Интернет: 100 Мбит/с", 7015.00, 1, 3, "network"),
|
||
("Аренда порта без резерва, в составе:\n Скорость порта: 1 Гбит/с", 1525.00, 1, 3, "network"),
|
||
("Аренда публичной подсети (Длина префикса: /30 — 1 IPv4 адрес)", 589.66, 1, 4, "ip"),
|
||
]
|
||
|
||
# ── Функции вариативности ────────────────────────────────────
|
||
|
||
def vary_price(base, pct=0.20):
|
||
"""Случайное изменение цены ±pct, округление до копеек."""
|
||
factor = 1.0 + random.uniform(-pct, pct)
|
||
return round(base * factor, 2)
|
||
|
||
def vary_qty(min_q, max_q):
|
||
return random.randint(min_q, max_q)
|
||
|
||
def format_price(p):
|
||
"""Формат цены с пробелами-разделителями: 213 905,44."""
|
||
s = f"{p:,.2f}"
|
||
# 213,905.44 → 213 905,44
|
||
return s.replace(",", " ").replace(".", ",").replace(" ", " ")
|
||
|
||
def pick_services(count=5, with_prices=True):
|
||
"""Выбрать случайный набор услуг. Возвращает [(name, price, qty, sum), ...]."""
|
||
selected = random.sample(SERVICES, min(count, len(SERVICES)))
|
||
result = []
|
||
total = 0.0
|
||
for i, (name, base_price, min_q, max_q, cat) in enumerate(selected, 1):
|
||
price = vary_price(base_price) if with_prices else base_price
|
||
qty = vary_qty(min_q, max_q)
|
||
s = round(price * qty, 2)
|
||
total += s
|
||
result.append({
|
||
"num": i,
|
||
"name": name,
|
||
"price": price,
|
||
"price_str": format_price(price),
|
||
"qty": qty,
|
||
"sum": s,
|
||
"sum_str": format_price(s),
|
||
"cat": cat,
|
||
})
|
||
return result, round(total, 2), format_price(round(total, 2))
|