lambda-erp 0.8.18__tar.gz → 0.8.19__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 (89) hide show
  1. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/PKG-INFO +1 -1
  2. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/reports.py +3 -3
  3. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/journal_entry.py +36 -23
  4. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/pyproject.toml +1 -1
  5. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/.gitignore +0 -0
  6. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/LICENSE +0 -0
  7. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/README.md +0 -0
  8. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/__init__.py +0 -0
  9. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/attachments.py +0 -0
  10. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/auth.py +0 -0
  11. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/bootstrap.py +0 -0
  12. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/chat.py +0 -0
  13. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/demo_limits.py +0 -0
  14. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/deps.py +0 -0
  15. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/errors.py +0 -0
  16. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/main.py +0 -0
  17. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/oauth.py +0 -0
  18. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/pdf.py +0 -0
  19. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/providers.py +0 -0
  20. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/remarks_md.py +0 -0
  21. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/__init__.py +0 -0
  22. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/accounting.py +0 -0
  23. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/actions.py +0 -0
  24. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/admin.py +0 -0
  25. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/analytics.py +0 -0
  26. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/availability.py +0 -0
  27. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/bank_reconciliation.py +0 -0
  28. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/chat_api.py +0 -0
  29. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/documents.py +0 -0
  30. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/masters.py +0 -0
  31. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/mcp.py +0 -0
  32. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/proposals.py +0 -0
  33. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/routers/setup.py +0 -0
  34. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/services.py +0 -0
  35. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/templates/document.html +0 -0
  36. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/api/templates/proposal.html +0 -0
  37. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/docs/agents/README.md +0 -0
  38. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/frontend/LICENSE +0 -0
  39. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/frontend/README.md +0 -0
  40. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/frontend/src/api/client.ts +0 -0
  41. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/__init__.py +0 -0
  42. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/__init__.py +0 -0
  43. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/bank_transaction.py +0 -0
  44. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/budget.py +0 -0
  45. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/chart_of_accounts.py +0 -0
  46. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/general_ledger.py +0 -0
  47. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/payment_entry.py +0 -0
  48. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/pos_invoice.py +0 -0
  49. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/purchase_invoice.py +0 -0
  50. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/revaluation.py +0 -0
  51. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/sales_invoice.py +0 -0
  52. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/__init__.py +0 -0
  53. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/engine.py +0 -0
  54. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/pack.py +0 -0
  55. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/packs/__init__.py +0 -0
  56. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/packs/ch.py +0 -0
  57. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/packs/de_common.py +0 -0
  58. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/packs/de_skr03.py +0 -0
  59. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/packs/de_skr04.py +0 -0
  60. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/packs/generic.py +0 -0
  61. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/profiles.py +0 -0
  62. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/setup/spine.py +0 -0
  63. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/accounting/subscription.py +0 -0
  64. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/assets/__init__.py +0 -0
  65. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/assets/asset.py +0 -0
  66. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/assets/reservation.py +0 -0
  67. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/buying/__init__.py +0 -0
  68. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/buying/purchase_order.py +0 -0
  69. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/controllers/__init__.py +0 -0
  70. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/controllers/currency.py +0 -0
  71. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/controllers/defaults.py +0 -0
  72. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/controllers/pricing_rule.py +0 -0
  73. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/controllers/taxes_and_totals.py +0 -0
  74. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/database.py +0 -0
  75. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/exceptions.py +0 -0
  76. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/hooks.py +0 -0
  77. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/model.py +0 -0
  78. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/selling/__init__.py +0 -0
  79. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/selling/proposal.py +0 -0
  80. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/selling/quotation.py +0 -0
  81. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/selling/sales_order.py +0 -0
  82. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/simulation.py +0 -0
  83. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/stock/__init__.py +0 -0
  84. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/stock/delivery_note.py +0 -0
  85. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/stock/purchase_receipt.py +0 -0
  86. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/stock/stock_entry.py +0 -0
  87. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/stock/stock_ledger.py +0 -0
  88. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/lambda_erp/utils.py +0 -0
  89. {lambda_erp-0.8.18 → lambda_erp-0.8.19}/terraform/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: lambda-erp
3
- Version: 0.8.18
3
+ Version: 0.8.19
4
4
  Summary: Core ERP logic - accounting, sales, purchasing, inventory
5
5
  Author: TORUS INVESTMENTS AG
6
6
  License-Expression: Apache-2.0
@@ -508,14 +508,14 @@ def _profit_and_loss(db, company=None, from_date=None, to_date=None):
508
508
  "account": acc["name"],
509
509
  "account_name": acc["account_name"],
510
510
  "root_type": acc["root_type"],
511
- "amount": abs(balance),
511
+ "amount": balance,
512
512
  }
513
513
  if acc["root_type"] == "Income":
