velocity-python 0.1.16__tar.gz → 0.1.18__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. {velocity_python-0.1.16/src/velocity_python.egg-info → velocity_python-0.1.18}/PKG-INFO +1 -1
  2. {velocity_python-0.1.16 → velocity_python-0.1.18}/pyproject.toml +1 -1
  3. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/__init__.py +1 -1
  4. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/base_handler.py +10 -9
  5. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/context.py +31 -13
  6. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/exceptions.py +6 -1
  7. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/lambda_handler.py +3 -3
  8. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/mixins/web_handler.py +23 -7
  9. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/mysql/sql.py +2 -2
  10. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlite/sql.py +2 -2
  11. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlserver/sql.py +2 -2
  12. velocity_python-0.1.18/src/velocity/payment/__init__.py +36 -0
  13. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/payment/base_adapter.py +4 -4
  14. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/payment/braintree_adapter.py +18 -9
  15. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/payment/charge_rules.py +4 -4
  16. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/payment/stripe_adapter.py +43 -26
  17. {velocity_python-0.1.16 → velocity_python-0.1.18/src/velocity_python.egg-info}/PKG-INFO +1 -1
  18. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity_python.egg-info/SOURCES.txt +0 -6
  19. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_lambda_handler.py +1 -1
  20. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_payment_stripe_adapter.py +10 -6
  21. velocity_python-0.1.16/src/velocity/payment/__init__.py +0 -96
  22. velocity_python-0.1.16/src/velocity/payment/demo_profiles.py +0 -353
  23. velocity_python-0.1.16/src/velocity/payment/profiles.py +0 -74
  24. velocity_python-0.1.16/src/velocity/payment/router.py +0 -601
  25. velocity_python-0.1.16/tests/test_payment_demo_profiles.py +0 -58
  26. velocity_python-0.1.16/tests/test_payment_profiles.py +0 -72
  27. velocity_python-0.1.16/tests/test_payment_router.py +0 -107
  28. {velocity_python-0.1.16 → velocity_python-0.1.18}/LICENSE +0 -0
  29. {velocity_python-0.1.16 → velocity_python-0.1.18}/README.md +0 -0
  30. {velocity_python-0.1.16 → velocity_python-0.1.18}/setup.cfg +0 -0
  31. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/__init__.py +0 -0
  32. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/amplify.py +0 -0
  33. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/amplify_build.py +0 -0
  34. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/__init__.py +0 -0
  35. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/context_factory.py +0 -0
  36. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
  37. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
  38. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/perf.py +0 -0
  39. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/response.py +0 -0
  40. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/handlers/sqs_handler.py +0 -0
  41. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/tests/__init__.py +0 -0
  42. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/tests/test_base_handler_error_response.py +0 -0
  43. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
  44. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/aws/tests/test_response.py +0 -0
  45. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/__init__.py +0 -0
  46. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/__init__.py +0 -0
  47. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/async_support.py +0 -0
  48. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/column.py +0 -0
  49. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/database.py +0 -0
  50. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/decorators.py +0 -0
  51. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/engine.py +0 -0
  52. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/result.py +0 -0
  53. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/row.py +0 -0
  54. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/sequence.py +0 -0
  55. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/table.py +0 -0
  56. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/transaction.py +0 -0
  57. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/core/view.py +0 -0
  58. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/exceptions.py +0 -0
  59. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/migrations.py +0 -0
  60. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/__init__.py +0 -0
  61. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/base/__init__.py +0 -0
  62. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/base/initializer.py +0 -0
  63. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/base/operators.py +0 -0
  64. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/base/sql.py +0 -0
  65. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/base/types.py +0 -0
  66. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/mysql/__init__.py +0 -0
  67. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/mysql/operators.py +0 -0
  68. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/mysql/reserved.py +0 -0
  69. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/mysql/types.py +0 -0
  70. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/postgres/__init__.py +0 -0
  71. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/postgres/operators.py +0 -0
  72. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/postgres/reserved.py +0 -0
  73. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/postgres/sql.py +0 -0
  74. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/postgres/types.py +0 -0
  75. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlite/__init__.py +0 -0
  76. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlite/operators.py +0 -0
  77. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlite/reserved.py +0 -0
  78. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlite/types.py +0 -0
  79. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
  80. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlserver/operators.py +0 -0
  81. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
  82. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/sqlserver/types.py +0 -0
  83. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/servers/tablehelper.py +0 -0
  84. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/__init__.py +0 -0
  85. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/common_db_test.py +0 -0
  86. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/__init__.py +0 -0
  87. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/common.py +0 -0
  88. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_column.py +0 -0
  89. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_connections.py +0 -0
  90. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_database.py +0 -0
  91. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_engine.py +0 -0
  92. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
  93. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_imports.py +0 -0
  94. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_result.py +0 -0
  95. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_row.py +0 -0
  96. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
  97. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
  98. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
  99. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
  100. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
  101. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_table.py +0 -0
  102. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
  103. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
  104. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/sql/__init__.py +0 -0
  105. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/sql/common.py +0 -0
  106. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
  107. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
  108. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
  109. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_db_utils.py +0 -0
  110. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_postgres.py +0 -0
  111. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
  112. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
  113. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_result_caching.py +0 -0
  114. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
  115. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
  116. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
  117. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
  118. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_sql_builder.py +0 -0
  119. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_tablehelper.py +0 -0
  120. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/tests/test_view_helper.py +0 -0
  121. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/db/utils.py +0 -0
  122. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/logging.py +0 -0
  123. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/__init__.py +0 -0
  124. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/conv/__init__.py +0 -0
  125. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/conv/iconv.py +0 -0
  126. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/conv/oconv.py +0 -0
  127. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/db.py +0 -0
  128. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/export.py +0 -0
  129. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/format.py +0 -0
  130. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/mail.py +0 -0
  131. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/merge.py +0 -0
  132. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/pdf.py +0 -0
  133. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/__init__.py +0 -0
  134. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/test_db.py +0 -0
  135. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/test_fix.py +0 -0
  136. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/test_format.py +0 -0
  137. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/test_iconv.py +0 -0
  138. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/test_merge.py +0 -0
  139. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/test_oconv.py +0 -0
  140. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/test_original_error.py +0 -0
  141. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tests/test_timer.py +0 -0
  142. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/timer.py +0 -0
  143. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/misc/tools.py +0 -0
  144. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity/payment/authorizenet_adapter.py +0 -0
  145. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity_python.egg-info/dependency_links.txt +0 -0
  146. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity_python.egg-info/entry_points.txt +0 -0
  147. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity_python.egg-info/requires.txt +0 -0
  148. {velocity_python-0.1.16 → velocity_python-0.1.18}/src/velocity_python.egg-info/top_level.txt +0 -0
  149. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_amplify_build.py +0 -0
  150. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_async_support.py +0 -0
  151. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_batch_operations.py +0 -0
  152. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_concurrency_safety.py +0 -0
  153. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_connection_pool.py +0 -0
  154. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_connection_resilience.py +0 -0
  155. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_decorators.py +0 -0
  156. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_email_processing.py +0 -0
  157. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_iconv_money_to_cents.py +0 -0
  158. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_lambda_handler_auth.py +0 -0
  159. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_mixins_import.py +0 -0
  160. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_n_plus_one.py +0 -0
  161. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_observability.py +0 -0
  162. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_payment_braintree_adapter.py +0 -0
  163. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_payment_profile_sorting.py +0 -0
  164. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_pdf.py +0 -0
  165. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_prepared_statements.py +0 -0
  166. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_psycopg3_upgrade.py +0 -0
  167. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_query_cache.py +0 -0
  168. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_row_batch_update.py +0 -0
  169. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_row_cache_staleness.py +0 -0
  170. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_row_dirty_tracking.py +0 -0
  171. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_schema_migrations.py +0 -0
  172. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_security_hardening.py +0 -0
  173. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_spreadsheet_functions.py +0 -0
  174. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_sqs_per_record_transactions.py +0 -0
  175. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_sys_modified_count_postgres_demo.py +0 -0
  176. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_table_alter.py +0 -0
  177. {velocity_python-0.1.16 → velocity_python-0.1.18}/tests/test_where_clause_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Velocity Team <info@codeclubs.org>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "velocity-python"
