booking-fix: бронь берется из других полей, поправил список колонок, которые можно добавлять в этапы, даты редактируются в российском формате, … #70
82
api/alembic/versions/0015_aggregates_fix.py
Normal file
82
api/alembic/versions/0015_aggregates_fix.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
|
||||||
|
revision = "0015"
|
||||||
|
down_revision = "0014"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
_DOLLAR_TAG_RE = re.compile(r"\$\w+\$")
|
||||||
|
|
||||||
|
|
||||||
|
def _find_dollar_tag(line: str) -> str | None:
|
||||||
|
m = _DOLLAR_TAG_RE.search(line.strip())
|
||||||
|
return m.group(0) if m else None
|
||||||
|
|
||||||
|
|
||||||
|
def _split_statements(sql: str) -> list[str]:
|
||||||
|
statements: list[str] = []
|
||||||
|
current: list[str] = []
|
||||||
|
in_dollar = False
|
||||||
|
dollar_tag: str | None = None
|
||||||
|
|
||||||
|
for line in sql.split("\n"):
|
||||||
|
stripped = line.strip()
|
||||||
|
if stripped.startswith("--"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not in_dollar:
|
||||||
|
tag = _find_dollar_tag(stripped)
|
||||||
|
if tag and tag.endswith("$") and tag.startswith("$"):
|
||||||
|
dollar_tag = tag
|
||||||
|
in_dollar = True
|
||||||
|
current.append(line)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if in_dollar and dollar_tag and stripped.startswith(dollar_tag):
|
||||||
|
after = stripped[len(dollar_tag):].strip()
|
||||||
|
if after == ";" or after == "":
|
||||||
|
in_dollar = False
|
||||||
|
dollar_tag = None
|
||||||
|
if after == ";":
|
||||||
|
current.append(line)
|
||||||
|
statements.append("\n".join(current))
|
||||||
|
current = []
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not in_dollar and stripped.rstrip().endswith(";"):
|
||||||
|
current.append(line)
|
||||||
|
statements.append("\n".join(current))
|
||||||
|
current = []
|
||||||
|
continue
|
||||||
|
|
||||||
|
current.append(line)
|
||||||
|
|
||||||
|
remaining = "\n".join(current).strip()
|
||||||
|
if remaining:
|
||||||
|
statements.append(remaining)
|
||||||
|
|
||||||
|
return statements
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
ddl_path = os.path.join(os.path.dirname(__file__), "sql", "0015_aggregates_fix.sql")
|
||||||
|
with open(ddl_path) as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
statements = _split_statements(content)
|
||||||
|
for stmt in statements:
|
||||||
|
stripped = stmt.strip().rstrip(";").strip()
|
||||||
|
if not stripped:
|
||||||
|
continue
|
||||||
|
if all(l.strip().startswith("--") or not l.strip() for l in stripped.split("\n")):
|
||||||
|
continue
|
||||||
|
op.execute(stripped)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
pass
|
||||||
2906
api/alembic/versions/sql/0015_aggregates_fix.sql
Normal file
2906
api/alembic/versions/sql/0015_aggregates_fix.sql
Normal file
File diff suppressed because one or more lines are too long
@ -7,7 +7,6 @@ from fastapi import APIRouter, Depends, HTTPException, Response
|
|||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from src.services.org_unit_service import OrgUnitService
|
from src.services.org_unit_service import OrgUnitService
|
||||||
from src.services.budget_line_service import BudgetLineService
|
|
||||||
from src.db.models.form_type import FormTypeEnum
|
from src.db.models.form_type import FormTypeEnum
|
||||||
from src.services.sheet_service import SheetService
|
from src.services.sheet_service import SheetService
|
||||||
from src.domain.schemas import AddLineSchema, BaseListResponse, BaseSingleResponse, BudgetFormResponse, CellPatch, CellsPatch, DirectionSchemaEnum, FormCreateSchema, SheetFormTypeResponse, SheetResponse
|
from src.domain.schemas import AddLineSchema, BaseListResponse, BaseSingleResponse, BudgetFormResponse, CellPatch, CellsPatch, DirectionSchemaEnum, FormCreateSchema, SheetFormTypeResponse, SheetResponse
|
||||||
@ -135,7 +134,6 @@ async def get_sheet(
|
|||||||
t0 = time.perf_counter()
|
t0 = time.perf_counter()
|
||||||
bf_service = BudgetFormService(db)
|
bf_service = BudgetFormService(db)
|
||||||
sheet_service = SheetService(db)
|
sheet_service = SheetService(db)
|
||||||
|
|
||||||
form = await bf_service.get(
|
form = await bf_service.get(
|
||||||
user=current_user,
|
user=current_user,
|
||||||
budget_form_id=form_id,
|
budget_form_id=form_id,
|
||||||
|
|||||||
@ -39,7 +39,7 @@ class FormType(Base):
|
|||||||
}
|
}
|
||||||
SECTIONS_BY_FORM_TYPE = {
|
SECTIONS_BY_FORM_TYPE = {
|
||||||
FormTypeEnum.FORM_1: ["plan", "contract_summary", "allocation", "sequestration", "reserve", "approved", "collegial", "ckk", "contract_detail", "q1", "q2", "q3", "q4", "totals"],
|
FormTypeEnum.FORM_1: ["plan", "contract_summary", "allocation", "sequestration", "reserve", "approved", "collegial", "ckk", "contract_detail", "q1", "q2", "q3", "q4", "totals"],
|
||||||
FormTypeEnum.FORM_2: ["plan", "seq_dfip", "seq_ssp", "approved", "contract", "booking", "q1", "q2", "q3", "q4", "totals"],
|
FormTypeEnum.FORM_2: ["plan", "seq_dfip", "seq_ssp", "approved", "contract", "booking", "q1", "q2", "q3", "q4", "totals", "contract_summary", "allocation", "collegial", "ckk", "fact_q1", "fact_q2", "fact_q3", "fact_q4"],
|
||||||
FormTypeEnum.FORM_3: ["q1", "q2", "q3", "q4", "year"],
|
FormTypeEnum.FORM_3: ["q1", "q2", "q3", "q4", "year"],
|
||||||
FormTypeEnum.FORM_4: ["plan", "seq_dfip", "approved", "contract", "booking", "q1", "q2", "q3", "q4", "totals", "contract_summary", "allocation", "reserve", "collegial", "ckk"],
|
FormTypeEnum.FORM_4: ["plan", "seq_dfip", "approved", "contract", "booking", "q1", "q2", "q3", "q4", "totals", "contract_summary", "allocation", "reserve", "collegial", "ckk"],
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,7 +59,7 @@ class FormPhaseService:
|
|||||||
if form_phase.column_keys and budget_form.form_type.section_list:
|
if form_phase.column_keys and budget_form.form_type.section_list:
|
||||||
for column_key in form_phase.column_keys:
|
for column_key in form_phase.column_keys:
|
||||||
section = column_key.split(".")
|
section = column_key.split(".")
|
||||||
if section[0] not in budget_form.form_type.section_list:
|
if len(section) == 2 and section[0] not in budget_form.form_type.section_list:
|
||||||
if "column_keys" in errors:
|
if "column_keys" in errors:
|
||||||
errors["column_keys"].append(f"Колонка {column_key} некорректна")
|
errors["column_keys"].append(f"Колонка {column_key} некорректна")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -96,7 +96,7 @@ const useRealtimeData = (formId, sheetName, direction, formType, year) => {
|
|||||||
} else {
|
} else {
|
||||||
res = await FormsSheetApi.get(formId, sheetName);
|
res = await FormsSheetApi.get(formId, sheetName);
|
||||||
}
|
}
|
||||||
const data = res.result;
|
const data = res.result.filter((d) => d.depth > -1);
|
||||||
|
|
||||||
if (!data || data.length === 0) {
|
if (!data || data.length === 0) {
|
||||||
setData([]);
|
setData([]);
|
||||||
|
|||||||
@ -19,5 +19,5 @@ export function isVspNewRow(rowData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getParentId(data){
|
export function getParentId(data){
|
||||||
return data.project_id || data.expense_item_id || null;
|
return data?.project_id || data?.expense_item_id || null;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user