lambda-erp 0.1.48__tar.gz → 0.1.49__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 (71) hide show
  1. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/PKG-INFO +1 -1
  2. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/auth.py +12 -12
  3. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/database.py +3 -3
  4. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/pyproject.toml +1 -1
  5. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/.gitignore +0 -0
  6. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/LICENSE +0 -0
  7. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/README.md +0 -0
  8. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/__init__.py +0 -0
  9. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/attachments.py +0 -0
  10. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/bootstrap.py +0 -0
  11. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/chat.py +0 -0
  12. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/demo_limits.py +0 -0
  13. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/deps.py +0 -0
  14. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/errors.py +0 -0
  15. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/main.py +0 -0
  16. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/oauth.py +0 -0
  17. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/pdf.py +0 -0
  18. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/providers.py +0 -0
  19. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/remarks_md.py +0 -0
  20. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/__init__.py +0 -0
  21. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/accounting.py +0 -0
  22. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/admin.py +0 -0
  23. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/analytics.py +0 -0
  24. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/bank_reconciliation.py +0 -0
  25. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/chat_api.py +0 -0
  26. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/documents.py +0 -0
  27. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/masters.py +0 -0
  28. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/proposals.py +0 -0
  29. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/reports.py +0 -0
  30. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/routers/setup.py +0 -0
  31. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/services.py +0 -0
  32. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/templates/document.html +0 -0
  33. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/api/templates/proposal.html +0 -0
  34. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/docs/agents/README.md +0 -0
  35. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/frontend/README.md +0 -0
  36. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/frontend/src/api/client.ts +0 -0
  37. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/__init__.py +0 -0
  38. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/__init__.py +0 -0
  39. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/bank_transaction.py +0 -0
  40. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/budget.py +0 -0
  41. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/chart_of_accounts.py +0 -0
  42. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/general_ledger.py +0 -0
  43. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/journal_entry.py +0 -0
  44. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/payment_entry.py +0 -0
  45. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/pos_invoice.py +0 -0
  46. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/purchase_invoice.py +0 -0
  47. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/revaluation.py +0 -0
  48. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/sales_invoice.py +0 -0
  49. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/accounting/subscription.py +0 -0
  50. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/buying/__init__.py +0 -0
  51. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/buying/purchase_order.py +0 -0
  52. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/controllers/__init__.py +0 -0
  53. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/controllers/currency.py +0 -0
  54. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/controllers/defaults.py +0 -0
  55. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/controllers/pricing_rule.py +0 -0
  56. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/controllers/taxes_and_totals.py +0 -0
  57. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/exceptions.py +0 -0
  58. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/hooks.py +0 -0
  59. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/model.py +0 -0
  60. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/selling/__init__.py +0 -0
  61. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/selling/proposal.py +0 -0
  62. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/selling/quotation.py +0 -0
  63. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/selling/sales_order.py +0 -0
  64. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/simulation.py +0 -0
  65. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/stock/__init__.py +0 -0
  66. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/stock/delivery_note.py +0 -0
  67. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/stock/purchase_receipt.py +0 -0
  68. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/stock/stock_entry.py +0 -0
  69. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/stock/stock_ledger.py +0 -0
  70. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/lambda_erp/utils.py +0 -0
  71. {lambda_erp-0.1.48 → lambda_erp-0.1.49}/terraform/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lambda-erp
3
- Version: 0.1.48
3
+ Version: 0.1.49
4
4
  Summary: Core ERP logic - accounting, sales, purchasing, inventory
5
5
  Author: TORUS INVESTMENTS AG
6
6
  License-Expression: MIT
@@ -680,14 +680,14 @@ def get_api_caller(request: Request) -> dict:
680
680
  raise HTTPException(status_code=401, detail="Empty bearer token")
681
681
 
682
682
  rows = db.sql(
683
- 'SELECT id, name, user, role, session_owner FROM "Api Key" WHERE key_hash = ? AND revoked = 0',
683
+ 'SELECT id, name, owner, role, session_owner FROM "Api Key" WHERE key_hash = ? AND revoked = 0',
684
684
  [hash_api_key(token)],
685
685
  )
686
686
  if not rows:
687
687
  raise HTTPException(status_code=401, detail="Invalid API key")
688
688
  key = dict(rows[0])
689
689
 
690
- owner = db.get_value("User", key["user"], ["name", "full_name", "role", "enabled"])
690
+ owner = db.get_value("User", key["owner"], ["name", "full_name", "role", "enabled"])
691
691
  if not owner or not owner.get("enabled"):
692
692
  raise HTTPException(status_code=401, detail="Invalid API key")