7
- version = "0.1.16"
7
+ version = "0.1.18"
8
8
  authors = [
9
9
  { name="Velocity Team", email="info@codeclubs.org" },
10
10
  ]
@@ -1,4 +1,4 @@
1
- __version__ = version = "0.1.16"
1
+ __version__ = version = "0.1.18"
2
2
 
3
3
  import importlib as _importlib
4
4
 
@@ -239,15 +239,16 @@ class BaseHandler:
239
239
  or "error"
240
240
  )
241
241
 
242
- logger.warning(
243
- "AlertError during action execution",
244
- exc_info=True,
245
- extra={
246
- "handler": self.__class__.__name__,
247
- "action": getattr(local_context, "action", lambda: None)(),
248
- "tx_present": tx is not None,
249
- },
250
- )
242
+ if getattr(exception, "log_to_cloudwatch", False):
243
+ logger.warning(
244
+ "AlertError during action execution",
245
+ exc_info=True,
246
+ extra={
247
+ "handler": self.__class__.__name__,
248
+ "action": getattr(local_context, "action", lambda: None)(),
249
+ "tx_present": tx is not None,
250
+ },
251
+ )
251
252
 
252
253
  # Default behavior: raising AlertError surfaces a UI alert.
253
254
  # If `toast: true` is present in the payload, show a toast instead.