514
514
  income_rows.append(row)
515
- total_income += abs(balance)
515
+ total_income += balance
516
516
  else:
517
517
  expense_rows.append(row)
518
- total_expense += abs(balance)
518
+ total_expense += balance
519
519
 
520
520
  return {
521
521
  "income": income_rows,
@@ -76,26 +76,27 @@ class JournalEntry(Document):
76
76
  self._set_totals()
77
77
 
78
78
  def _normalize_amounts(self):
79
- """Keep each row's base debit/credit and its *_in_account_currency twin in
80
- sync. lambda-erp has no per-line exchange rate (base == account currency),
81
- so back-fill whichever side is missing. Without this, a row created with
82
- the amount ONLY in debit_in_account_currency (as the chat's create path
83
- did) leaves base debit/credit at 0 it passes the 0==0 balance check,
84
- submits "successfully", and posts NOTHING (GL is built from the base
85
- fields, and _get_gl_entries skips 0/0 rows). Idempotent."""
79
+ """Back-fill only missing base/account-currency amounts.
80
+
81
+ ``None`` or an absent field means the caller supplied only the matching
82
+ amount in the other currency. An explicit zero is meaningful: period-end
83
+ valuation entries move the base carrying value without changing the
84
+ foreign-currency quantity, so their *_in_account_currency amount must
85
+ remain zero.
86
+ """
86
87
  for row in self.get("accounts") or []:
87
- debit = flt(row.get("debit"))
88
- credit = flt(row.get("credit"))
89
- dr_ac = flt(row.get("debit_in_account_currency"))
90
- cr_ac = flt(row.get("credit_in_account_currency"))
91
- if not debit and dr_ac:
92
- row["debit"] = dr_ac
93
- if not credit and cr_ac:
94
- row["credit"] = cr_ac
95
- if not dr_ac and debit:
96
- row["debit_in_account_currency"] = debit
97
- if not cr_ac and credit:
98
- row["credit_in_account_currency"] = credit
88
+ debit = row.get("debit")
89
+ credit = row.get("credit")
90
+ dr_ac = row.get("debit_in_account_currency")
91
+ cr_ac = row.get("credit_in_account_currency")
92
+ if debit is None and dr_ac is not None:
93
+ row["debit"] = flt(dr_ac)
94
+ if credit is None and cr_ac is not None:
95
+ row["credit"] = flt(cr_ac)
96
+ if dr_ac is None and debit is not None:
97
+ row["debit_in_account_currency"] = flt(debit)
98
+ if cr_ac is None and credit is not None:
99
+ row["credit_in_account_currency"] = flt(credit)
99
100
 
100
101
  def _validate_debit_credit(self):
101
102
  """Ensure total debits == total credits.
@@ -235,21 +236,33 @@ class JournalEntry(Document):
235
236
  journal entries map 1:1 from account rows to GL entries.
236
237
  """
237
238
  gl_entries = []
239
+ db = get_db()
240
+ base_currency = db.get_value("Company", self.company, "default_currency") or "USD"
238
241
 
239
242
  for row in self.get("accounts"):
240
243
  if not (flt(row.get("debit")) or flt(row.get("credit"))):
241
244
  continue
242
245
 
246
+ debit = flt(row.get("debit"), 2)
247
+ credit = flt(row.get("credit"), 2)
248
+ dr_ac = row.get("debit_in_account_currency")
249
+ cr_ac = row.get("credit_in_account_currency")
250
+ account_currency = (
251
+ db.get_value("Account", row.get("account"), "account_currency")
252
+ or base_currency
253
+ )
254
+
243
255
  gl_entries.append(
244
256
  _dict(
245
257
  account=row.get("account"),
246
258
  party_type=row.get("party_type"),
247
259
  party=row.get("party"),
248
260
  cost_center=row.get("cost_center"),
249
- debit=flt(row.get("debit"), 2),
250
- credit=flt(row.get("credit"), 2),
251
- debit_in_account_currency=flt(row.get("debit_in_account_currency") or row.get("debit"), 2),
252
- credit_in_account_currency=flt(row.get("credit_in_account_currency") or row.get("credit"), 2),
261
+ debit=debit,
262
+ credit=credit,
263
+ debit_in_account_currency=flt(debit if dr_ac is None else dr_ac, 2),
264
+ credit_in_account_currency=flt(credit if cr_ac is None else cr_ac, 2),
265
+ account_currency=account_currency,
253
266
  against_voucher_type=row.get("reference_doctype") or row.get("reference_type"),
254
267
  against_voucher=row.get("reference_name"),
255
268
  voucher_type=self.DOCTYPE,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lambda-erp"
3
- version = "0.8.18"
3
+ version = "0.8.19"
4
4
  description = "Core ERP logic - accounting, sales, purchasing, inventory"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
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