693
693
  effective_role = (
@@ -699,10 +699,10 @@ def get_api_caller(request: Request) -> dict:
699
699
 
700
700
  return {
701
701
  "name": key["session_owner"],
702
- "full_name": f"{owner.get('full_name') or key['user']} (API)",
702
+ "full_name": f"{owner.get('full_name') or key['owner']} (API)",
703
703
  "role": effective_role,
704
704
  "api_key_id": key["id"],
705
- "api_key_user": key["user"],
705
+ "api_key_user": key["owner"],
706
706
  }
707
707
 
708
708
 
@@ -717,7 +717,7 @@ def _serialize_api_key(row: dict) -> dict:
717
717
  return {
718
718
  "id": row["id"],
719
719
  "name": row["name"],
720
- "user": row.get("user"),
720
+ "user": row.get("owner"),
721
721
  "role": row["role"],
722
722
  "key_prefix": row["key_prefix"],
723
723
  "created_at": row.get("created_at"),
@@ -727,7 +727,7 @@ def _serialize_api_key(row: dict) -> dict:
727
727
 
728
728
 
729
729
  def _get_key_or_404(db, key_id: str) -> dict:
730
- rows = db.sql('SELECT id, user, revoked FROM "Api Key" WHERE id = ?', [key_id])
730
+ rows = db.sql('SELECT id, owner, revoked FROM "Api Key" WHERE id = ?', [key_id])
731
731
  if not rows:
732
732
  raise HTTPException(status_code=404, detail="API key not found")
733
733
  return dict(rows[0])
@@ -735,7 +735,7 @@ def _get_key_or_404(db, key_id: str) -> dict:
735
735
 
736
736
  def _require_key_access(key: dict, user: dict) -> None:
737
737
  """A key is managed by its owner; admins can manage every key."""
738
- if key["user"] != user["name"] and user["role"] != "admin":
738
+ if key["owner"] != user["name"] and user["role"] != "admin":
739
739
  raise HTTPException(status_code=403, detail="Not your API key")
740
740
 
741
741
 
@@ -748,13 +748,13 @@ def list_api_keys(user: dict = Depends(require_viewer)):
748
748
  db = get_db()
749
749
  if user["role"] == "admin":
750
750
  rows = db.sql(
751
- 'SELECT id, name, user, role, key_prefix, created_at, last_used_at, revoked '
751
+ 'SELECT id, name, owner, role, key_prefix, created_at, last_used_at, revoked '
752
752
  'FROM "Api Key" ORDER BY created_at DESC'
753
753
  )
754
754
  else:
755
755
  rows = db.sql(
756
- 'SELECT id, name, user, role, key_prefix, created_at, last_used_at, revoked '
757
- 'FROM "Api Key" WHERE user = ? ORDER BY created_at DESC',
756
+ 'SELECT id, name, owner, role, key_prefix, created_at, last_used_at, revoked '
757
+ 'FROM "Api Key" WHERE owner = ? ORDER BY created_at DESC',
758
758
  [user["name"]],
759
759
  )
760
760
  return [_serialize_api_key(dict(r)) for r in rows]
@@ -789,13 +789,13 @@ def create_api_key(data: ApiKeyCreate, user: dict = Depends(require_viewer)):
789
789
  created_at = now()
790
790
  db.sql(
791
791
  'INSERT INTO "Api Key" '
792
- '(id, name, user, key_hash, key_prefix, role, session_owner, created_at, last_used_at, revoked) '
792
+ '(id, name, owner, key_hash, key_prefix, role, session_owner, created_at, last_used_at, revoked) '
793
793
  'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0)',
794
794
  [key_id, name, user["name"], key_hash, key_prefix, role, f"api:{user['name']}", created_at, None],
795
795
  )
796
796
  db.conn.commit()
797
797
  row = {
798
- "id": key_id, "name": name, "user": user["name"], "role": role, "key_prefix": key_prefix,
798
+ "id": key_id, "name": name, "owner": user["name"], "role": role, "key_prefix": key_prefix,
799
799
  "created_at": created_at, "last_used_at": None, "revoked": 0,
800
800
  }
801
801
  result = _serialize_api_key(row)
@@ -1321,7 +1321,7 @@ class Database:
1321
1321
  """CREATE TABLE IF NOT EXISTS "Api Key" (
1322
1322
  id TEXT PRIMARY KEY,
1323
1323
  name TEXT,
1324
- user TEXT NOT NULL,
1324
+ owner TEXT NOT NULL,
1325
1325
  key_hash TEXT UNIQUE,
1326
1326
  key_prefix TEXT,
1327
1327
  role TEXT DEFAULT 'manager',
@@ -1907,14 +1907,14 @@ def _m019_api_keys_per_user(db: "Database") -> None:
1907
1907
  owner's live role). Existing v1 rows are DROPPED, not migrated — decided
1908
1908
  2026-07-14: no legacy rules; holders simply re-issue their keys.
1909
1909
  """
1910
- if "user" in db._get_table_columns("Api Key"):
1910
+ if "owner" in db._get_table_columns("Api Key"):
1911
1911
  return # fresh install — table already has the v2 shape
1912
1912
  db.conn.execute('DROP TABLE "Api Key"')
1913
1913
  db.conn.execute(
1914
1914
  """CREATE TABLE "Api Key" (
1915
1915
  id TEXT PRIMARY KEY,
1916
1916
  name TEXT,
1917
- user TEXT NOT NULL,
1917
+ owner TEXT NOT NULL,
1918
1918
  key_hash TEXT UNIQUE,
1919
1919
  key_prefix TEXT,
1920
1920
  role TEXT DEFAULT 'manager',
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lambda-erp"
3
- version = "0.1.48"
3
+ version = "0.1.49"
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