@@ -24,7 +24,19 @@ logger = get_logger("velocity.aws.handlers.context")
24
24
  @engine.transaction
25
25
  class Context:
26
26
 
27
- def __init__(self, aws_event, aws_context, args, postdata, response, session):
27
+ JOB_ACTIVITY_TABLE = "aws_job_activity"
28
+ USER_DATA_TABLE = "user_data"
29
+
30
+ def __init__(
31
+ self,
32
+ aws_event,
33
+ aws_context,
34
+ args,
35
+ postdata,
36
+ response,
37
+ session,
38
+ feature_flag_loader=None,
39
+ ):
28
40
  self.__args = args
29
41
  self.__postdata = postdata
30
42
  self.__response = response
@@ -37,6 +49,7 @@ class Context:
37
49
  self._job_record_cache = {}
38
50
  self._job_cancelled_flag = False
39
51
  self._feature_flags_cache = None
52
+ self._feature_flag_loader = feature_flag_loader
40
53
 
41
54
  def postdata(self, keys=-1, default=None):
42
55
  if keys == -1:
@@ -173,7 +186,7 @@ class Context:
173
186
  # Sanitize data before storing in database
174
187
  sanitized_data = self._sanitize_job_data(data)
175
188
  job_id = self.postdata("job_id")
176
- tx.table("aws_job_activity").update(sanitized_data, {"job_id": job_id})
189
+ tx.table(self.JOB_ACTIVITY_TABLE).update(sanitized_data, {"job_id": job_id})
177
190
  self._job_record_cache.pop(job_id, None)
178
191
  tx.commit()
179
192
 
@@ -182,7 +195,7 @@ class Context:
182
195
  if not job_data:
183
196
  return
184
197
  sanitized_data = self._sanitize_job_data(job_data)
185
- tx.table("aws_job_activity").insert(sanitized_data)
198
+ tx.table(self.JOB_ACTIVITY_TABLE).insert(sanitized_data)
186
199
  job_id = sanitized_data.get("job_id")
187
200
  if job_id:
188
201
  self._job_record_cache.pop(job_id, None)
@@ -277,7 +290,7 @@ class Context:
277
290
  return None
278
291
 
279
292
  if refresh or job_id not in self._job_record_cache:
280
- record = tx.table("aws_job_activity").find({"job_id": job_id})
293
+ record = tx.table(self.JOB_ACTIVITY_TABLE).find({"job_id": job_id})
281
294
  if record is not None:
282
295
  self._job_record_cache[job_id] = record
283
296
  elif job_id in self._job_record_cache:
@@ -330,7 +343,7 @@ class Context:
330
343
  }
331
344
  )
332
345
 
333
- tx.table("aws_job_activity").update(
346
+ tx.table(self.JOB_ACTIVITY_TABLE).update(
334
347
  {
335
348
  "status": "Cancelled",
336
349
  "message": to_json(message),
@@ -474,14 +487,17 @@ class Context:
474
487
  return result
475
488
 
476
489
  def _load_feature_flags(self, tx):
477
- """Load feature flag values from the shared helpers module."""
490
+ """Load feature flags via injected loader with optional support fallback."""
491
+ if callable(self._feature_flag_loader):
492
+ return self._feature_flag_loader(tx)
493
+
478
494
  try:
479
495
  from support.app import helpers
480
- except ImportError as exc:
481
- raise RuntimeError(
482
- "support.app.helpers is required for feature flag lookups"
483
- ) from exc
484
- return helpers.get_feature_flags(tx)
496
+
497
+ return helpers.get_feature_flags(tx)
498
+ except ImportError:
499
+ # Keep velocity generic when support is not installed.
500
+ return {}
485
501
 
486
502
  def _get_feature_flag_cache(self, tx):
487
503
  """Return cached feature flags, loading them once per request."""
@@ -514,7 +530,9 @@ class Context:
514
530
 
515
531
  def merge_user_data(self, tx, base_data, email_address):
516
532
  """Merge stored user settings from the user_data table into base_data."""
517
- data = tx.table("user_data").select(["key", "val"], {"userid": email_address})
533
+ data = tx.table(self.USER_DATA_TABLE).select(
534
+ ["key", "val"], {"userid": email_address}
535
+ )
518
536
 
519
537
  for row in data:
520
538
  base_data = deep_merge(base_data, json.loads(row["val"]), update=True)
@@ -760,5 +778,5 @@ def tracking_table_name_for_email(email):
760
778
  normalized = email.strip().lower()
761
779
  if not normalized:
762
780
  return None
763
- table = f"CC_{hashlib.md5(normalized.encode('utf-8')).hexdigest()}".lower()
781
+ table = f"VP_{hashlib.md5(normalized.encode('utf-8')).hexdigest()}".lower()
764
782
  return f"user_tracking.{table}"
@@ -14,6 +14,7 @@ class AlertError(AppError):
14
14
  title: str | None = None,
15
15
  toast: bool = False,
16
16
  variant: str | None = None,
17
+ log_to_cloudwatch: bool = False,
17
18
  **payload,
18
19
  ):
19
20
  # Backwards compatible:
@@ -24,13 +25,16 @@ class AlertError(AppError):
24
25
  and title is None
25
26
  and toast is False
26
27
  and variant is None
28
+ and log_to_cloudwatch is False
27
29
  and not payload
28
30
  ):
29
31
  super().__init__(message)
32
+ self.log_to_cloudwatch = log_to_cloudwatch
30
33
  return
31
34
 
32
- if isinstance(message, dict) and title is None and toast is False and variant is None and not payload:
35
+ if isinstance(message, dict) and title is None and toast is False and variant is None and log_to_cloudwatch is False and not payload:
33
36
  super().__init__(message)
37
+ self.log_to_cloudwatch = log_to_cloudwatch
34
38
  return
35
39
 
36
40
  data: dict = {}
@@ -49,6 +53,7 @@ class AlertError(AppError):
49
53
  data.update(payload)
50
54
 
51
55
  super().__init__(data)
56
+ self.log_to_cloudwatch = log_to_cloudwatch
52
57
 
53
58
  def get_payload(self):
54
59
  data = self.args[0]
@@ -154,10 +154,10 @@ class LambdaHandler(BaseHandler):
154
154
  extra={"request_id": request_id},
155
155
  )
156
156
 
157
- logger.debug("starting BackOfficeEvents.onError")
157
+ logger.debug("starting handler.onError")
158
158
 
159
159
  temp = copy.deepcopy(context.postdata() or {})
160
- logger.debug("starting BackOfficeEvents.log")
160
+ logger.debug("starting handler.log")
161
161
  payload = temp.get("payload")
162
162
  if isinstance(payload, dict):
163
163
  payload.pop("cognito_user", None)
@@ -166,7 +166,7 @@ class LambdaHandler(BaseHandler):
166
166
  temp.get("action"),
167
167
  extra={"payload": pprint.pformat(temp), "traceback": tb},
168
168
  )
169
- logger.debug("Ending BackOfficeEvents.OnError Done")
169
+ logger.debug("ending handler.onError done")
170
170
 
171
171
  def serve(self, tx):
172
172
  response = Response()
@@ -31,6 +31,10 @@ class WebHandler(ABC):
31
31
  helpers spread across other classes.
