Initial commit

This commit is contained in:
2026-07-14 01:16:33 +03:00
commit 92f04e0e8a
29 changed files with 2454 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

115
services/contractors.py Normal file
View File

@@ -0,0 +1,115 @@
def get_contractors(conn):
cursor = conn.cursor()
cursor.execute("""
SELECT id, name
FROM contractors
WHERE active = 1
ORDER BY name
""")
return cursor.fetchall()
def get_all_contractors(conn):
cursor = conn.cursor()
cursor.execute("""
SELECT id, name, active
FROM contractors
ORDER BY name
""")
return cursor.fetchall()
def add_contractor(conn, name):
cursor = conn.cursor()
cursor.execute("""
INSERT OR IGNORE INTO contractors(name)
VALUES(?)
""", (name,))
conn.commit()
return cursor.rowcount > 0
def add_contractors_bulk(conn, text):
cursor = conn.cursor()
added = 0
exists = 0
for line in text.splitlines():
name = line.strip()
if not name:
continue
cursor.execute(
"""
INSERT OR IGNORE INTO contractors(name)
VALUES(?)
""",
(name,),
)
if cursor.rowcount:
added += 1
else:
exists += 1
conn.commit()
return added, exists
def activate_contractor(conn, contractor_id):
cursor = conn.cursor()
cursor.execute("""
UPDATE contractors
SET active = 1
WHERE id = ?
""", (contractor_id,))
conn.commit()
def disable_contractor(conn, contractor_id):
cursor = conn.cursor()
cursor.execute("""
UPDATE contractors
SET active = 0
WHERE id = ?
""", (contractor_id,))
conn.commit()
def delete_contractor(conn, contractor_id):
cursor = conn.cursor()
cursor.execute(
"""
UPDATE documents_1c
SET contractor_id = NULL
WHERE contractor_id = ?
""",
(contractor_id,),
)
cursor.execute(
"""
DELETE FROM contractors
WHERE id = ?
""",
(contractor_id,),
)
conn.commit()

55
services/documents.py Normal file
View File

@@ -0,0 +1,55 @@
from datetime import datetime
def update_comment_1c(conn, doc_id, comment):
cursor = conn.cursor()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
cursor.execute(
"""
UPDATE documents_1c
SET comment = ?, updated_at = ?
WHERE id = ?
""",
(comment.strip(), now, doc_id),
)
conn.commit()
return cursor.rowcount > 0
def update_comment_sbis(conn, doc_id, comment):
cursor = conn.cursor()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
cursor.execute(
"""
UPDATE documents_sbis
SET comment = ?, updated_at = ?
WHERE id = ?
""",
(comment.strip(), now, doc_id),
)
conn.commit()
return cursor.rowcount > 0
def get_distinct_states_1c(conn):
rows = conn.execute(
"""
SELECT DISTINCT state
FROM documents_1c
WHERE state IS NOT NULL AND TRIM(state) != ''
ORDER BY state COLLATE NOCASE
"""
).fetchall()
return [r[0] for r in rows]
def get_distinct_states_sbis(conn):
rows = conn.execute(
"""
SELECT DISTINCT state
FROM documents_sbis
WHERE state IS NOT NULL AND TRIM(state) != ''
ORDER BY state COLLATE NOCASE
"""
).fetchall()
return [r[0] for r in rows]

121
services/excel_import.py Normal file
View File

