93 lines
4.7 KiB
Python
93 lines
4.7 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
Убирает точные дубли позиций прайса (одинаковый раздел+название+цена, возникшие
|
||
из-за пересечения источников: старый сайт Bitrix + 3 файла 1С). Если у одной и
|
||
той же услуги в разных источниках цена расходится — оставляет по одной строке
|
||
на каждую цену и подписывает источник в скобках, а не молча выбирает одну.
|
||
"""
|
||
import csv, io
|
||
import build_price_map as b
|
||
|
||
LABEL_ORDER = ['старый прайс', 'ЦОМ', 'Остео', 'Дети']
|
||
|
||
def esc(s):
|
||
# В PostgreSQL со standard_conforming_strings обратный слэш — обычный символ,
|
||
# удваивать его нельзя: имена приезжали в базу с лишним слэшем.
|
||
return "'" + str(s).replace("'", "''") + "'"
|
||
|
||
# ---------- Bitrix-происхождение (уже в базе) ----------
|
||
bitrix = [] # (id, slug, name, price)
|
||
with io.open('bitrix_items.csv', encoding='utf-8') as f:
|
||
for row in csv.reader(f):
|
||
bitrix.append((int(row[0]), row[1], row[2], float(row[3])))
|
||
|
||
# ---------- 1С: те же три файла, но с меткой источника ----------
|
||
DEPT_LABEL = {'D:/ЦОМ.xlsx': 'ЦОМ', 'D:/Остео.xlsx': 'Остео', 'D:/Дана Дети.xls': 'Дети'}
|
||
c1c = [] # (label, slug, name, price)
|
||
for path, kind, ncol, pcol in b.FILES:
|
||
rows = b.parse_xlsx(path) if kind == 'xlsx' else b.parse_xls(path)
|
||
items = b.extract(rows, ncol, pcol)
|
||
label = DEPT_LABEL[path]
|
||
for sec, name, price in items:
|
||
key = (sec or '').strip().lower()
|
||
slug = b.MAP.get(key, 'prochee-price')
|
||
c1c.append((label, slug, name.strip(), price))
|
||
|
||
# ---------- группировка: (slug, name) -> {price: {labels}} ----------
|
||
groups = {} # (slug, name) -> {price: set(labels)}
|
||
bitrix_by_key = {} # (slug, name) -> [(id, price), ...]
|
||
|
||
for pid, slug, name, price in bitrix:
|
||
key = (slug, name)
|
||
bitrix_by_key.setdefault(key, []).append((pid, price))
|
||
groups.setdefault(key, {}).setdefault(price, set()).add('старый прайс')
|
||
|
||
for label, slug, name, price in c1c:
|
||
key = (slug, name)
|
||
groups.setdefault(key, {}).setdefault(price, set()).add(label)
|
||
|
||
updates = [] # (id, new_name)
|
||
inserts = [] # (slug, name, price)
|
||
deletes = [] # id (bitrix rows made redundant — only happens if a bitrix row
|
||
# duplicates another bitrix row exactly; not expected, kept for safety)
|
||
|
||
for (slug, name), pricemap in groups.items():
|
||
bitrix_rows = bitrix_by_key.get((slug, name), [])
|
||
if len(pricemap) == 1:
|
||
# все источники сходятся в одной цене — ничего не меняем/не плодим
|
||
if not bitrix_rows:
|
||
(price,) = pricemap.keys()
|
||
inserts.append((slug, name, price))
|
||
# если bitrix_rows уже есть — они и представляют эту цену, 1С дублировать не нужно
|
||
continue
|
||
# расхождение цен — подписываем каждую цену источниками
|
||
bitrix_prices = {p for _, p in bitrix_rows}
|
||
for price, labels in pricemap.items():
|
||
label_str = ', '.join(l for l in LABEL_ORDER if l in labels)
|
||
new_name = '%s (%s)' % (name, label_str)
|
||
if price in bitrix_prices:
|
||
for pid, p in bitrix_rows:
|
||
if p == price:
|
||
updates.append((pid, new_name))
|
||
else:
|
||
inserts.append((slug, new_name, price))
|
||
|
||
o = io.open('seed_dedup.sql', 'w', encoding='utf-8')
|
||
o.write('BEGIN;\n')
|
||
# сначала снести прежнюю "плоскую" заливку 1С (3585 строк без дедупа), затем
|
||
# переименовать конфликтующие bitrix-строки и вставить заново уже с разметкой
|
||
o.write("DELETE FROM price_items WHERE legacy_id IS NULL;\n")
|
||
for pid, new_name in updates:
|
||
o.write("UPDATE price_items SET name=%s WHERE id=%d;\n" % (esc(new_name), pid))
|
||
for slug, name, price in inserts:
|
||
o.write("INSERT INTO price_items (section_id,name,price,sort,published) "
|
||
"SELECT id,%s,%s,100,true FROM price_sections WHERE slug=%s;\n" % (
|
||
esc(name), price, esc(slug)))
|
||
o.write('COMMIT;\n')
|
||
o.close()
|
||
|
||
print('групп (раздел,название):', len(groups))
|
||
print('групп с расхождением цены:', sum(1 for v in groups.values() if len(v) > 1))
|
||
print('обновлений имени (bitrix-строки):', len(updates))
|
||
print('новых вставок:', len(inserts))
|