32
32
  """
33
33
 
34
+ API_ACTIVITY_TABLE = "aws_api_activity"
35
+ SYSTEM_LOG_TABLE = "sys_log"
36
+ LAMBDA_METRICS_TABLE = "lambda_metrics"
37
+
34
38
  def __init__(self, *args, **kwargs):
35
39
  super().__init__(*args, **kwargs)
36
40
  self.start_time = None
@@ -91,7 +95,7 @@ class WebHandler(ABC):
91
95
  try:
92
96
  perf.start("aws_api_activity insert")
93
97
  self.activity_log_key = (
94
- tx.table("aws_api_activity").new(self.activity_data).pk
98
+ tx.table(self.API_ACTIVITY_TABLE).new(self.activity_data).pk
95
99
  )
96
100
  perf.log(
97
101
  "aws_api_activity insert",
@@ -126,7 +130,7 @@ class WebHandler(ABC):
126
130
  "status": "success",
127
131
  }
128
132
 
129
- tx.table("aws_api_activity").update(update_data, self.activity_log_key)
133
+ tx.table(self.API_ACTIVITY_TABLE).update(update_data, self.activity_log_key)
130
134
 
131
135
  def track_activity_error(self, tx, context, exception, tb_string):
132
136
  """Update activity record to reflect an error"""
@@ -144,7 +148,7 @@ class WebHandler(ABC):
144
148
  }
145
149
  update_data["exception"] = exception.__class__.__name__
146
150
 
147
- tx.table("aws_api_activity").update(update_data, self.activity_log_key)
151
+ tx.table(self.API_ACTIVITY_TABLE).update(update_data, self.activity_log_key)
148
152
 
149
153
  def _sanitize_postdata(self, postdata: Dict) -> str:
150
154
  """Remove sensitive information from postdata before logging"""
@@ -257,12 +261,15 @@ class WebHandler(ABC):
257
261
  except Exception: # pragma: no cover - best effort
258
262
  pass
259
263
 
260
- tx.table("sys_log").insert(error_data)
264
+ tx.table(self.SYSTEM_LOG_TABLE).insert(error_data)
261
265
 
262
266
  def send_error_notification(self, tx, context, exc: str, tb_string: str):
263
267
  """Send error notification email to administrators"""
264
268
  try:
265
- from support.app import helpers
269
+ sendmail = self._get_sendmail_callable()
270
+ if sendmail is None:
271
+ logger.debug("No sendmail callable configured; skipping notification.")
272
+ return
266
273
 
267
274
  environment = os.environ.get("USER_BRANCH", "Unknown").title()
268
275
  function_name = os.environ.get("AWS_LAMBDA_FUNCTION_NAME", "Unknown")
@@ -307,7 +314,7 @@ Request Details:
307
314
 
308
315
  sender = self._resolve_error_notification_sender(tx, context)
309
316
 
310
- helpers.sendmail(
317
+ sendmail(
311
318
  tx,
312
319
  subject=subject,
313
320
  body=body,
@@ -384,6 +391,15 @@ Request Details:
384
391
  """Default sender address (disabled unless overridden)"""
385
392
  return ""
386
393
 
394
+ def _get_sendmail_callable(self):
395
+ """Resolve notification sender callable without hard dependency."""
396
+ try:
397
+ from support.app import helpers
398
+
399
+ return getattr(helpers, "sendmail", None)
400
+ except ImportError:
401
+ return None
402
+
387
403
  def _get_error_context(self, context) -> str:
388
404
  """Sanitize request context for reporting"""
389
405
  try:
@@ -409,7 +425,7 @@ Request Details:
409
425
  "sys_modified_by": "Lambda",
410
426
  }
411
427
  try:
412
- tx.table("lambda_metrics").insert(metrics_data)
428
+ tx.table(self.LAMBDA_METRICS_TABLE).insert(metrics_data)
413
429
  except Exception: # pragma: no cover - optional table
414
430
  pass
415
431
  except Exception: # pragma: no cover - best effort
@@ -435,7 +435,7 @@ class SQL(BaseSQLDialect):
435
435
  table_identifier = quote(name)
436
436
  base_name = name.split(".")[-1].replace("`", "")
437
437
  base_name_sql = base_name.replace("'", "''")
438
- trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"cc_sysmod_{base_name}")
438
+ trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"vp_sysmod_{base_name}")
439
439
 
440
440
  statements = []
441
441
  if drop:
@@ -518,7 +518,7 @@ END;
518
518
  table_identifier = quote(name)
519
519
  base_name = name.split(".")[-1].replace("`", "")
520
520
  base_name_sql = base_name.replace("'", "''")
521
- trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"cc_sysmod_{base_name}")
521
+ trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"vp_sysmod_{base_name}")
522
522
 
523
523
  has_count = "sys_modified_count" in existing_columns
524
524
 
@@ -388,7 +388,7 @@ class SQL(BaseSQLDialect):
388
388
  table_identifier = quote(name)
389
389
  base_name = name.split(".")[-1].replace('"', "")
390
390
  base_name_sql = base_name.replace("'", "''")
391
- trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"cc_sysmod_{base_name}")
391
+ trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"vp_sysmod_{base_name}")
392
392
 
393
393
  statements = []
394
394
  if drop:
@@ -469,7 +469,7 @@ END;
469
469
  table_identifier = quote(name)
470
470
  base_name = name.split(".")[-1].replace('"', "")
471
471
  base_name_sql = base_name.replace("'", "''")
472
- trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"cc_sysmod_{base_name}")
472
+ trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"vp_sysmod_{base_name}")
473
473
 
474
474
  has_count = "sys_modified_count" in existing_columns
475
475
 
@@ -463,7 +463,7 @@ class SQL(BaseSQLDialect):
463
463
  table_identifier = quote(name if "." in name else f"{schema_part}.{table_part}")
464
464
  base_name = table_part.replace("[", "").replace("]", "")
465
465
  base_name_sql = base_name.replace("'", "''")
466
- trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"CC_SYS_MOD_{base_name}")
466
+ trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"VP_SYSMOD_{base_name}")
467
467
 
468
468
  statements = []
469
469
  if drop:
@@ -560,7 +560,7 @@ END;
560
560
  table_identifier = quote(name if "." in name else f"{schema}.{table_name}")
561
561
  object_name = f"[{schema}].[{table_name}]"
562
562
  table_name_sql = table_name.replace("'", "''")
563
- trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"CC_SYS_MOD_{table_name}")
563
+ trigger_prefix = re.sub(r"[^0-9A-Za-z_]+", "_", f"VP_SYSMOD_{table_name}")
564
564
 
565
565
  has_count = "sys_modified_count" in existing_columns
566
566
 
@@ -0,0 +1,36 @@
1
+ """Generic payment adapters and shared charge rules for velocity-python.
2
+
3
+ Application-specific routing/profile logic lives outside velocity (e.g. in
4
+ support.app.payment).
5
+ """
6
+
7
+ from .base_adapter import PaymentProcessorAdapter, ProcessorError
8
+ from .stripe_adapter import StripeAdapter
9
+ from .braintree_adapter import BraintreeAdapter
10
+
11
+ try:
12
+ from .authorizenet_adapter import AuthorizeNetAdapter
13
+ except ImportError:
14
+ AuthorizeNetAdapter = None
15
+
16
+ from .charge_rules import (
17
+ should_charge_immediately,
18
+ is_below_immediate_charge_minimum,
19
+ is_above_immediate_charge_maximum,
20
+ )
21
+
22
+ __all__ = [
23
+ # Base classes
24
+ "PaymentProcessorAdapter",
25
+ "ProcessorError",
26
+ # Adapters
27
+ "StripeAdapter",
28
+ "BraintreeAdapter",
29
+ "AuthorizeNetAdapter",
30
+ # Generic shared helpers
31
+ "should_charge_immediately",
32
+ "is_below_immediate_charge_minimum",
33
+ "is_above_immediate_charge_maximum",
34
+ ]
35
+
36
+ __version__ = "1.0.0"
@@ -133,8 +133,8 @@ class PaymentProcessorAdapter(ABC):
133
133
  - processor_account_id: External account identifier
134
134
  - revenue_split_percentage: Platform fee percentage (e.g., 15.00)
135
135
  - metadata: Additional transaction metadata
136
- - donor_email: Donor email address
137
- - donor_name: Donor full name
136
+ - customer_email: Customer email address
137
+ - customer_name: Customer full name
138
138
  - form_sys_id: Related form identifier (optional)
139
139
 
140
140
  Returns:
@@ -174,8 +174,8 @@ class PaymentProcessorAdapter(ABC):
174
174
  - processor_account_id: External account identifier (optional)
175
175
  - revenue_split_percentage: Platform fee percentage (optional)
176
176
  - metadata: Additional transaction metadata
177
- - donor_email: Donor email address
178
- - donor_name: Donor full name
177
+ - customer_email: Customer email address
178
+ - customer_name: Customer full name
179
179
  - description: Transaction description (optional)
180
180
  - descriptor: Processor descriptor object (optional)
181
181
 
@@ -8,7 +8,7 @@ the processor-agnostic payment flow. Braintree was the original processor and
8
8
  remains available for legacy clients.
9
9
 
10
10
  Key Features:
11
- - Platform-centric model (all payments to CaringCent account)
11
+ - Platform-centric model (all payments to a platform account)
12
12
  - Manual settlement to clients (not instant split like Stripe)
13
13
  - Sub-merchant accounts (if configured)
14
14
  - Authorization with later capture support
@@ -25,7 +25,7 @@ class BraintreeAdapter(PaymentProcessorAdapter):
25
25
  Braintree adapter for payment processing.
26
26
 
27
27
  Uses Braintree sub-merchant accounts with manual settlement.
28
- All payments go to CaringCent platform account first.
28
+ All payments go to a platform account first.
29
29
  """
