Fix depreciation mirror selection and TDS capital account exclusion
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
__version__ = "1.25.5"
|
||||
__version__ = "1.25.6"
|
||||
AGENT_NAME = "ERP Local Agent"
|
||||
|
||||
@@ -968,6 +968,61 @@ class LocalAccountingStore:
|
||||
"provisional": fy_end > today,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _looks_like_depreciation_text(value: str) -> bool:
|
||||
text = re.sub(r"[^a-z0-9]+", " ", str(value or "").casefold()).strip()
|
||||
if not text:
|
||||
return False
|
||||
return any(token in text for token in (
|
||||
"depreciation","depn","depreciation expense","depreciation reserve",
|
||||
"accumulated depreciation","provision for depreciation",
|
||||
))
|
||||
|
||||
def _recorded_depreciation_for_asset(self, db: sqlite3.Connection, *, tally_guid: str,
|
||||
asset_ledger_name: str, start_date: str, end_date: str) -> dict:
|
||||
rows = db.execute(
|
||||
"""SELECT v.id AS voucher_id,
|
||||
COALESCE(NULLIF(v.effective_date,''),v.voucher_date) AS movement_date,
|
||||
v.voucher_type_name,v.voucher_number,v.reference,v.narration,
|
||||
e.amount,e.is_deemed_positive
|
||||
FROM tally_voucher_ledger_entries e
|
||||
JOIN tally_vouchers v ON v.id=e.voucher_id
|
||||
WHERE v.tally_guid=?
|
||||
AND lower(trim(COALESCE(e.ledger_name,'')))=lower(trim(?))
|
||||
AND COALESCE(NULLIF(v.effective_date,''),v.voucher_date)>=?
|
||||
AND COALESCE(NULLIF(v.effective_date,''),v.voucher_date)<=?
|
||||
AND lower(COALESCE(v.is_cancelled,'')) NOT IN ('yes','true','1')
|
||||
AND lower(COALESCE(v.is_optional,'')) NOT IN ('yes','true','1')
|
||||
ORDER BY movement_date,v.id""",
|
||||
(tally_guid,asset_ledger_name,start_date,end_date),
|
||||
).fetchall()
|
||||
total=0.0; vouchers=[]; seen=set()
|
||||
for row in rows:
|
||||
if self._is_debit_entry(row):
|
||||
continue
|
||||
counter_rows=db.execute(
|
||||
"""SELECT ledger_name FROM tally_voucher_ledger_entries
|
||||
WHERE voucher_id=? AND lower(trim(COALESCE(ledger_name,'')))<>lower(trim(?))""",
|
||||
(int(row["voucher_id"]),asset_ledger_name),
|
||||
).fetchall()
|
||||
counters=[str(x["ledger_name"] or "").strip() for x in counter_rows]
|
||||
text=" ".join([str(row["voucher_type_name"] or ""),str(row["reference"] or ""),
|
||||
str(row["narration"] or ""),*counters])
|
||||
if not self._looks_like_depreciation_text(text):
|
||||
continue
|
||||
total += abs(float(row["amount"] or 0))
|
||||
vid=int(row["voucher_id"])
|
||||
if vid not in seen:
|
||||
seen.add(vid)
|
||||
vouchers.append({
|
||||
"voucher_id":vid,"date":str(row["movement_date"] or ""),
|
||||
"voucher_type":str(row["voucher_type_name"] or ""),
|
||||
"voucher_number":str(row["voucher_number"] or ""),
|
||||
"reference":str(row["reference"] or ""),
|
||||
"counter_ledgers":counters,
|
||||
})
|
||||
return {"amount":round(total,2),"voucher_count":len(vouchers),"vouchers":vouchers,"already_recorded":bool(total>0)}
|
||||
|
||||
def depreciation_preview(self, client_id: int, *, tally_guid: str, fy_start: str, fy_end: str) -> dict:
|
||||
if not self.exists(client_id):
|
||||
raise ValueError("Accounting storage is not initialized for this client.")
|
||||
@@ -1003,13 +1058,20 @@ class LocalAccountingStore:
|
||||
AND lower(COALESCE(v.is_optional,'')) NOT IN ('yes','true','1')""",
|
||||
(tally_guid,name,start.isoformat(),movement_end.isoformat()),
|
||||
).fetchall()
|
||||
full=half=reductions=0.0
|
||||
recorded_dep=self._recorded_depreciation_for_asset(
|
||||
db,tally_guid=tally_guid,asset_ledger_name=name,
|
||||
start_date=start.isoformat(),end_date=movement_end.isoformat()
|
||||
)
|
||||
recorded_dep_amount=float(recorded_dep.get("amount") or 0)
|
||||
full=half=0.0; raw_credit_reductions=0.0
|
||||
for e in entries:
|
||||
amt=abs(float(e["amount"] or 0))
|
||||
if self._is_debit_entry(e):
|
||||
if self._half_rate_addition(str(e["movement_date"] or ""), end): half += amt
|
||||
else: full += amt
|
||||
else: reductions += amt
|
||||
else:
|
||||
raw_credit_reductions += amt
|
||||
reductions=max(0.0,raw_credit_reductions-recorded_dep_amount)
|
||||
opening_wdv = abs(float(row["opening_balance"] or 0))
|
||||
tally_closing = abs(float(row["closing_balance"] or 0))
|
||||
additions_total = round(full + half, 2)
|
||||
@@ -1024,6 +1086,10 @@ class LocalAccountingStore:
|
||||
"ledger_key":key,"ledger_guid":str(row["master_guid"] or ""),"ledger_name":name,"parent_group":str(row["parent"] or ""),
|
||||
"opening_wdv":opening_wdv,"tally_closing_balance":tally_closing,
|
||||
"additions_full_rate":round(full,2),"additions_half_rate":round(half,2),"reductions":round(reductions,2),
|
||||
"recorded_depreciation":round(recorded_dep_amount,2),
|
||||
"depreciation_already_recorded":bool(recorded_dep.get("already_recorded")),
|
||||
"recorded_depreciation_voucher_count":int(recorded_dep.get("voucher_count") or 0),
|
||||
"recorded_depreciation_vouchers":list(recorded_dep.get("vouchers") or []),
|
||||
"rate_percent":rules.get(key,0.0),
|
||||
"movement_entries":len(entries),
|
||||
})
|
||||
@@ -1050,7 +1116,12 @@ class LocalAccountingStore:
|
||||
full_base=max(0.0, opening+full-reductions)
|
||||
dep=min(closing_before, (full_base*rate/100.0)+(half*rate/200.0))
|
||||
dep=round(dep,2); closing=round(max(0.0,closing_before-dep),2); total+=dep
|
||||
line={**row,"rate_percent":rate,"depreciation_amount":dep,"closing_wdv":closing,"closing_before_depreciation":round(closing_before,2)}
|
||||
recorded_dep=float(row.get("recorded_depreciation") or 0)
|
||||
line={**row,"rate_percent":rate,"depreciation_amount":dep,
|
||||
"recorded_depreciation":round(recorded_dep,2),
|
||||
"depreciation_already_recorded":bool(recorded_dep>0),
|
||||
"remaining_unrecorded_depreciation":round(max(0.0,dep-recorded_dep),2),
|
||||
"closing_wdv":closing,"closing_before_depreciation":round(closing_before,2)}
|
||||
lines.append(line)
|
||||
mapping=preview["mapping"]
|
||||
with self.connect(client_id) as db:
|
||||
@@ -1067,7 +1138,19 @@ class LocalAccountingStore:
|
||||
db.execute("""INSERT INTO it_depreciation_run_lines(run_id,line_no,ledger_key,ledger_guid,ledger_name,parent_group,opening_wdv,additions_full_rate,additions_half_rate,reductions,rate_percent,depreciation_amount,closing_wdv,payload_json)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||
(run_id,i,row["ledger_key"],row["ledger_guid"],row["ledger_name"],row["parent_group"],row["opening_wdv"],row["additions_full_rate"],row["additions_half_rate"],row["reductions"],row["rate_percent"],row["depreciation_amount"],row["closing_wdv"],json.dumps(row,ensure_ascii=False,separators=(",",":"))))
|
||||
return {"run_id":run_id,"status":"draft","company_name":str(mapping.get("company_name") or ""),"fy_start":str(fy_start),"fy_end":str(fy_end),"total_depreciation":round(total,2),"depreciation_expense_ledger":str(depreciation_expense_ledger or ""),"depreciation_reserve_ledger":str(depreciation_reserve_ledger or ""),"lines":lines,"proposed_entry":{"debit_ledger":str(depreciation_expense_ledger or "Depreciation"),"credit_ledger":str(depreciation_reserve_ledger or "Depreciation Reserve"),"amount":round(total,2)},"no_tally_writeback":True}
|
||||
total_recorded=round(sum(float(x.get("recorded_depreciation") or 0) for x in lines),2)
|
||||
total_remaining=round(sum(float(x.get("remaining_unrecorded_depreciation") or 0) for x in lines),2)
|
||||
return {"run_id":run_id,"status":"draft","company_name":str(mapping.get("company_name") or ""),
|
||||
"fy_start":str(fy_start),"fy_end":str(fy_end),"total_depreciation":round(total,2),
|
||||
"total_recorded_depreciation":total_recorded,
|
||||
"total_remaining_unrecorded_depreciation":total_remaining,
|
||||
"depreciation_expense_ledger":str(depreciation_expense_ledger or ""),
|
||||
"depreciation_reserve_ledger":str(depreciation_reserve_ledger or ""),
|
||||
"lines":lines,
|
||||
"proposed_entry":{"debit_ledger":str(depreciation_expense_ledger or "Depreciation"),
|
||||
"credit_ledger":str(depreciation_reserve_ledger or "Depreciation Reserve"),
|
||||
"amount":round(total,2)},
|
||||
"no_tally_writeback":True}
|
||||
|
||||
def get_it_depreciation_run(self, client_id: int, run_id: int) -> dict:
|
||||
with self.connect(client_id) as db:
|
||||
|
||||
@@ -3164,22 +3164,27 @@ class AgentCommandProcessor:
|
||||
if not value:
|
||||
return False
|
||||
exact = {
|
||||
"capital account",
|
||||
"capital accounts",
|
||||
"partners capital",
|
||||
"partner capital",
|
||||
"partners capital accounts",
|
||||
"partner capital accounts",
|
||||
"proprietors capital",
|
||||
"proprietor capital",
|
||||
"owners capital",
|
||||
"owner capital",
|
||||
"share capital",
|
||||
"reserves surplus",
|
||||
"reserves and surplus",
|
||||
"capital account","capital accounts","partners capital","partner capital",
|
||||
"partners capital accounts","partner capital accounts","proprietors capital",
|
||||
"proprietor capital","owners capital","owner capital","share capital",
|
||||
"reserves surplus","reserves and surplus","partners current account",
|
||||
"partner current account","partners current accounts","partner current accounts",
|
||||
"proprietors current account","proprietor current account",
|
||||
"owners current account","owner current account",
|
||||
}
|
||||
if value in exact:
|
||||
return True
|
||||
owner_prefix = (
|
||||
value.startswith("partner ") or value.startswith("partners ")
|
||||
or value.startswith("proprietor ") or value.startswith("proprietors ")
|
||||
or value.startswith("owner ") or value.startswith("owners ")
|
||||
)
|
||||
current_account_like = (
|
||||
" current account" in value or " current accounts" in value
|
||||
or " current a c" in value or value.endswith(" current ac")
|
||||
)
|
||||
if owner_prefix and current_account_like:
|
||||
return True
|
||||
return (
|
||||
value.startswith("capital account ")
|
||||
or value.endswith(" capital account")
|
||||
|
||||
Reference in New Issue
Block a user