50 lines
1.6 KiB
Python
50 lines
1.6 KiB
Python
"""Read-only source reconciliation, without patient-level output."""
|
|
|
|
import json
|
|
import sys
|
|
from collections import Counter, defaultdict
|
|
from decimal import Decimal
|
|
|
|
from openpyxl import load_workbook
|
|
|
|
wb = load_workbook(sys.argv[1], read_only=True, data_only=True)
|
|
rates = {
|
|
str(row[3]): Decimal(str(row[4]))
|
|
for row in wb["产品毛利率"].iter_rows(min_row=6, values_only=True)
|
|
if row[3] and row[4] is not None
|
|
}
|
|
totals = defaultdict(lambda: {"rows": 0, "revenue": Decimal(0), "gross": Decimal(0), "customers": set()})
|
|
precision = Counter()
|
|
quality = Counter()
|
|
for row in wb["明细"].iter_rows(min_row=3, values_only=True):
|
|
period = f"{int(row[0])}-{int(str(row[1]).removesuffix('月')):02d}"
|
|
v = Decimal(str(row[13]))
|
|
t = totals[period]
|
|
t["rows"] += 1
|
|
t["revenue"] += v
|
|
t["gross"] += v * rates.get(row[14], Decimal(0))
|
|
t["customers"].add(row[3])
|
|
for i in [5, 11, 12, 13]:
|
|
if row[i] is not None:
|
|
n = Decimal(str(row[i]))
|
|
if n != n.quantize(Decimal("0.0001")):
|
|
precision[i] += 1
|
|
quality["negative_revenue"] += v < 0
|
|
quality["g_l_mismatch"] += row[6] != row[11]
|
|
quality["i_n_mismatch"] += row[8] != row[13]
|
|
quality["missing_margin"] += row[14] not in rates
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"totals": {p: {**v, "customers": len(v["customers"])} for p, v in totals.items()},
|
|
"precision_exceeds_four": dict(precision),
|
|
"quality": dict(quality),
|
|
"rates": rates,
|
|
},
|
|
default=str,
|
|
ensure_ascii=False,
|
|
indent=2,
|
|
)
|
|
)
|
|
wb.close()
|