30
30
 
31
31
  def __init__(self, config: Dict[str, Any]):
@@ -59,6 +59,7 @@ class BraintreeAdapter(PaymentProcessorAdapter):
59
59
  )
60
60
 
61
61
  self.environment = environment_name
62
+ self.platform = config.get("platform")
62
63
 
63
64
  # ========================================================================
64
65
  # ACCOUNT MANAGEMENT
@@ -287,26 +288,34 @@ class BraintreeAdapter(PaymentProcessorAdapter):
287
288
  "custom_fields": {
288
289
  "client_id": str(payment_data.get("client_id")),
289
290
  "form_sys_id": str(payment_data.get("form_sys_id", "")),
290
- "platform": "caringcent",
291
291
  },
292
292
  }
293
293
 
294
+ if self.platform:
295
+ transaction_params["custom_fields"]["platform"] = str(self.platform)
296
+
294
297
  # Add sub-merchant account if configured
295
298
  if processor_account_id:
296
299
  transaction_params["merchant_account_id"] = processor_account_id
297
300
 
298
301
  # Add customer details
299
- if payment_data.get("donor_email"):
302
+ customer_email = payment_data.get("customer_email") or payment_data.get(
303
+ "donor_email"
304
+ )
305
+ customer_name = payment_data.get("customer_name") or payment_data.get(
306
+ "donor_name"
307
+ )
308
+ if customer_email:
300
309
  transaction_params["customer"] = {
301
- "email": payment_data["donor_email"],
310
+ "email": customer_email,
302
311
  "first_name": (
303
- payment_data.get("donor_name", "").split()[0]
304
- if payment_data.get("donor_name")
312
+ customer_name.split()[0]
313
+ if customer_name
305
314
  else None
306
315
  ),
307
316
  "last_name": (
308
- " ".join(payment_data.get("donor_name", "").split()[1:])
309
- if payment_data.get("donor_name")
317
+ " ".join(customer_name.split()[1:])
318
+ if customer_name
310
319
  else None
311
320
  ),
312
321
  }
