yeref 0.25.4__py3-none-any.whl → 0.25.6__py3-none-any.whl
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.
yeref/yeref.py
CHANGED
@@ -16097,7 +16097,7 @@ async def calc_metrics(bot, PROJECT_USERNAME, dataroom_folder_id, EXTRA_D, BASE_
|
|
16097
16097
|
offset += len(tbl['rows'])
|
16098
16098
|
|
16099
16099
|
# 5.3) Оставляем минимум 2 пустые строки перед следующей таблицей
|
16100
|
-
offset +=
|
16100
|
+
offset += 3
|
16101
16101
|
|
16102
16102
|
# 6) Выполняем единый batchUpdate для всех data_requests
|
16103
16103
|
write_body = {
|
@@ -16309,14 +16309,14 @@ async def return_unit_metrics(bot, data_users, EXTRA_D):
|
|
16309
16309
|
results.append({
|
16310
16310
|
"MO": mo,
|
16311
16311
|
"N": str(N),
|
16312
|
-
"MRR":
|
16313
|
-
"ARPU":
|
16314
|
-
"ARR":
|
16315
|
-
"ChurnR":
|
16316
|
-
"LTV1":
|
16317
|
-
"LTV2":
|
16318
|
-
"CMGR":
|
16319
|
-
"CAC":
|
16312
|
+
"MRR": mrr_fmt,
|
16313
|
+
"ARPU": fmt(ARPU),
|
16314
|
+
"ARR": fmt(ARR),
|
16315
|
+
"ChurnR": fmt(ChurnR),
|
16316
|
+
"LTV1": fmt(LTV1),
|
16317
|
+
"LTV2": fmt(LTV2),
|
16318
|
+
"CMGR": fmt(CMGR),
|
16319
|
+
"CAC": ""
|
16320
16320
|
})
|
16321
16321
|
|
16322
16322
|
f_name = os.path.join(EXTRA_D, "2_unit_metrics.csv")
|
@@ -16325,8 +16325,16 @@ async def return_unit_metrics(bot, data_users, EXTRA_D):
|
|
16325
16325
|
writer.writerow(["MO", "N", "MRR", "ARPU", "ARR", "ChurnR", "LTV1", "LTV2", "CMGR", "CAC"])
|
16326
16326
|
for row in results:
|
16327
16327
|
writer.writerow([
|
16328
|
-
row["MO"],
|
16329
|
-
row["
|
16328
|
+
row["MO"],
|
16329
|
+
str(row["N"]).replace('.', ','),
|
16330
|
+
str(row["MRR"]).replace('.', ','),
|
16331
|
+
str(row["ARPU"]).replace('.', ','),
|
16332
|
+
str(row["ARR"]).replace('.', ','),
|
16333
|
+
str(row["ChurnR"]).replace('.', ','),
|
16334
|
+
str(row["LTV1"]).replace('.', ','),
|
16335
|
+
str(row["LTV2"]).replace('.', ','),
|
16336
|
+
str(row["CMGR"]).replace('.', ','),
|
16337
|
+
str(row["CAC"]).replace('.', ',')
|
16330
16338
|
])
|
16331
16339
|
|
16332
16340
|
cmgr_vals = [float(r["CMGR"]) for r in results if r["CMGR"] != ""]
|
@@ -16334,7 +16342,7 @@ async def return_unit_metrics(bot, data_users, EXTRA_D):
|
|
16334
16342
|
factors = [1 + v for v in cmgr_vals]
|
16335
16343
|
avg = math.prod(factors) ** (1 / len(factors))
|
16336
16344
|
writer.writerow([])
|
16337
|
-
writer.writerow([f"Rev ~ ×{round(avg, 2)} monthly"])
|
16345
|
+
writer.writerow([f"Rev ~ ×{round(avg, 2)} monthly".replace('.', ',')])
|
16338
16346
|
|
16339
16347
|
result = f_name
|
16340
16348
|
thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
|
@@ -16429,7 +16437,7 @@ async def return_cohort_metrics(bot, data_users, EXTRA_D):
|
|
16429
16437
|
for r in table:
|
16430
16438
|
writer.writerow(r)
|
16431
16439
|
writer.writerow([])
|
16432
|
-
writer.writerow([f"Churn ~ ×{avg_churn:.2f} monthly"])
|
16440
|
+
writer.writerow([f"Churn ~ ×{avg_churn:.2f} monthly".replace('.', ',')])
|
16433
16441
|
|
16434
16442
|
result = f_name
|
16435
16443
|
thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
|
@@ -16503,12 +16511,12 @@ async def return_retention_metrics(bot, data_users, EXTRA_D):
|
|
16503
16511
|
else:
|
16504
16512
|
rev = rev_by_cohort[c].get(offset, 0.0)
|
16505
16513
|
if rev > 0:
|
16506
|
-
cell = f"{rev:.1f}"
|
16514
|
+
cell = f"{rev:.1f}".replace('.', ',')
|
16507
16515
|
row.append(cell)
|
16508
16516
|
row_sum += rev
|
16509
16517
|
else:
|
16510
|
-
row.append("0
|
16511
|
-
row.append(f"{row_sum:.1f}")
|
16518
|
+
row.append("0,0")
|
16519
|
+
row.append(f"{row_sum:.1f}".replace('.', ','))
|
16512
16520
|
writer.writerow(row)
|
16513
16521
|
|
16514
16522
|
factors = []
|
@@ -16521,7 +16529,7 @@ async def return_retention_metrics(bot, data_users, EXTRA_D):
|
|
16521
16529
|
avg_multiplier = math.prod(factors) ** (1 / len(factors)) if factors else 1.0
|
16522
16530
|
|
16523
16531
|
writer.writerow([])
|
16524
|
-
writer.writerow([f"NRR ~ ×{avg_multiplier:.2f} monthly"])
|
16532
|
+
writer.writerow([f"NRR ~ ×{avg_multiplier:.2f} monthly".replace('.', ',')])
|
16525
16533
|
|
16526
16534
|
result = f_name
|
16527
16535
|
thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
|
@@ -16538,6 +16546,7 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
|
|
16538
16546
|
try:
|
16539
16547
|
metrics = defaultdict(lambda: {"sum_amount": 0.0})
|
16540
16548
|
|
16549
|
+
# Собираем данные по месяцам
|
16541
16550
|
for USER_TID, USER_VARS, USER_LSTS in data_users:
|
16542
16551
|
USER_LSTS = json.loads(USER_LSTS or "{}")
|
16543
16552
|
USER_PAYMENTS = USER_LSTS.get("USER_PAYMENTS", [])
|
@@ -16548,12 +16557,14 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
|
|
16548
16557
|
amt = float(pay.get("AMOUNT", 0)) * 0.013
|
16549
16558
|
metrics[mo_p]["sum_amount"] += amt
|
16550
16559
|
|
16560
|
+
# Функция форматирования с запятой
|
16551
16561
|
def fmt(x):
|
16552
|
-
return f"{x:.2f}".rstrip("0").rstrip(".") if x is not None else ""
|
16562
|
+
return f"{x:.2f}".rstrip("0").rstrip(".").replace(".", ",") if x is not None else ""
|
16553
16563
|
|
16554
16564
|
# Сортируем месяцы
|
16555
16565
|
months_sorted = sorted(metrics.keys())
|
16556
16566
|
results = []
|
16567
|
+
np_values = []
|
16557
16568
|
|
16558
16569
|
for mo in months_sorted:
|
16559
16570
|
MRR = metrics[mo]["sum_amount"]
|
@@ -16562,12 +16573,12 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
|
|
16562
16573
|
OPEX = 4.5
|
16563
16574
|
OP = GP - OPEX
|
16564
16575
|
|
16565
|
-
#
|
16566
|
-
after_comm = OP * 0.70
|
16567
|
-
after_fiat = after_comm * 0.99
|
16568
|
-
COMM = OP - after_comm
|
16569
|
-
EXCH = after_comm - after_fiat
|
16570
|
-
NP = after_fiat
|
16576
|
+
# комиссия 30% и обмен 1%
|
16577
|
+
after_comm = OP * 0.70
|
16578
|
+
after_fiat = after_comm * 0.99
|
16579
|
+
COMM = OP - after_comm
|
16580
|
+
EXCH = after_comm - after_fiat
|
16581
|
+
NP = after_fiat
|
16571
16582
|
|
16572
16583
|
results.append([
|
16573
16584
|
mo,
|
@@ -16580,16 +16591,27 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
|
|
16580
16591
|
fmt(EXCH),
|
16581
16592
|
fmt(NP)
|
16582
16593
|
])
|
16594
|
+
np_values.append(NP)
|
16595
|
+
|
16596
|
+
# Вычисляем средний NP (если есть хотя бы одно значение)
|
16597
|
+
avg_np = sum(np_values) / len(np_values) if np_values else 0.0
|
16598
|
+
avg_np_str = fmt(avg_np)
|
16583
16599
|
|
16584
16600
|
f_name = os.path.join(EXTRA_D, "5_profit_and_loss_metrics.csv")
|
16585
16601
|
with open(f_name, "w", newline="", encoding="utf-8") as f:
|
16586
16602
|
writer = csv.writer(f)
|
16603
|
+
# Заголовок
|
16587
16604
|
writer.writerow([
|
16588
16605
|
"Mo", "MRR", "COGS", "Gross Profit",
|
16589
16606
|
"OPEX", "Operating Profit", "Comission (30%)", "Fiat (1%)", "Net Profit"
|
16590
16607
|
])
|
16608
|
+
# Строки по месяцам
|
16591
16609
|
for row in results:
|
16592
16610
|
writer.writerow(row)
|
16611
|
+
# Пустая строка перед средним
|
16612
|
+
writer.writerow([])
|
16613
|
+
# Строка со средним Net Profit
|
16614
|
+
writer.writerow([f"Average Net Profit: {avg_np_str}"])
|
16593
16615
|
|
16594
16616
|
result = f_name
|
16595
16617
|
thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
|
@@ -16599,6 +16621,7 @@ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
|
|
16599
16621
|
await asyncio.sleep(round(random.uniform(0, 1), 2))
|
16600
16622
|
finally:
|
16601
16623
|
return result
|
16624
|
+
|
16602
16625
|
# endregion
|
16603
16626
|
|
16604
16627
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
yeref/__init__.py,sha256=Qpv3o6Xa78VdLcsSRmctGtpnYE9btpAkCekgGhgJyXM,49
|
2
|
+
yeref/l_.py,sha256=LMX_olmJwq-tgoALJCnhV_fGrL_i_43yBLkLIcEVqGo,1176743
|
3
|
+
yeref/tonweb.js,sha256=Jf6aFOQ1OIY4q7fINYz-m5LsI3seMus124M5SYYZmtE,443659
|
4
|
+
yeref/yeref.py,sha256=8Ow6asK12jj3noAAUVtCKwq-txpj_ks_w-L-IQKqaZA,1056443
|
5
|
+
yeref-0.25.6.dist-info/METADATA,sha256=bsrMXHVBgRzsBy8TBIwOSrV1PA13MYOgpYrFdb4BfPY,118
|
6
|
+
yeref-0.25.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
+
yeref-0.25.6.dist-info/top_level.txt,sha256=yCQKchWHbfV-3OuQPYRdi2loypD-nmbDJbtt3OuKKkY,6
|
8
|
+
yeref-0.25.6.dist-info/RECORD,,
|
yeref-0.25.4.dist-info/RECORD
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
yeref/__init__.py,sha256=Qpv3o6Xa78VdLcsSRmctGtpnYE9btpAkCekgGhgJyXM,49
|
2
|
-
yeref/l_.py,sha256=LMX_olmJwq-tgoALJCnhV_fGrL_i_43yBLkLIcEVqGo,1176743
|
3
|
-
yeref/tonweb.js,sha256=Jf6aFOQ1OIY4q7fINYz-m5LsI3seMus124M5SYYZmtE,443659
|
4
|
-
yeref/yeref.py,sha256=TB7u0uxv8RGRRLfQ6iaeFS-Ng2YuhOx0JDo1n7om6gs,1055802
|
5
|
-
yeref-0.25.4.dist-info/METADATA,sha256=ecy4S3CjeJWmItaFH2Zc2IC7hgTSPR3TSVFtZqsUi_4,118
|
6
|
-
yeref-0.25.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
-
yeref-0.25.4.dist-info/top_level.txt,sha256=yCQKchWHbfV-3OuQPYRdi2loypD-nmbDJbtt3OuKKkY,6
|
8
|
-
yeref-0.25.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|