chore: import existing codebase as baseline
Verify / verify (push) Failing after 1m20s

This commit is contained in:
Jayway Liu
2026-09-26 01:12:10 +08:00
commit 0ac0c4eb56
77 changed files with 14155 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
import hashlib
import zipfile
from datetime import date
from decimal import Decimal
from io import BytesIO
import pytest
from django.contrib.auth.models import User
from finance.importing import (
decimal,
file_digest,
period_value,
process_dataset,
profile_file,
rows_for,
safe_text,
suggest_mapping,
validate_archive,
validate_mapping,
)
from finance.models import Dataset, Membership, Organization
pytestmark = pytest.mark.django_db
@pytest.fixture
def import_dataset(tmp_path, settings):
settings.MEDIA_ROOT = tmp_path
org = Organization.objects.create(name="Import tests")
user = User.objects.create_user("importer", password="Import-TestPassword991!")
Membership.objects.create(user=user, organization=org, role="admin")
ds = Dataset.objects.create(
organization=org,
created_by=user,
name="sample.csv",
sha256="c" * 64,
status="queued",
mapping={
"sheet": "CSV",
"header": 1,
"columns": [
{"index": 0, "name": "期间", "role": "period"},
{"index": 1, "name": "科室", "role": "dimension", "key": "department"},
{"index": 2, "name": "产品一级分类", "role": "dimension", "key": "product"},
{"index": 3, "name": "实际收入", "role": "revenue"},
{"index": 4, "name": "毛利贡献", "role": "gross"},
{"index": 5, "name": "客户编码", "role": "customer"},
],
"roi_formula": "profit_over_cost",
"margin_rates": {"医疗服务": "0.6"},
},
)
source = tmp_path / "sample.csv"
source.write_text(
"期间,科室,产品一级分类,实际收入,毛利贡献,客户编码\n"
"2026-08,儿科,医疗服务,100,60,C1\n"
"2026-08,儿科,未知产品,25,,\n"
"\n",
encoding="utf-8",
)
ds.file.name = str(source)
ds.save(update_fields=["file"])
return ds
def test_csv_import_commits_rows_quality_and_derived_gross(import_dataset):
ds = process_dataset(import_dataset.pk)
assert ds.status == "ready"
assert ds.row_count == 2
assert ds.periods == ["2026-08"]
assert ds.quality["missing_cost"] == 2
assert ds.quality["missing_gross"] == 1
assert ds.quality["missing_customer"] == 1
assert ds.quality["blank_rows"] == 1
assert list(ds.facts.order_by("source_row").values_list("gross", flat=True)) == [
Decimal("60.000000000000000000000000"),
None,
]
assert ds.facts.get(source_row=2).dimensions["department"] == "儿科"
def test_profile_csv_mapping_and_file_digest(tmp_path):
source = tmp_path / "input.csv"
source.write_text("期间,科室,实际收入\n2026-08,儿科,12\n", encoding="utf-8")
profile = profile_file(source)
mapping = suggest_mapping(profile)
assert mapping["columns"][0]["role"] == "period"
assert mapping["columns"][2]["role"] == "revenue"
assert validate_mapping(mapping, profile) == mapping
from django.core.files.uploadedfile import SimpleUploadedFile
upload = SimpleUploadedFile("input.csv", source.read_bytes(), content_type="text/csv")
assert file_digest(upload) == hashlib.sha256(source.read_bytes()).hexdigest()
def test_safe_text_and_period_inputs():
assert safe_text(date(2026, 8, 3)) == "2026-08-03"
assert safe_text("x" * 5000) == "x" * 4000
assert period_value({"period": date(2026, 8, 3)}) == "2026-08"
assert period_value({"period": "2026-8-19T12:00:00"}) == "2026-08"
with pytest.raises(ValueError, match="精度"):
decimal("0.0000000000000000000000001")
def test_archive_rejects_macro_and_external_links():
for member in ("xl/vbaProject.bin", "xl/externalLinks/externalLink1.xml"):
archive_file = BytesIO()
with zipfile.ZipFile(archive_file, "w") as archive:
archive.writestr(member, "blocked")
archive_file.seek(0)
with pytest.raises(ValueError, match="宏或外部链接"):
validate_archive(archive_file)
def test_workbook_rows_can_read_formulas_from_selected_sheet(tmp_path):
from openpyxl import Workbook
path = tmp_path / "book.xlsx"
workbook = Workbook()
workbook.active.title = "Data"
workbook.active.append(["value"])
workbook.active.append(["=1+1"])
workbook.save(path)
assert list(rows_for(path, "Data", formulas=True)) == [("value",), ("=1+1",)]