@@ -0,0 +1,121 @@
import pandas as pd
from datetime import datetime
from services.contractors import get_contractors
def _find_column(df, aliases):
for name in aliases:
if name in df.columns:
return name
return None
def import_excel(file, conn):
contractors = {
name: contractor_id
for contractor_id, name in get_contractors(conn)
}
cursor = conn.cursor()
df = pd.read_excel(file)
required = {
"contractor": _find_column(df, ["Контрагент"]),
"doc_type": _find_column(df, ["Вид документа", "Тип документа"]),
"doc_date": _find_column(df, ["Дата", "Дата документа"]),
"doc_number": _find_column(df, ["Номер", "Номер документа"]),
"amount": _find_column(df, ["Сумма"]),
"state": _find_column(df, ["Состояние ЭДО", "Состояние", "Статус"]),
}
missing = [key for key, col in required.items() if col is None]
if missing:
raise ValueError(
f"В файле не найдены обязательные колонки: {', '.join(missing)}"
)
imported = 0
updated = 0
skipped = 0
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
for _, row in df.iterrows():
contr = str(row[required["contractor"]]).strip()
if contr not in contractors:
skipped += 1
continue
contractor_id = contractors[contr]
doc_type = row[required["doc_type"]]
doc_date = row[required["doc_date"]]
number = row[required["doc_number"]]
summ = row[required["amount"]]
state = row[required["state"]]
amount = float(summ) if pd.notna(summ) else 0
cursor.execute(
"""
SELECT id
FROM documents_1c
WHERE contractor_id = ?
AND doc_type = ?
AND doc_date = ?
AND doc_number = ?
AND amount = ?
""",
(
contractor_id,
str(doc_type),
str(doc_date),
str(number),
amount,
),
)
document = cursor.fetchone()
if document:
cursor.execute(
"""
UPDATE documents_1c
SET state = ?, updated_at = ?
WHERE id = ?
""",
(str(state), now, document[0]),
)
updated += 1
else:
cursor.execute(
"""
INSERT INTO documents_1c (
contractor_id,
doc_type,
doc_date,
doc_number,
amount,
state,
comment,
created_at,
updated_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
contractor_id,
str(doc_type),
str(doc_date),
str(number),
amount,
str(state),
"",
now,
now,
),
)
imported += 1
conn.commit()
return imported, updated, skipped

152
services/sbis_import.py Normal file
View File

@@ -0,0 +1,152 @@
import pandas as pd
from datetime import datetime
from services.contractors import get_contractors
def _find_column(df, aliases):
for name in aliases:
if name in df.columns:
return name
return None
def import_sbis_excel(file, conn):
contractors = {
name: contractor_id
for contractor_id, name in get_contractors(conn)
}
cursor = conn.cursor()
df = pd.read_excel(file)
required = {
"contractor": _find_column(
df, ["Контрагент", "Наименование контрагента", "Организация"]
),
"doc_date": _find_column(df, ["Дата", "Дата документа"]),
"doc_number": _find_column(df, ["Номер", "Номер документа"]),
"doc_type": _find_column(df, ["Вид документа", "Тип документа", "Тип"]),
"amount": _find_column(df, ["Сумма"]),
"state": _find_column(df, ["Состояние", "Статус", "Состояние документа"]),
}
missing = [key for key, col in required.items() if col is None]
if missing:
raise ValueError(
f"В файле не найдены обязательные колонки: {', '.join(missing)}"
)
responsible_col = _find_column(
df, ["Ответственный", "Ответственный сотрудник"]
)
description_col = _find_column(df, ["Описание", "Комментарий", "Примечание"])
imported = 0
updated = 0
skipped = 0
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Получаем максимальный row_order для новых записей
cursor.execute("SELECT COALESCE(MAX(row_order), 0) FROM documents_sbis")
max_order = cursor.fetchone()[0] or 0
for idx, (_, row) in enumerate(df.iterrows()):
contr = str(row[required["contractor"]]).strip()
if contr not in contractors:
skipped += 1
continue
doc_type = row[required["doc_type"]]
doc_date = row[required["doc_date"]]
number = row[required["doc_number"]]
summ = row[required["amount"]]
state = row[required["state"]]
amount = float(summ) if pd.notna(summ) else 0
responsible = (
str(row[responsible_col]).strip()
if responsible_col and pd.notna(row[responsible_col])
else None
)
description = (
str(row[description_col]).strip()
if description_col and pd.notna(row[description_col])
else None
)
# Проверяем существование документа
cursor.execute(
"""
SELECT id
FROM documents_sbis
WHERE contractor = ?
AND doc_type = ?
AND doc_date = ?
AND doc_number = ?
AND amount = ?
""",
(
contr,
str(doc_type),
str(doc_date),
str(number),
amount,
),
)
document = cursor.fetchone()
if document:
cursor.execute(
"""
UPDATE documents_sbis
SET state = ?,
responsible = COALESCE(?, responsible),
description = COALESCE(?, description),
updated_at = ?
WHERE id = ?
""",
(str(state), responsible, description, now, document[0]),
)
updated += 1
else:
row_order = max_order + idx + 1
cursor.execute(
"""
INSERT INTO documents_sbis (
raw_text,
doc_date,
doc_number,
contractor,
doc_type,
amount,
description,
state,
responsible,
created_at,
updated_at,
row_order
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
None,
str(doc_date),
str(number),
contr,
str(doc_type),
amount,
description,
str(state),
responsible,
now,
now,
row_order,
),
)
imported += 1
conn.commit()
return imported, updated, skipped