@@ -16,24 +16,24 @@ def should_charge_immediately(total_charge_amount: Any) -> bool:
16
16
 
17
17
 
18
18
  def is_below_immediate_charge_minimum(
19
- total_charge_amount: Any, minimum_donation_amount: Any
19
+ total_charge_amount: Any, minimum_charge_amount: Any
20
20
  ) -> bool:
21
21
  """Return True only when an actual immediate charge exists and is below the minimum."""
22
22
  if not should_charge_immediately(total_charge_amount):
23
23
  return False
24
24
  try:
25
- return float(total_charge_amount) < float(minimum_donation_amount)
25
+ return float(total_charge_amount) < float(minimum_charge_amount)
26
26
  except (TypeError, ValueError):
27
27
  return False
28
28
 
29
29
 
30
30
  def is_above_immediate_charge_maximum(
31
- total_charge_amount: Any, maximum_donation_amount: Any
31
+ total_charge_amount: Any, maximum_charge_amount: Any
32
32
  ) -> bool:
33
33
  """Return True only when an actual immediate charge exists and is above the maximum."""
34
34
  if not should_charge_immediately(total_charge_amount):
35
35
  return False
36
36
  try:
37
- return float(total_charge_amount) > float(maximum_donation_amount)
37
+ return float(total_charge_amount) > float(maximum_charge_amount)
38
38
  except (TypeError, ValueError):
39
39
  return False
@@ -45,6 +45,7 @@ class StripeAdapter(PaymentProcessorAdapter):
45
45
  self.publishable_key = config.get("publishable_key")
46
46
  self.webhook_secret = config.get("webhook_secret")
47
47
  self.environment = config.get("environment", "test")
48
+ self.platform = config.get("platform")
48
49
 
49
50
  # ========================================================================
50
51
  # ACCOUNT MANAGEMENT
@@ -80,14 +81,17 @@ class StripeAdapter(PaymentProcessorAdapter):
80
81
  if part
81
82
  ).strip()
82
83
 
