style: ruff format 对本轮修改文件统一格式
This commit is contained in:
+13
-2
@@ -536,7 +536,13 @@ def build_formula_workbook(ds, member, export_context, output):
|
||||
"导入确认的产品毛利率表",
|
||||
"仅 GrossSource=lookup 的行参与毛利计算;0.2 表示 20%",
|
||||
),
|
||||
("ListAmount", "原价金额", "金额", source_name("list_amount"), "用于扣率与原价客单价;缺失则相关指标不可用"),
|
||||
(
|
||||
"ListAmount",
|
||||
"原价金额",
|
||||
"金额",
|
||||
source_name("list_amount"),
|
||||
"用于扣率与原价客单价;缺失则相关指标不可用",
|
||||
),
|
||||
]
|
||||
for row in [
|
||||
["用途", "公式分析工作簿;本地修改不回写系统。"],
|
||||
@@ -762,7 +768,12 @@ def process_formula_export(export_id):
|
||||
job.save(update_fields=["path", "status", "error", "finished_at", "expires_at"])
|
||||
return stats
|
||||
except Exception as exc:
|
||||
job.status, job.error, job.finished_at, job.expires_at = "failed", str(exc)[:500], timezone.now(), None
|
||||
job.status, job.error, job.finished_at, job.expires_at = (
|
||||
"failed",
|
||||
str(exc)[:500],
|
||||
timezone.now(),
|
||||
None,
|
||||
)
|
||||
# 只清理本次登记且确认位于受控目录内的文件;目录被换成符号链接时拒绝删除。
|
||||
leftover = [path for path in created if _unlink_created_file(path) == "blocked"]
|
||||
if leftover:
|
||||
|
||||
@@ -249,7 +249,9 @@ def formula_definitions(request, dataset_id):
|
||||
raise APIError("定义保存发生并发冲突,请重试", 409) from exc
|
||||
created = True
|
||||
# 审计与定义变更在同一事务内提交;审计失败时变更一并回滚。
|
||||
audit(request, "formula_definition.save", item.pk, {"dataset": str(ds.pk), "name": definition["name"]})
|
||||
audit(
|
||||
request, "formula_definition.save", item.pk, {"dataset": str(ds.pk), "name": definition["name"]}
|
||||
)
|
||||
return JsonResponse(
|
||||
{
|
||||
"id": str(item.pk),
|
||||
|
||||
@@ -23,9 +23,7 @@ class Command(BaseCommand):
|
||||
def handle(self, *args, **options):
|
||||
while True:
|
||||
jobs, files, orphans = self.clean_expired()
|
||||
self.stdout.write(
|
||||
f"Expired {jobs} jobs; removed {files} files; reclaimed {orphans} orphan files"
|
||||
)
|
||||
self.stdout.write(f"Expired {jobs} jobs; removed {files} files; reclaimed {orphans} orphan files")
|
||||
if not options["loop"]:
|
||||
return
|
||||
time.sleep(max(60, options["interval"]))
|
||||
|
||||
@@ -4,15 +4,14 @@ from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('finance', '0004_formuladefinition'),
|
||||
("finance", "0004_formuladefinition"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='formuladefinition',
|
||||
name='revision',
|
||||
model_name="formuladefinition",
|
||||
name="revision",
|
||||
field=models.PositiveIntegerField(default=1),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -98,9 +98,7 @@ def test_formula_workbook_exposes_custom_metric_as_recalculable_column(formula_d
|
||||
assert custom["B1"].value == "收入成本差(本期)"
|
||||
assert custom["B2"].value == f"='分析汇总'!C{metric_row}"
|
||||
custom_note = next(
|
||||
str(row[1])
|
||||
for row in workbook["使用说明"].iter_rows(values_only=True)
|
||||
if row[0] == "收入成本差"
|
||||
str(row[1]) for row in workbook["使用说明"].iter_rows(values_only=True) if row[0] == "收入成本差"
|
||||
)
|
||||
assert "含义:实际收入减成本" in custom_note
|
||||
assert "范围:按所选分组及本期、基期计算" in custom_note
|
||||
|
||||
@@ -54,10 +54,21 @@ def test_to_decimal_evaluator_golden_samples():
|
||||
{"operator": "divide", "left": {"metric": "revenue"}, "right": {"metric": "customers"}}, values
|
||||
) == Decimal("999999999999.99") / Decimal("7")
|
||||
# 除零与缺失指标返回 None(对应 Excel #N/A)
|
||||
assert to_decimal({"operator": "divide", "left": {"metric": "revenue"}, "right": {"number": 0}}, values) is None
|
||||
assert to_decimal({"operator": "add", "left": {"metric": "cost"}, "right": {"metric": "customers"}}, {**values, "customers": None}) is None
|
||||
assert (
|
||||
to_decimal({"operator": "divide", "left": {"metric": "revenue"}, "right": {"number": 0}}, values)
|
||||
is None
|
||||
)
|
||||
assert (
|
||||
to_decimal(
|
||||
{"operator": "add", "left": {"metric": "cost"}, "right": {"metric": "customers"}},
|
||||
{**values, "customers": None},
|
||||
)
|
||||
is None
|
||||
)
|
||||
# 负数与常数组合
|
||||
assert to_decimal({"operator": "subtract", "left": {"number": -2.5}, "right": {"metric": "cost"}}, values) == Decimal("-2.5") - Decimal("0.0000001")
|
||||
assert to_decimal(
|
||||
{"operator": "subtract", "left": {"number": -2.5}, "right": {"metric": "cost"}}, values
|
||||
) == Decimal("-2.5") - Decimal("0.0000001")
|
||||
|
||||
|
||||
def test_reconcile_uses_independent_tolerances_per_metric_kind(workspace):
|
||||
@@ -72,7 +83,16 @@ def test_reconcile_uses_independent_tolerances_per_metric_kind(workspace):
|
||||
workbook = load_workbook(BytesIO(output.getvalue()), data_only=False)
|
||||
sheet = workbook["对账检查"]
|
||||
rows = list(sheet.iter_rows(values_only=True))
|
||||
assert list(rows[0]) == ["指标", "分组", "期间侧", "服务器 Decimal 参考", "公式结果", "差异", "容差", "状态"]
|
||||
assert list(rows[0]) == [
|
||||
"指标",
|
||||
"分组",
|
||||
"期间侧",
|
||||
"服务器 Decimal 参考",
|
||||
"公式结果",
|
||||
"差异",
|
||||
"容差",
|
||||
"状态",
|
||||
]
|
||||
|
||||
def find(metric, side="本期"):
|
||||
return next(row for row in rows[1:] if row[0] == metric and row[2] == side)
|
||||
@@ -84,7 +104,9 @@ def test_reconcile_uses_independent_tolerances_per_metric_kind(workspace):
|
||||
assert find("ROI")[6] == pytest.approx(0.0001)
|
||||
assert find("客单价")[6] == pytest.approx(0.0001)
|
||||
# 状态公式按容差列比较(<=G),不再统一 <0.01
|
||||
status = next(cell.value for cell in sheet[2] if isinstance(cell.value, str) and cell.value.startswith("=IF(D"))
|
||||
status = next(
|
||||
cell.value for cell in sheet[2] if isinstance(cell.value, str) and cell.value.startswith("=IF(D")
|
||||
)
|
||||
assert "<=G2" in status
|
||||
# 参数页写明对账规则,容差调整需财务批准
|
||||
parameters = {str(row[0]): row for row in workbook["参数与口径"].iter_rows(values_only=True) if row[0]}
|
||||
@@ -208,8 +230,7 @@ def test_reconcile_passes_in_libreoffice_with_per_metric_tolerances(workspace, t
|
||||
assert result.returncode == 0, result.stderr or result.stdout
|
||||
values = load_workbook(output / workbook_path.name, data_only=True)
|
||||
statuses = [
|
||||
(row[0], row[1], row[2], row[7])
|
||||
for row in values["对账检查"].iter_rows(min_row=2, values_only=True)
|
||||
(row[0], row[1], row[2], row[7]) for row in values["对账检查"].iter_rows(min_row=2, values_only=True)
|
||||
]
|
||||
assert statuses
|
||||
assert all(status in ("通过", "无参考") for *_head, status in statuses), statuses
|
||||
|
||||
@@ -88,26 +88,21 @@ def test_status_and_download_deny_revoked_viewer(workspace, settings):
|
||||
job.save(update_fields=["path"])
|
||||
|
||||
assert client.get(f"/api/datasets/{ds.pk}/formula-exports/{job.pk}").status_code == 200
|
||||
assert (
|
||||
client.get(f"/api/datasets/{ds.pk}/formula-exports/{job.pk}/download").status_code == 200
|
||||
)
|
||||
assert client.get(f"/api/datasets/{ds.pk}/formula-exports/{job.pk}/download").status_code == 200
|
||||
|
||||
member.role = "viewer"
|
||||
member.save(update_fields=["role"])
|
||||
assert client.get(f"/api/datasets/{ds.pk}/formula-exports/{job.pk}").status_code == 403
|
||||
assert (
|
||||
client.get(f"/api/datasets/{ds.pk}/formula-exports/{job.pk}/download").status_code == 403
|
||||
)
|
||||
assert client.get(f"/api/datasets/{ds.pk}/formula-exports/{job.pk}/download").status_code == 403
|
||||
|
||||
|
||||
def test_half_finished_export_cannot_be_downloaded(workspace, settings):
|
||||
ds, _, client, *_ = workspace
|
||||
for status, code in (("processing", 409), ("failed", 409), ("queued", 409)):
|
||||
job = _export_job(ds, status=status)
|
||||
assert (
|
||||
client.get(f"/api/datasets/{ds.pk}/formula-exports/{job.pk}/download").status_code
|
||||
== code
|
||||
), status
|
||||
assert client.get(f"/api/datasets/{ds.pk}/formula-exports/{job.pk}/download").status_code == code, (
|
||||
status
|
||||
)
|
||||
succeeded = _export_job(
|
||||
ds,
|
||||
status="succeeded",
|
||||
@@ -115,18 +110,13 @@ def test_half_finished_export_cannot_be_downloaded(workspace, settings):
|
||||
finished_at=timezone.now(),
|
||||
expires_at=timezone.now() + timedelta(hours=1),
|
||||
)
|
||||
assert (
|
||||
client.get(f"/api/datasets/{ds.pk}/formula-exports/{succeeded.pk}/download").status_code
|
||||
== 410
|
||||
)
|
||||
assert client.get(f"/api/datasets/{ds.pk}/formula-exports/{succeeded.pk}/download").status_code == 410
|
||||
|
||||
|
||||
def test_stale_processing_export_is_reclaimed_after_timeout(workspace):
|
||||
ds, *_ = workspace
|
||||
job = _export_job(ds, status="processing")
|
||||
FormulaExport.objects.filter(pk=job.pk).update(
|
||||
created_at=timezone.now() - timedelta(minutes=20)
|
||||
)
|
||||
FormulaExport.objects.filter(pk=job.pk).update(created_at=timezone.now() - timedelta(minutes=20))
|
||||
|
||||
call_command("import_worker", once=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user