fix(migration): label EFECTIVO cash rows as CASH DEPOSIT
The EFECTIVO ledgers have no type column — in Access the transaction type
is implied by which table a row lives in — so unlike DATOS2 there was no
string to map and typeId came out NULL on all 13,496 rows.
That is not just a blank label. handleGetAccountDetails in
my.jorgecuadros.com identifies payments by matching TYPEOFTRX against
('PAYMENT THANK YOU', 'PAYPAL', 'CASH DEPOSIT', 'CHECK DEPOSIT') to reset
the running balance in mode=current. An unlabelled payment is not
recognised, so the balance silently diverges from legacy — 285 rows across
129 customers in the current year alone.
"CASH DEPOSIT" is measured, not chosen: matching the unlabelled rows to the
live site on (NUMid, date, amount) resolves unanimously to that label —
66/66 in the current-year `datosfreak` and 100/100 in the prior-year `2025`
table, the only two periods the site allowlists.
The FM3 fee streams (EFECTIVO FM3 627, CHEQUE FM3 157) have the same
missing-type problem and are deliberately left NULL: every row predates both
exposed periods, so nothing can be matched against a legacy label and none
can reach a customer. Guessing "CHECK DEPOSIT" there would feed the
payment-detection list on no evidence.
type_id_for(None) returns None, so call sites without a label are unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -166,12 +166,24 @@ def main():
|
|||||||
s(r["conepto"]),
|
s(r["conepto"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
def efectivo_like(src, name, domain, custmap, src_db, legacy_tbl, *, seen=None):
|
def efectivo_like(src, name, domain, custmap, src_db, legacy_tbl, *, seen=None,
|
||||||
|
type_label=None):
|
||||||
"""Load an EFECTIVO-shaped cash ledger.
|
"""Load an EFECTIVO-shaped cash ledger.
|
||||||
|
|
||||||
`seen` (a set) makes the load de-duplicating: keys are added to it as
|
`seen` (a set) makes the load de-duplicating: keys are added to it as
|
||||||
rows load, and a row whose key is already present is skipped. That is
|
rows load, and a row whose key is already present is skipped. That is
|
||||||
how EFECTIVO_BACKUP contributes only its genuinely-new rows.
|
how EFECTIVO_BACKUP contributes only its genuinely-new rows.
|
||||||
|
|
||||||
|
`type_label` names the transaction type for every row. These tables have
|
||||||
|
no type column at all — in Access the type is implied by which table the
|
||||||
|
row lives in — so unlike DATOS2 there is no string to map and typeId came
|
||||||
|
out NULL for all of them.
|
||||||
|
|
||||||
|
That is not merely a blank label. handleGetAccountDetails in
|
||||||
|
my.jorgecuadros.com identifies payments by matching TYPEOFTRX against
|
||||||
|
('PAYMENT THANK YOU', 'PAYPAL', 'CASH DEPOSIT', 'CHECK DEPOSIT') to reset
|
||||||
|
the running balance in mode=current; an unlabelled payment is not
|
||||||
|
recognised and the balance silently diverges from legacy.
|
||||||
"""
|
"""
|
||||||
nonlocal skip_cust, skip_date, skip_dupe
|
nonlocal skip_cust, skip_date, skip_dupe
|
||||||
df = load(src, name)
|
df = load(src, name)
|
||||||
@@ -189,9 +201,20 @@ def main():
|
|||||||
skip_date += 1; continue
|
skip_date += 1; continue
|
||||||
add(cid, domain, td, dec(r["monto"], Decimal(0)), cur(r["monedas"]),
|
add(cid, domain, td, dec(r["monto"], Decimal(0)), cur(r["monedas"]),
|
||||||
reference=s(r["folio"]), message=s(r["conepto"]),
|
reference=s(r["folio"]), message=s(r["conepto"]),
|
||||||
|
typeid=type_id_for(type_label),
|
||||||
src_db=src_db, src_tbl=legacy_tbl, legacy=str(int(r["_row_num"])))
|
src_db=src_db, src_tbl=legacy_tbl, legacy=str(int(r["_row_num"])))
|
||||||
|
|
||||||
def fm3(name, legacy_tbl, check_col=None):
|
def fm3(name, legacy_tbl, check_col=None):
|
||||||
|
"""FM3 fee streams. Deliberately left unlabelled, unlike EFECTIVO.
|
||||||
|
|
||||||
|
These rows (EFECTIVO FM3 627, CHEQUE FM3 157) also have no type column,
|
||||||
|
but every one of them predates the two periods the site exposes — it
|
||||||
|
allowlists only the current year and the prior year — so none can be
|
||||||
|
matched against a legacy label, and none can reach a customer. Inventing
|
||||||
|
a plausible name like "CHECK DEPOSIT" would feed the payment-detection
|
||||||
|
list in handleGetAccountDetails on nothing but a guess. Leave them NULL
|
||||||
|
until a real mapping is available.
|
||||||
|
"""
|
||||||
nonlocal skip_cust, skip_date
|
nonlocal skip_cust, skip_date
|
||||||
df = load("stg_utilities", name)
|
df = load("stg_utilities", name)
|
||||||
for _, r in df.iterrows():
|
for _, r in df.iterrows():
|
||||||
@@ -237,17 +260,25 @@ def main():
|
|||||||
# order matters: EFECTIVO is the live table and loads first, so a collision
|
# order matters: EFECTIVO is the live table and loads first, so a collision
|
||||||
# always resolves in its favour.
|
# always resolves in its favour.
|
||||||
cash_seen: set = set()
|
cash_seen: set = set()
|
||||||
|
# "CASH DEPOSIT" is not a guess: matching these rows to the live site on
|
||||||
|
# (NUMid, date, amount) resolves to that label unanimously — 66/66 in the
|
||||||
|
# current-year `datosfreak` and 100/100 in the prior-year `2025` table,
|
||||||
|
# which are the only two periods the site exposes.
|
||||||
efectivo_like("stg_utilities", "efectivo", "UTILITY", util_cust, "UTILITIES",
|
efectivo_like("stg_utilities", "efectivo", "UTILITY", util_cust, "UTILITIES",
|
||||||
"EFECTIVO", seen=cash_seen)
|
"EFECTIVO", seen=cash_seen, type_label="CASH DEPOSIT")
|
||||||
efectivo_like("stg_utilities", "efectivo_backup", "UTILITY", util_cust, "UTILITIES",
|
efectivo_like("stg_utilities", "efectivo_backup", "UTILITY", util_cust, "UTILITIES",
|
||||||
"EFECTIVO_BACKUP", seen=cash_seen)
|
"EFECTIVO_BACKUP", seen=cash_seen, type_label="CASH DEPOSIT")
|
||||||
fm3("efectivo_fm3", "EFECTIVO FM3")
|
fm3("efectivo_fm3", "EFECTIVO FM3")
|
||||||
fm3("cheque_fm3", "CHEQUE FM3", check_col="num_cheque")
|
fm3("cheque_fm3", "CHEQUE FM3", check_col="num_cheque")
|
||||||
billing("datos2", "datos2")
|
billing("datos2", "datos2")
|
||||||
billing("fee_anual", "FEE ANUAL")
|
billing("fee_anual", "FEE ANUAL")
|
||||||
billing("fee15", "fee15")
|
billing("fee15", "fee15")
|
||||||
iva()
|
iva()
|
||||||
efectivo_like("stg_seguros", "efectivo", "INSURANCE", ins_cust, "SEGUROS 16_be", "EFECTIVO")
|
# Same record shape in the seguros DB. Labelled for consistency in the
|
||||||
|
# platform's own UI; unverifiable against the site, which only ever reads
|
||||||
|
# domain='UTILITY', so no customer-facing behaviour depends on it.
|
||||||
|
efectivo_like("stg_seguros", "efectivo", "INSURANCE", ins_cust, "SEGUROS 16_be",
|
||||||
|
"EFECTIVO", type_label="CASH DEPOSIT")
|
||||||
|
|
||||||
if sync_mode:
|
if sync_mode:
|
||||||
# Transaction types are rebuilt with fresh uuids each run; resolve them
|
# Transaction types are rebuilt with fresh uuids each run; resolve them
|
||||||
|
|||||||
Reference in New Issue
Block a user