84
+ customer_metadata = {
85
+ "email_address": email_address,
86
+ **(customer_data.get("metadata") or {}),
87
+ }
88
+ if self.platform:
89
+ customer_metadata["platform"] = str(self.platform)
90
+
83
91
  customer = stripe.Customer.create(
84
92
  email=email_address,
85
93
  name=full_name or email_address,
86
- metadata={
87
- "platform": "caringcent",
88
- "email_address": email_address,
89
- **(customer_data.get("metadata") or {}),
90
- },
94
+ metadata=customer_metadata,
91
95
  api_key=self._api_key,
92
96
  )
93
97
  return {
@@ -210,6 +214,13 @@ class StripeAdapter(PaymentProcessorAdapter):
210
214
  email = client_data["email"]
211
215
 
212
216
  # Create Express account
217
+ account_metadata = {
218
+ "client_id": str(client_id),
219
+ "environment": self.environment,
220
+ }
221
+ if self.platform:
222
+ account_metadata["platform"] = str(self.platform)
223
+
213
224
  account = stripe.Account.create(
214
225
  type="express", # Express account type
215
226
  country="US",
@@ -226,11 +237,7 @@ class StripeAdapter(PaymentProcessorAdapter):
226
237
  "mcc": "8299", # Schools and Educational Services
227
238
  "url": client_data.get("website_url"),
228
239
  },
229
- metadata={
230
- "client_id": str(client_id),
231
- "platform": "caringcent",
232
- "environment": self.environment,
233
- },
240
+ metadata=account_metadata,
234
241
  api_key=self._api_key,
235
242
  )
236
243
 
@@ -401,6 +408,18 @@ class StripeAdapter(PaymentProcessorAdapter):
401
408
  )
402
409
 
403
410
  # Create PaymentIntent
411
+ payment_metadata = {
412
+ "client_id": str(payment_data.get("client_id")),
413
+ "form_sys_id": str(payment_data.get("form_sys_id", "")),
414
+ "customer_email": payment_data.get("customer_email")
415
+ or payment_data.get("donor_email"),
416
+ "customer_name": payment_data.get("customer_name")
417
+ or payment_data.get("donor_name"),
418
+ "environment": self.environment,
419
+ }
420
+ if self.platform:
421
+ payment_metadata["platform"] = str(self.platform)
422
+
404
423
  payment_intent = stripe.PaymentIntent.create(
405
424
  amount=amount_cents,
406
425
  currency=currency,
@@ -412,14 +431,7 @@ class StripeAdapter(PaymentProcessorAdapter):
412
431
  transfer_data={
413
432
  "destination": processor_account_id, # Client's account
414
433
  },
415
- metadata={
416
- "client_id": str(payment_data.get("client_id")),
417
- "form_sys_id": str(payment_data.get("form_sys_id", "")),
418
- "donor_email": payment_data.get("donor_email"),
419
- "donor_name": payment_data.get("donor_name"),
420
- "platform": "caringcent",
421
- "environment": self.environment,
422
- },
434
+ metadata=payment_metadata,
423
435
  api_key=self._api_key,
424
436
  )
425
437
 
@@ -489,6 +501,18 @@ class StripeAdapter(PaymentProcessorAdapter):
489
501
  amount_cents, revenue_split_percentage
490
502
  )
491
503
 
504
+ payment_metadata = {
505
+ "client_id": str(payment_data.get("client_id")),
506
+ "customer_email": payment_data.get("customer_email")
507
+ or payment_data.get("donor_email"),
508
+ "customer_name": payment_data.get("customer_name")
509
+ or payment_data.get("donor_name"),
510
+ "environment": self.environment,
511
+ **(payment_data.get("metadata") or {}),
512
+ }
513
+ if self.platform:
514
+ payment_metadata["platform"] = str(self.platform)
515
+
492
516
  payment_intent = stripe.PaymentIntent.create(
493
517
  amount=amount_cents,
494
518
  currency=currency,
@@ -499,14 +523,7 @@ class StripeAdapter(PaymentProcessorAdapter):
499
523
  application_fee_amount=platform_fee_cents,
500
524
  transfer_data={"destination": processor_account_id},
501
525
  description=payment_data.get("description"),
502
- metadata={
503
- "client_id": str(payment_data.get("client_id")),
504
- "donor_email": payment_data.get("donor_email"),
505
- "donor_name": payment_data.get("donor_name"),
506
- "platform": "caringcent",
507
- "environment": self.environment,
508
- **(payment_data.get("metadata") or {}),
509
- },
526
+ metadata=payment_metadata,
510
527
  api_key=self._api_key,
511
528
  )
512
529
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Velocity Team <info@codeclubs.org>
6
6
  License-Expression: MIT