test_save_samples_keeps_id.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. """协议样本保存保留原行 ID,避免下游外键被整表替换打断。"""
  2. import unittest
  3. from datetime import datetime
  4. from unittest.mock import patch
  5. from sqlalchemy import create_engine
  6. from sqlalchemy.orm import sessionmaker
  7. from app.crud.collection_protocol import save_samples
  8. from app.crud.research_donation import _create_samples
  9. from app.models.models import BizProtocolSample
  10. from app.models.research_donation import (
  11. BizResearchDonationSample,
  12. BizResearchDonationSampleTransport,
  13. )
  14. def _session():
  15. engine = create_engine("sqlite://")
  16. BizProtocolSample.__table__.create(bind=engine)
  17. return sessionmaker(bind=engine)()
  18. def _sample(**kwargs):
  19. now = datetime(2026, 10, 27, 9, 0, 0)
  20. data = dict(
  21. collection_protocol_id="proto-1",
  22. tenant_no="tenant-a",
  23. create_dept_id="",
  24. create_time=now,
  25. update_time=now,
  26. del_flag=0,
  27. )
  28. data.update(kwargs)
  29. return BizProtocolSample(**data)
  30. class TestSaveSamplesKeepsIdentity(unittest.TestCase):
  31. def test_existing_sample_keeps_id_and_removed_sample_is_soft_deleted(self):
  32. db = _session()
  33. db.add(_sample(id="sample-keep", sample_code="SC001"))
  34. db.add(_sample(id="sample-drop", sample_code="SC002"))
  35. db.commit()
  36. with patch("app.crud.sample_freight.apply_freight_on_protocol_save"), patch(
  37. "app.crud.collection_protocol.save_sample_transports"
  38. ), patch("app.crud.collection_protocol._migrate_sample_child_refs_on_replace"):
  39. saved = save_samples(
  40. db,
  41. "proto-1",
  42. "tenant-a",
  43. "user-1",
  44. [{"id": "sample-keep", "sample_code": "SC001", "remark": "改备注"}],
  45. )
  46. self.assertEqual(saved[0].id, "sample-keep")
  47. self.assertEqual(saved[0].remark, "改备注")
  48. rows = {row.id: row for row in db.query(BizProtocolSample).all()}
  49. self.assertEqual(rows["sample-keep"].del_flag, 0)
  50. self.assertEqual(rows["sample-drop"].del_flag, 1)
  51. def test_same_sample_code_without_id_still_keeps_row(self):
  52. db = _session()
  53. db.add(_sample(id="sample-keep", sample_code="SC001", remark="旧"))
  54. db.commit()
  55. with patch("app.crud.sample_freight.apply_freight_on_protocol_save"), patch(
  56. "app.crud.collection_protocol.save_sample_transports"
  57. ), patch("app.crud.collection_protocol._migrate_sample_child_refs_on_replace"):
  58. saved = save_samples(
  59. db,
  60. "proto-1",
  61. "tenant-a",
  62. "user-1",
  63. [{"sample_code": "SC001", "remark": "新"}],
  64. )
  65. self.assertEqual(saved[0].id, "sample-keep")
  66. self.assertEqual(saved[0].remark, "新")
  67. self.assertEqual(db.query(BizProtocolSample).filter_by(del_flag=0).count(), 1)
  68. class TestDonationSamplesKeepIdentity(unittest.TestCase):
  69. def test_existing_donation_sample_keeps_id(self):
  70. engine = create_engine("sqlite://")
  71. BizResearchDonationSample.__table__.create(bind=engine)
  72. BizResearchDonationSampleTransport.__table__.create(bind=engine)
  73. db = sessionmaker(bind=engine)()
  74. now = datetime(2026, 10, 27, 9, 0, 0)
  75. db.add(
  76. BizResearchDonationSample(
  77. id="don-keep",
  78. research_donation_id="don-1",
  79. tenant_no="tenant-a",
  80. sample_code="DN001",
  81. create_dept_id="",
  82. create_time=now,
  83. update_time=now,
  84. del_flag=0,
  85. )
  86. )
  87. db.add(
  88. BizResearchDonationSample(
  89. id="don-drop",
  90. research_donation_id="don-1",
  91. tenant_no="tenant-a",
  92. sample_code="DN002",
  93. create_dept_id="",
  94. create_time=now,
  95. update_time=now,
  96. del_flag=0,
  97. )
  98. )
  99. db.commit()
  100. saved = _create_samples(
  101. db,
  102. "don-1",
  103. "tenant-a",
  104. "user-1",
  105. [{"sample_code": "DN001", "remark": "留下"}],
  106. now,
  107. )
  108. self.assertEqual(saved[0].id, "don-keep")
  109. self.assertEqual(saved[0].remark, "留下")
  110. rows = {row.id: row for row in db.query(BizResearchDonationSample).all()}
  111. self.assertEqual(rows["don-keep"].del_flag, 0)
  112. self.assertEqual(rows["don-drop"].del_flag, 1)
  113. if __name__ == "__main__":
  114. unittest.main()