test_pl_plan_archive_zip_export.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import io
  2. import zipfile
  3. from openpyxl import load_workbook
  4. from app.services.pl_plan_archive_zip_export import (
  5. sanitize_zip_segment,
  6. build_attachment_filename,
  7. first_row_no_by_plan_id,
  8. build_hyperlink_formula,
  9. parse_url_list,
  10. collect_hazard_cert_items,
  11. merge_plan_attachment_items,
  12. build_archive_zip_bytes,
  13. )
  14. from app.utils.excel_export import ExportColumn
  15. def test_sanitize_zip_segment():
  16. assert sanitize_zip_segment("装货·司机/A") == "装货·司机_A"
  17. assert sanitize_zip_segment(" a ") == "a"
  18. def test_build_attachment_filename():
  19. name = build_attachment_filename(1, "装货·司机", "https://cdn.example/path/a.jpg")
  20. assert name.startswith("01_装货·司机_")
  21. assert name.endswith(".jpg")
  22. def test_first_row_no_by_plan_id():
  23. rows = [
  24. {"planId": "p1", "rowNo": 1},
  25. {"planId": "p1", "rowNo": 2},
  26. {"planId": "p2", "rowNo": 3},
  27. ]
  28. assert first_row_no_by_plan_id(rows) == {"p1": 1, "p2": 3}
  29. def test_build_hyperlink_formula():
  30. f = build_hyperlink_formula("附件/01_司机_ab12.jpg", "司机")
  31. assert f.startswith('=HYPERLINK(')
  32. assert "附件/01_司机_ab12.jpg" in f
  33. def test_parse_url_list_csv_and_json():
  34. assert parse_url_list("a.jpg,b.jpg") == ["a.jpg", "b.jpg"]
  35. assert parse_url_list('["x.png","y.png"]') == ["x.png", "y.png"]
  36. def test_collect_hazard_cert_items_labels():
  37. class P:
  38. product_name = "甲醇"
  39. purchase_cert_url = "https://x/p.pdf"
  40. transport_cert_url = None
  41. legal_use_cert_url = "https://x/l1.pdf,https://x/l2.pdf"
  42. items = collect_hazard_cert_items([P()])
  43. labels = [i["label"] for i in items]
  44. assert "购买证" in labels[0]
  45. assert any("合法使用证明" in x for x in labels)
  46. assert len(items) == 3
  47. def test_merge_dedupes_url():
  48. doc = [{"url": "https://a/1.jpg", "label": "司机"}]
  49. haz = [{"url": "https://a/1.jpg", "label": "购买证"}]
  50. merged = merge_plan_attachment_items(doc, haz)
  51. assert len(merged) == 1
  52. assert merged[0]["label"] == "司机"
  53. def test_build_archive_zip_bytes_structure_and_hyperlink():
  54. columns = [
  55. ExportColumn(title="序号", field="rowNo"),
  56. ExportColumn(title="计划编号", field="planNo"),
  57. ]
  58. rows = [
  59. {"planId": "p1", "rowNo": 1, "planNo": "PL001"},
  60. {"planId": "p1", "rowNo": 2, "planNo": "PL001"},
  61. ]
  62. attachments_by_plan = {
  63. "p1": [{"url": "https://cdn.example/a.jpg", "label": "司机"}],
  64. }
  65. def fake_download(url: str) -> bytes:
  66. return b"fake-image-bytes"
  67. stamp = "202609231230"
  68. data, failures = build_archive_zip_bytes(
  69. db=None,
  70. tenant_no="t1",
  71. columns=columns,
  72. rows=rows,
  73. attachments_by_plan=attachments_by_plan,
  74. stamp=stamp,
  75. download_fn=fake_download,
  76. )
  77. assert failures == []
  78. with zipfile.ZipFile(io.BytesIO(data)) as zf:
  79. names = zf.namelist()
  80. assert f"计划归档({stamp})/(总表)计划归档.xlsx" in names
  81. att = [n for n in names if n.startswith(f"计划归档({stamp})/附件/")]
  82. assert len(att) == 1
  83. assert "01_司机_" in att[0]
  84. xlsx_bytes = zf.read(f"计划归档({stamp})/(总表)计划归档.xlsx")
  85. wb = load_workbook(io.BytesIO(xlsx_bytes))
  86. ws = wb.active
  87. headers = [c.value for c in ws[1]]
  88. assert "附件_1" in headers
  89. attach_col = headers.index("附件_1") + 1
  90. assert str(ws.cell(2, attach_col).value).startswith("=HYPERLINK(")
  91. assert ws.cell(3, attach_col).value in (None, "")