74 lines
4.0 KiB
Python
74 lines
4.0 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
Полная перестройка прайса ИСКЛЮЧИТЕЛЬНО из трёх файлов 1С (ЦОМ/Остео/Дети).
|
||
Данные из дампа Bitrix (старого сайта) в прайс больше не подмешиваются.
|
||
|
||
Правила:
|
||
- Позиция группируется по (целевой раздел, название).
|
||
- Если во всех файлах, где она встретилась, цена одна и та же — одна строка,
|
||
имя без изменений.
|
||
- Если цена расходится — по одной строке на каждую уникальную цену, имя
|
||
подписывается источником в скобках: (ЦОМ), (Остео), (Дети), либо их сочетанием,
|
||
если несколько файлов сошлись на одной цене, а другой(ие) — разошлись.
|
||
"""
|
||
import io
|
||
import build_price_map as b
|
||
|
||
DEPT_LABEL = {'D:/ЦОМ.xlsx': 'ЦОМ', 'D:/Остео.xlsx': 'Остео', 'D:/Дана Дети.xls': 'Дети'}
|
||
LABEL_ORDER = ['ЦОМ', 'Остео', 'Дети']
|
||
|
||
def esc(s):
|
||
# В PostgreSQL со standard_conforming_strings обратный слэш — обычный символ.
|
||
# Удваивать его нельзя: имя «Справка №003 П\У» превращалось в «П\У».
|
||
return "'" + str(s).replace("'", "''") + "'"
|
||
|
||
items = [] # (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)
|
||
parsed = b.extract(rows, ncol, pcol)
|
||
label = DEPT_LABEL[path]
|
||
for sec, name, price in parsed:
|
||
key = (sec or '').strip().lower()
|
||
slug = b.MAP.get(key, 'prochee-price')
|
||
items.append((label, slug, name.strip(), price))
|
||
|
||
groups = {} # (slug, name) -> {price: set(labels)}
|
||
for label, slug, name, price in items:
|
||
groups.setdefault((slug, name), {}).setdefault(price, set()).add(label)
|
||
|
||
same_label_conflicts = [] # случаи, когда один и тот же файл даёт 2 разные цены
|
||
rows_out = [] # (slug, final_name, price)
|
||
|
||
for (slug, name), pricemap in groups.items():
|
||
if len(pricemap) == 1:
|
||
(price,) = pricemap.keys()
|
||
rows_out.append((slug, name, price))
|
||
continue
|
||
for price, labels in pricemap.items():
|
||
label_str = ', '.join(l for l in LABEL_ORDER if l in labels)
|
||
rows_out.append((slug, '%s (%s)' % (name, label_str), price))
|
||
# диагностика: конфликт внутри одного и того же файла (не разных отделений)
|
||
all_labels_per_price = list(pricemap.values())
|
||
if any(len(all_labels_per_price[i] & all_labels_per_price[j]) > 0
|
||
for i in range(len(all_labels_per_price))
|
||
for j in range(i + 1, len(all_labels_per_price))):
|
||
same_label_conflicts.append((name, pricemap))
|
||
|
||
o = io.open('seed_price_final.sql', 'w', encoding='utf-8')
|
||
o.write('BEGIN;\n')
|
||
o.write('DELETE FROM price_items;\n') # прайс теперь целиком из 3 файлов 1С
|
||
for i, (slug, name, price) in enumerate(rows_out):
|
||
o.write("INSERT INTO price_items (section_id,name,price,sort,published) "
|
||
"SELECT id,%s,%s,%s,true FROM price_sections WHERE slug=%s;\n" % (
|
||
esc(name), price, i + 1, esc(slug)))
|
||
o.write('COMMIT;\n')
|
||
o.close()
|
||
|
||
print('исходных строк с ценой (3 файла):', len(items))
|
||
print('уникальных групп (раздел,название):', len(groups))
|
||
print('групп с расхождением цены:', sum(1 for v in groups.values() if len(v) > 1))
|
||
print('итоговых строк прайса:', len(rows_out))
|
||
print('конфликтов внутри одного файла (2 цены на одно имя в одном отделении):', len(same_label_conflicts))
|
||
for name, pm in same_label_conflicts[:15]:
|
||
print(' ', name, dict(pm))
|