test_basic_experiment_delivery_remind.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. """基础实验交付日前一天服务号提醒单测。"""
  2. from datetime import date, datetime
  3. from unittest.mock import MagicMock, patch
  4. from app.services.basic_experiment_delivery_remind import (
  5. format_delivery_product_name,
  6. run_delivery_remind_for_date,
  7. )
  8. def test_format_delivery_product_name_full():
  9. assert (
  10. format_delivery_product_name(
  11. project_name="NK扩增",
  12. spec_text="1e8",
  13. package_text="冻存管",
  14. )
  15. == "NK扩增(1e8、冻存管)"
  16. )
  17. def test_format_delivery_product_name_name_and_spec_only():
  18. assert (
  19. format_delivery_product_name(
  20. project_name="NK扩增",
  21. spec_text="1e8",
  22. package_text="",
  23. )
  24. == "NK扩增(1e8)"
  25. )
  26. def test_format_delivery_product_name_name_and_package_only():
  27. assert (
  28. format_delivery_product_name(
  29. project_name="NK扩增",
  30. spec_text="",
  31. package_text="冻存管",
  32. )
  33. == "NK扩增(冻存管)"
  34. )
  35. def test_format_delivery_product_name_name_only():
  36. assert (
  37. format_delivery_product_name(
  38. project_name="NK扩增",
  39. spec_text="",
  40. package_text="",
  41. )
  42. == "NK扩增"
  43. )
  44. def test_format_delivery_product_name_empty():
  45. assert (
  46. format_delivery_product_name(
  47. project_name="",
  48. spec_text="",
  49. package_text="",
  50. )
  51. == ""
  52. )
  53. def test_send_basic_experiment_delivery_remind_builds_data():
  54. with patch(
  55. "app.services.wechat_mp_message._send_template"
  56. ) as send_tpl, patch("app.services.wechat_mp_message.settings") as st:
  57. st.WX_MP_TEMPLATE_BASIC_EXPERIMENT_DELIVERY = "tpl-be"
  58. st.WX_MP_TPL_BE_DELIVERY_FIELD_CUSTOMER = "thing6"
  59. st.WX_MP_TPL_BE_DELIVERY_FIELD_PRODUCT = "thing10"
  60. st.WX_MP_TPL_BE_DELIVERY_FIELD_QTY = "character_string8"
  61. st.WX_MP_TPL_BE_DELIVERY_FIELD_CONTACT = "thing7"
  62. st.WX_MP_TPL_BE_DELIVERY_FIELD_TIME = "time14"
  63. send_tpl.return_value = {"success": True, "msgid": "1"}
  64. from app.services.wechat_mp_message import send_basic_experiment_delivery_remind
  65. long_name = "这是一个超过二十个汉字的产品名称规格包装拼接"
  66. send_basic_experiment_delivery_remind(
  67. mp_openid="oid",
  68. customer_name="张三客户",
  69. product_name=long_name,
  70. quantity="3",
  71. contact_name="李联系人",
  72. time_text="2026-10-23 14:00",
  73. )
  74. assert send_tpl.called
  75. kwargs = send_tpl.call_args.kwargs
  76. assert kwargs["template_id"] == "tpl-be"
  77. assert kwargs["mp_openid"] == "oid"
  78. data = kwargs["data"]
  79. assert data["thing6"]["value"] == "张三客户"
  80. assert len(data["thing10"]["value"]) <= 20
  81. assert data["character_string8"]["value"] == "3"
  82. assert data["thing7"]["value"] == "李联系人"
  83. assert data["time14"]["value"] == "2026-10-23 14:00"
  84. def _make_db_for_remind(
  85. *,
  86. schedules,
  87. already_success=False,
  88. user_openid="mp-oid",
  89. ):
  90. """构造轻量 MagicMock Session,覆盖 remind 扫描路径。"""
  91. db = MagicMock()
  92. candidate_q = MagicMock()
  93. candidate_q.join.return_value = candidate_q
  94. candidate_q.outerjoin.return_value = candidate_q
  95. candidate_q.filter.return_value = candidate_q
  96. candidate_q.order_by.return_value = candidate_q
  97. candidate_q.all.return_value = schedules
  98. success_q = MagicMock()
  99. success_q.filter.return_value = success_q
  100. success_q.first.return_value = MagicMock() if already_success else None
  101. user = MagicMock()
  102. user.wx_mp_openid = user_openid
  103. user_q = MagicMock()
  104. user_q.filter.return_value = user_q
  105. user_q.first.return_value = user
  106. def query_side_effect(*models):
  107. from app.models.models import BizWxNotifyLog, SysUser
  108. if len(models) > 1:
  109. return candidate_q
  110. model = models[0]
  111. if model is BizWxNotifyLog:
  112. return success_q
  113. if model is SysUser:
  114. return user_q
  115. return candidate_q
  116. db.query.side_effect = query_side_effect
  117. return db
  118. def test_run_delivery_remind_sends_for_tomorrow_schedule():
  119. sched = MagicMock()
  120. sched.id = "sch-1"
  121. sched.tenant_no = "zkxw"
  122. sched.infusion_time = datetime(2026, 10, 23, 14, 0, 0)
  123. sched.spec_text = "1e8"
  124. sched.package_text = "冻存管"
  125. sched.schedule_status = "dsc"
  126. app = MagicMock()
  127. app.id = "app-1"
  128. app.tenant_no = "zkxw"
  129. app.create_by = "user-1"
  130. app.customer_name = "客户甲"
  131. app.customer_contact = "联系人乙"
  132. prod = MagicMock()
  133. prod.project_name = "NK扩增"
  134. prod.spec_text = "1e8"
  135. prod.package_text = "冻存管"
  136. prod.quantity = 2
  137. db = _make_db_for_remind(schedules=[(sched, app, prod)])
  138. with patch(
  139. "app.services.basic_experiment_delivery_remind._notify_enabled",
  140. return_value=True,
  141. ), patch(
  142. "app.services.wechat_mp_message.send_basic_experiment_delivery_remind"
  143. ) as send_fn:
  144. send_fn.return_value = {"success": True, "msgid": "m1"}
  145. stats = run_delivery_remind_for_date(db, today=date(2026, 10, 22))
  146. assert stats["candidates"] == 1
  147. assert stats["sent"] == 1
  148. assert send_fn.called
  149. kwargs = send_fn.call_args.kwargs
  150. assert kwargs["customer_name"] == "客户甲"
  151. assert kwargs["product_name"] == "NK扩增(1e8、冻存管)"
  152. assert kwargs["quantity"] == "2"
  153. assert kwargs["contact_name"] == "联系人乙"
  154. assert kwargs["time_text"] == "2026-10-23 14:00"
  155. assert db.add.called
  156. assert db.commit.called
  157. def test_run_delivery_remind_skips_when_already_success():
  158. sched = MagicMock()
  159. sched.id = "sch-1"
  160. sched.tenant_no = "zkxw"
  161. sched.infusion_time = datetime(2026, 10, 23, 14, 0, 0)
  162. sched.spec_text = ""
  163. sched.package_text = ""
  164. app = MagicMock()
  165. app.id = "app-1"
  166. app.tenant_no = "zkxw"
  167. app.create_by = "user-1"
  168. app.customer_name = "客户甲"
  169. app.customer_contact = "联系人乙"
  170. prod = MagicMock()
  171. prod.project_name = "NK"
  172. prod.spec_text = ""
  173. prod.package_text = ""
  174. prod.quantity = 1
  175. db = _make_db_for_remind(
  176. schedules=[(sched, app, prod)], already_success=True
  177. )
  178. with patch(
  179. "app.services.basic_experiment_delivery_remind._notify_enabled",
  180. return_value=True,
  181. ), patch(
  182. "app.services.wechat_mp_message.send_basic_experiment_delivery_remind"
  183. ) as send_fn:
  184. send_fn.return_value = {"success": True}
  185. stats = run_delivery_remind_for_date(db, today=date(2026, 10, 22))
  186. assert stats["skipped"] == 1
  187. assert stats["sent"] == 0
  188. assert not send_fn.called
  189. def test_run_delivery_remind_skips_without_openid():
  190. sched = MagicMock()
  191. sched.id = "sch-1"
  192. sched.tenant_no = "zkxw"
  193. sched.infusion_time = datetime(2026, 10, 23, 9, 0, 0)
  194. sched.spec_text = ""
  195. sched.package_text = ""
  196. app = MagicMock()
  197. app.id = "app-1"
  198. app.tenant_no = "zkxw"
  199. app.create_by = "user-1"
  200. app.customer_name = "客户甲"
  201. app.customer_contact = "联系人乙"
  202. prod = MagicMock()
  203. prod.project_name = "NK"
  204. prod.spec_text = ""
  205. prod.package_text = ""
  206. prod.quantity = 1
  207. db = _make_db_for_remind(
  208. schedules=[(sched, app, prod)], user_openid=""
  209. )
  210. with patch(
  211. "app.services.basic_experiment_delivery_remind._notify_enabled",
  212. return_value=True,
  213. ), patch(
  214. "app.services.wechat_mp_message.send_basic_experiment_delivery_remind"
  215. ) as send_fn:
  216. stats = run_delivery_remind_for_date(db, today=date(2026, 10, 22))
  217. assert stats["skipped"] == 1
  218. assert not send_fn.called
  219. def test_run_delivery_remind_noop_when_disabled():
  220. db = MagicMock()
  221. with patch(
  222. "app.services.basic_experiment_delivery_remind._notify_enabled",
  223. return_value=False,
  224. ):
  225. stats = run_delivery_remind_for_date(db, today=date(2026, 10, 22))
  226. assert stats == {"candidates": 0, "sent": 0, "skipped": 0, "failed": 0}
  227. assert not db.query.called