lambda-erp 0.2.5__tar.gz → 0.2.6__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 (82) hide show
  1. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/PKG-INFO +1 -1
  2. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/main.py +27 -2
  3. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/pyproject.toml +1 -1
  4. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/.gitignore +0 -0
  5. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/LICENSE +0 -0
  6. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/README.md +0 -0
  7. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/__init__.py +0 -0
  8. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/attachments.py +0 -0
  9. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/auth.py +0 -0
  10. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/bootstrap.py +0 -0
  11. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/chat.py +0 -0
  12. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/demo_limits.py +0 -0
  13. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/deps.py +0 -0
  14. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/errors.py +0 -0
  15. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/oauth.py +0 -0
  16. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/pdf.py +0 -0
  17. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/providers.py +0 -0
  18. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/remarks_md.py +0 -0
  19. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/__init__.py +0 -0
  20. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/accounting.py +0 -0
  21. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/admin.py +0 -0
  22. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/analytics.py +0 -0
  23. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/bank_reconciliation.py +0 -0
  24. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/chat_api.py +0 -0
  25. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/documents.py +0 -0
  26. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/masters.py +0 -0
  27. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/proposals.py +0 -0
  28. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/reports.py +0 -0
  29. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/routers/setup.py +0 -0
  30. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/services.py +0 -0
  31. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/templates/document.html +0 -0
  32. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/api/templates/proposal.html +0 -0
  33. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/docs/agents/README.md +0 -0
  34. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/frontend/README.md +0 -0
  35. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/frontend/src/api/client.ts +0 -0
  36. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/__init__.py +0 -0
  37. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/__init__.py +0 -0
  38. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/bank_transaction.py +0 -0
  39. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/budget.py +0 -0
  40. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/chart_of_accounts.py +0 -0
  41. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/general_ledger.py +0 -0
  42. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/journal_entry.py +0 -0
  43. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/payment_entry.py +0 -0
  44. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/pos_invoice.py +0 -0
  45. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/purchase_invoice.py +0 -0
  46. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/revaluation.py +0 -0
  47. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/sales_invoice.py +0 -0
  48. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/__init__.py +0 -0
  49. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/engine.py +0 -0
  50. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/pack.py +0 -0
  51. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/packs/__init__.py +0 -0
  52. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/packs/ch.py +0 -0
  53. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/packs/de_common.py +0 -0
  54. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/packs/de_skr03.py +0 -0
  55. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/packs/de_skr04.py +0 -0
  56. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/packs/generic.py +0 -0
  57. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/profiles.py +0 -0
  58. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/setup/spine.py +0 -0
  59. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/accounting/subscription.py +0 -0
  60. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/buying/__init__.py +0 -0
  61. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/buying/purchase_order.py +0 -0
  62. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/controllers/__init__.py +0 -0
  63. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/controllers/currency.py +0 -0
  64. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/controllers/defaults.py +0 -0
  65. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/controllers/pricing_rule.py +0 -0
  66. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/controllers/taxes_and_totals.py +0 -0
  67. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/database.py +0 -0
  68. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/exceptions.py +0 -0
  69. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/hooks.py +0 -0
  70. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/model.py +0 -0
  71. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/selling/__init__.py +0 -0
  72. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/selling/proposal.py +0 -0
  73. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/selling/quotation.py +0 -0
  74. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/selling/sales_order.py +0 -0
  75. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/simulation.py +0 -0
  76. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/stock/__init__.py +0 -0
  77. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/stock/delivery_note.py +0 -0
  78. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/stock/purchase_receipt.py +0 -0
  79. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/stock/stock_entry.py +0 -0
  80. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/stock/stock_ledger.py +0 -0
  81. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/lambda_erp/utils.py +0 -0
  82. {lambda_erp-0.2.5 → lambda_erp-0.2.6}/terraform/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lambda-erp
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Core ERP logic - accounting, sales, purchasing, inventory
5
5
  Author: TORUS INVESTMENTS AG
6
6
  License-Expression: MIT
@@ -158,11 +158,29 @@ async def ws_chat(websocket: WebSocket):
158
158
  # semantics: real files (assets, favicon, logos) resolve as-is; anything
159
159
  # else falls through to index.html and React Router handles it
160
160
  # client-side. API and WebSocket paths keep returning their normal 404s.
161
+ class _ImmutableStaticFiles(StaticFiles):
162
+ """Serve content-hashed build assets with a long-lived immutable cache.
163
+
164
+ Vite fingerprints every file under /assets (index-<hash>.js, etc.), so the
165
+ bytes at a given URL never change — a new build emits new filenames. The
166
+ `immutable` directive lets the browser skip revalidation entirely (no 304
167
+ round-trip on reload), while index.html stays `no-cache` so a new build is
168
+ still picked up. Net effect vs. the old default: fewer requests, not more.
169
+ """
170
+
171
+ async def get_response(self, path, scope):
172
+ response = await super().get_response(path, scope)
173
+ response.headers.setdefault(
174
+ "Cache-Control", "public, max-age=31536000, immutable"
175
+ )
176
+ return response
177
+
178
+
161
179
  frontend_dist = os.path.join(os.path.dirname(__file__), "..", "frontend", "dist")
162
180
  if os.path.isdir(frontend_dist):
163
181
  assets_dir = os.path.join(frontend_dist, "assets")
164
182
  if os.path.isdir(assets_dir):
165
- app.mount("/assets", StaticFiles(directory=assets_dir), name="assets")
183
+ app.mount("/assets", _ImmutableStaticFiles(directory=assets_dir), name="assets")
166
184
 
167
185
  frontend_root = os.path.realpath(frontend_dist)
168
186
  index_html = os.path.join(frontend_root, "index.html")
@@ -183,4 +201,11 @@ if os.path.isdir(frontend_dist):
183
201
  return FileResponse(candidate)
184
202
 
185
203
  # SPA fallback — React Router takes over from here.
186
- return FileResponse(index_html)
204
+ #
205
+ # `no-cache` = always revalidate the shell before reuse (a cheap 304
206
+ # when unchanged, fresh bytes after a deploy). index.html is the only
207
+ # UNHASHED file and it points at the hashed /assets bundles, so if the
208
+ # browser heuristically caches it (which it does when no Cache-Control
209
+ # is set), a soft reload serves a stale shell referencing old asset
210
+ # URLs — the "refresh doesn't refresh, need a hard-refresh" bug.
211
+ return FileResponse(index_html, headers={"Cache-Control": "no-cache"})
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lambda-erp"
3
- version = "0.2.5"
3
+ version = "0.2.6"
4
4
  description = "Core ERP logic - accounting, sales, purchasing, inventory"
5
5
  readme = "README.md"
6
6
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes