lambda-erp 0.8.24__tar.gz → 0.8.26__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.
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/PKG-INFO +1 -1
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/bank_reconciliation.py +40 -26
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/database.py +29 -7
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/pyproject.toml +1 -1
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/.gitignore +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/LICENSE +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/README.md +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/attachments.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/auth.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/bootstrap.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/chat.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/demo_limits.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/deps.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/errors.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/list_values.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/main.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/oauth.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/pdf.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/providers.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/remarks_md.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/accounting.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/actions.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/admin.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/analytics.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/availability.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/bank_reconciliation.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/bank_statements.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/chat_api.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/documents.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/masters.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/mcp.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/proposals.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/reports.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/routers/setup.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/services.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/templates/document.html +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/api/templates/proposal.html +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/docs/agents/README.md +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/frontend/LICENSE +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/frontend/README.md +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/frontend/src/api/client.ts +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/bank_account.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/bank_statement_import.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/bank_transaction.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/budget.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/camt.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/chart_of_accounts.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/general_ledger.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/journal_entry.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/payment_entry.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/pos_invoice.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/purchase_invoice.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/revaluation.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/sales_invoice.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/engine.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/pack.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/packs/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/packs/ch.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/packs/de_common.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/packs/de_skr03.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/packs/de_skr04.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/packs/generic.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/profiles.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/setup/spine.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/accounting/subscription.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/assets/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/assets/asset.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/assets/reservation.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/buying/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/buying/purchase_order.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/controllers/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/controllers/currency.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/controllers/defaults.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/controllers/pricing_rule.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/controllers/taxes_and_totals.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/exceptions.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/hooks.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/model.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/selling/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/selling/proposal.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/selling/quotation.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/selling/sales_order.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/simulation.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/stock/__init__.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/stock/delivery_note.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/stock/purchase_receipt.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/stock/stock_entry.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/stock/stock_ledger.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/lambda_erp/utils.py +0 -0
- {lambda_erp-0.8.24 → lambda_erp-0.8.26}/terraform/README.md +0 -0
|
@@ -256,10 +256,10 @@ def _voucher_candidates(tx: dict, limit: int) -> list[dict]:
|
|
|
256
256
|
'AND gle.voucher_type IN (?, ?) '
|
|
257
257
|
'AND NOT EXISTS (SELECT 1 FROM "Bank Reconciliation" br '
|
|
258
258
|
' WHERE br.voucher_type = gle.voucher_type AND br.voucher_no = gle.voucher_no '
|
|
259
|
-
' AND br.status = ?) '
|
|
259
|
+
' AND br.status = ? AND br.bank_account = ?) '
|
|
260
260
|
'GROUP BY gle.voucher_type, gle.voucher_no '
|
|
261
261
|
'ORDER BY MIN(gle.posting_date) DESC LIMIT 500',
|
|
262
|
-
[tx["bank_account"], "Payment Entry", "Journal Entry", "Active"],
|
|
262
|
+
[tx["bank_account"], "Payment Entry", "Journal Entry", "Active", tx["bank_account"]],
|
|
263
263
|
)
|
|
264
264
|
expected = _amount(tx)
|
|
265
265
|
deposit = _is_deposit(tx)
|
|
@@ -311,6 +311,7 @@ def _new_audit(tx: dict, *, mode: str, voucher_type: str, voucher_no: str,
|
|
|
311
311
|
get_db().insert("Bank Reconciliation", {
|
|
312
312
|
"name": name,
|
|
313
313
|
"bank_transaction": tx["name"],
|
|
314
|
+
"bank_account": tx["bank_account"],
|
|
314
315
|
"mode": mode,
|
|
315
316
|
"voucher_type": voucher_type,
|
|
316
317
|
"voucher_no": voucher_no,
|
|
@@ -360,34 +361,35 @@ def reverse_generated_reconciliation(reconciliation: str | None, *, voucher_type
|
|
|
360
361
|
"Bank Reconciliation", reconciliation,
|
|
361
362
|
["name", "bank_transaction", "voucher_type", "voucher_no", "status", "reversed_by"],
|
|
362
363
|
)
|
|
364
|
+
rows = [row] if row else []
|
|
363
365
|
else:
|
|
364
|
-
|
|
366
|
+
rows = db.sql(
|
|
365
367
|
'SELECT name, bank_transaction, voucher_type, voucher_no, status, reversed_by '
|
|
366
368
|
'FROM "Bank Reconciliation" WHERE voucher_type = ? AND voucher_no = ? '
|
|
367
|
-
'AND status = ?
|
|
369
|
+
'AND status = ?',
|
|
368
370
|
[voucher_type, voucher_no, "Active"],
|
|
369
371
|
)
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
372
|
+
for row in rows:
|
|
373
|
+
if row.get("status") != "Active":
|
|
374
|
+
continue
|
|
375
|
+
if row.get("voucher_type") != voucher_type or row.get("voucher_no") != voucher_no:
|
|
376
|
+
raise ValidationError("Bank reconciliation voucher does not match the cancelled document")
|
|
377
|
+
tx = _transaction(row["bank_transaction"])
|
|
378
|
+
db.set_value("Bank Transaction", tx["name"], {
|
|
379
|
+
"reference_doctype": None,
|
|
380
|
+
"reference_name": None,
|
|
381
|
+
"allocated_amount": 0,
|
|
382
|
+
"unallocated_amount": _amount(tx),
|
|
383
|
+
"status": "Unreconciled",
|
|
384
|
+
"reconciled_by": None,
|
|
385
|
+
"reconciled_at": None,
|
|
386
|
+
"modified": now(),
|
|
387
|
+
})
|
|
388
|
+
db.set_value("Bank Reconciliation", row["name"], {
|
|
389
|
+
"status": "Reversed",
|
|
390
|
+
"reversed_by": row.get("reversed_by"),
|
|
391
|
+
"reversed_at": now(),
|
|
392
|
+
})
|
|
391
393
|
|
|
392
394
|
|
|
393
395
|
def _allocation_profile(tx: dict, allocations: list[dict]) -> tuple[tuple[str, str, str, str], list[dict]]:
|
|
@@ -586,7 +588,19 @@ def _validate_existing_voucher(tx: dict, voucher_type: str, voucher_no: str) ->
|
|
|
586
588
|
raise ValidationError(f"{voucher_type} {voucher_no} is unavailable or not submitted")
|
|
587
589
|
if document.get("company") != tx["company"]:
|
|
588
590
|
raise ValidationError("Voucher and bank transaction belong to different companies")
|
|
589
|
-
|
|
591
|
+
db = get_db()
|
|
592
|
+
used = db.sql(
|
|
593
|
+
'SELECT bank_transaction FROM "Bank Reconciliation" '
|
|
594
|
+
'WHERE voucher_type = ? AND voucher_no = ? AND bank_account = ? '
|
|
595
|
+
'AND status = ? LIMIT 1',
|
|
596
|
+
[voucher_type, voucher_no, tx["bank_account"], "Active"],
|
|
597
|
+
)
|
|
598
|
+
if used:
|
|
599
|
+
raise ValidationError(
|
|
600
|
+
f"The {voucher_type} {voucher_no} bank movement on account "
|
|
601
|
+
f"{tx['bank_account']} is already reconciled with {used[0]['bank_transaction']}"
|
|
602
|
+
)
|
|
603
|
+
rows = db.sql(
|
|
590
604
|
'SELECT COALESCE(SUM(debit), 0) AS debit, COALESCE(SUM(credit), 0) AS credit, '
|
|
591
605
|
'COALESCE(SUM(debit_in_account_currency), 0) AS debit_ccy, '
|
|
592
606
|
'COALESCE(SUM(credit_in_account_currency), 0) AS credit_ccy '
|
|
@@ -1423,12 +1423,14 @@ class Database:
|
|
|
1423
1423
|
"""CREATE INDEX IF NOT EXISTS "ix_bank_transaction_detail_parent"
|
|
1424
1424
|
ON "Bank Transaction Detail" (parent, idx)""",
|
|
1425
1425
|
|
|
1426
|
-
#
|
|
1427
|
-
#
|
|
1428
|
-
# reversed rows remain
|
|
1426
|
+
# Audit trail for bank reconciliation decisions. A transaction can
|
|
1427
|
+
# have only one active reconciliation. A multi-bank Journal Entry
|
|
1428
|
+
# may be linked once per bank account; reversed rows remain for
|
|
1429
|
+
# review.
|
|
1429
1430
|
"""CREATE TABLE IF NOT EXISTS "Bank Reconciliation" (
|
|
1430
1431
|
name TEXT PRIMARY KEY,
|
|
1431
1432
|
bank_transaction TEXT NOT NULL,
|
|
1433
|
+
bank_account TEXT NOT NULL,
|
|
1432
1434
|
mode TEXT NOT NULL,
|
|
1433
1435
|
voucher_type TEXT NOT NULL,
|
|
1434
1436
|
voucher_no TEXT NOT NULL,
|
|
@@ -1438,15 +1440,13 @@ class Database:
|
|
|
1438
1440
|
created_at TEXT,
|
|
1439
1441
|
reversed_by TEXT,
|
|
1440
1442
|
reversed_at TEXT,
|
|
1441
|
-
FOREIGN KEY (bank_transaction) REFERENCES "Bank Transaction"(name)
|
|
1443
|
+
FOREIGN KEY (bank_transaction) REFERENCES "Bank Transaction"(name),
|
|
1444
|
+
FOREIGN KEY (bank_account) REFERENCES "Account"(name)
|
|
1442
1445
|
)""",
|
|
1443
1446
|
|
|
1444
1447
|
"""CREATE UNIQUE INDEX IF NOT EXISTS "ux_bank_reconciliation_active_transaction"
|
|
1445
1448
|
ON "Bank Reconciliation" (bank_transaction) WHERE status = 'Active'""",
|
|
1446
1449
|
|
|
1447
|
-
"""CREATE UNIQUE INDEX IF NOT EXISTS "ux_bank_reconciliation_active_voucher"
|
|
1448
|
-
ON "Bank Reconciliation" (voucher_type, voucher_no) WHERE status = 'Active'""",
|
|
1449
|
-
|
|
1450
1450
|
# --- Chat Sessions ---
|
|
1451
1451
|
"""CREATE TABLE IF NOT EXISTS "Chat Session" (
|
|
1452
1452
|
id TEXT PRIMARY KEY,
|
|
@@ -2427,6 +2427,27 @@ def _m024_bank_reconciliation(db: "Database") -> None:
|
|
|
2427
2427
|
db._add_column_if_missing("Bank Transaction", "reconciled_at", "TEXT")
|
|
2428
2428
|
|
|
2429
2429
|
|
|
2430
|
+
def _m025_bank_reconciliation_multi_account_voucher(db: "Database") -> None:
|
|
2431
|
+
"""Allow one voucher to reconcile one bank movement per bank account.
|
|
2432
|
+
|
|
2433
|
+
Version 24 allowed only one active reconciliation for an entire voucher.
|
|
2434
|
+
That rejects legitimate multi-bank journals (for example one CHF fee and
|
|
2435
|
+
one USD fee collected in a single Journal Entry). Keep the conservative
|
|
2436
|
+
one-use rule at the bank-account leg instead.
|
|
2437
|
+
"""
|
|
2438
|
+
db.ensure_column("Bank Reconciliation", "bank_account", "TEXT")
|
|
2439
|
+
db._alter_table_lock_safe([
|
|
2440
|
+
'DROP INDEX IF EXISTS "ux_bank_reconciliation_active_voucher"',
|
|
2441
|
+
'UPDATE "Bank Reconciliation" SET bank_account = ('
|
|
2442
|
+
'SELECT bt.bank_account FROM "Bank Transaction" bt '
|
|
2443
|
+
'WHERE bt.name = bank_transaction'
|
|
2444
|
+
') WHERE bank_account IS NULL',
|
|
2445
|
+
'CREATE UNIQUE INDEX IF NOT EXISTS "ux_bank_reconciliation_active_voucher_account" '
|
|
2446
|
+
'ON "Bank Reconciliation" (voucher_type, voucher_no, bank_account) '
|
|
2447
|
+
"WHERE status = 'Active'",
|
|
2448
|
+
], ["Bank Reconciliation"])
|
|
2449
|
+
|
|
2450
|
+
|
|
2430
2451
|
Database.MIGRATIONS = [
|
|
2431
2452
|
(1, "chat_message_session_id", _m001_chat_message_session_id),
|
|
2432
2453
|
(2, "chat_session_user_id", _m002_chat_session_user_id),
|
|
@@ -2452,6 +2473,7 @@ Database.MIGRATIONS = [
|
|
|
2452
2473
|
(22, "company_default_tax_templates", _m022_company_default_tax_templates),
|
|
2453
2474
|
(23, "camt_bank_statement_import", _m023_camt_bank_statement_import),
|
|
2454
2475
|
(24, "bank_reconciliation", _m024_bank_reconciliation),
|
|
2476
|
+
(25, "bank_reconciliation_multi_account_voucher", _m025_bank_reconciliation_multi_account_voucher),
|
|
2455
2477
|
]
|
|
2456
2478
|
|
|
2457
2479
|
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|