yeref 0.24.90__tar.gz → 0.24.92__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yeref
3
- Version: 0.24.90
3
+ Version: 0.24.92
4
4
  Summary: desc-f
5
5
  Author: john smith
6
6
  Dynamic: author
@@ -2,7 +2,7 @@ from setuptools import setup
2
2
 
3
3
  setup(
4
4
  name='yeref',
5
- version='0.24.90',
5
+ version='0.24.92',
6
6
  description='desc-f',
7
7
  author='john smith',
8
8
  packages=['yeref'],
@@ -15926,7 +15926,7 @@ async def upd_user_data(ENT_TID, data, web_app_init_data, PROJECT_USERNAME, BASE
15926
15926
 
15927
15927
 
15928
15928
  # region unit ecomonics
15929
- async def return_activity_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
15929
+ async def calc_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
15930
15930
  try:
15931
15931
  schema_name = "USER"
15932
15932
  if PROJECT_USERNAME == 'FereyBotBot':
@@ -15939,6 +15939,85 @@ async def return_activity_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
15939
15939
  sql = f"SELECT {schema_name}_TID FROM \"{schema_name}\""
15940
15940
  data_ents = await db_select_pg(sql, (), BASE_P)
15941
15941
 
15942
+ sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
15943
+ data_users = await db_select_pg(sql, (), BASE_P)
15944
+
15945
+ months = ["2025-06", "2025-07", "2025-08", "2025-09"]
15946
+ data_users = []
15947
+ for _ in range(30):
15948
+ # дата входа
15949
+ entry_month = random.choice(months)
15950
+ entry_day = random.randint(1, 28)
15951
+ entry_date = f"{entry_month}-{entry_day:02}"
15952
+ entry_dt_obj = datetime.strptime(entry_date, '%Y-%m-%d')
15953
+ entry_dt = f"{entry_dt_obj.strftime('%d-%m-%Y')}_{datetime.now().strftime('%H-%M-%S')}"
15954
+ utm = random.choice(["/start", "/startapp"])
15955
+
15956
+ # месяцы от входа и дальше
15957
+ valid_months = [m for m in months if datetime.strptime(m + "-01", "%Y-%m-%d") >= entry_dt_obj.replace(day=1)]
15958
+ if not valid_months:
15959
+ valid_months = [entry_month]
15960
+
15961
+ user_mau = sorted(random.sample(valid_months, k=random.randint(1, len(valid_months))))
15962
+ user_dau_dates = set()
15963
+ txs, payments = [], []
15964
+
15965
+ # платеж
15966
+ if user_mau:
15967
+ pay_month = random.choice(user_mau)
15968
+ pay_day = random.randint(1, 28)
15969
+ pay_date = f"{pay_month}-{pay_day:02}"
15970
+ dt_pay = datetime.strptime(pay_date, "%Y-%m-%d")
15971
+ payments = [{
15972
+ "TYPE": random.choice(["don", "sub", "pst"]),
15973
+ "DT_START": f"{dt_pay.strftime('%d-%m-%Y')}_14-00-00",
15974
+ "DT_END": "0",
15975
+ "AMOUNT": str(random.randint(10, 1000))
15976
+ }]
15977
+ user_dau_dates.add(pay_date)
15978
+
15979
+ # вход в приложение
15980
+ user_dau_dates.add(entry_date)
15981
+ for m in user_mau:
15982
+ day = random.randint(1, 28)
15983
+ visit = f"{m}-{day:02}"
15984
+ dt_visit = datetime.strptime(visit, "%Y-%m-%d")
15985
+ if dt_visit >= entry_dt_obj and random.random() < 0.7:
15986
+ user_dau_dates.add(visit)
15987
+
15988
+ # статусы (отток) с низкой вероятностью
15989
+ USER_STATUSES = []
15990
+ if random.random() < 0.2: # 10% шанс оттока
15991
+ churn_month = random.choice(valid_months)
15992
+ churn_day = random.randint(1, 28)
15993
+ churn_date = f"{churn_month}-{churn_day:02}"
15994
+ churn_ts = datetime.strptime(churn_date, "%Y-%m-%d").strftime("%d-%m-%Y") + "_23-59-59"
15995
+ USER_STATUSES = [{random.choice(["left", "kicked"]): churn_ts}]
15996
+
15997
+ user_dau = sorted(user_dau_dates)
15998
+ wallet = f"wallet{random.randint(1, 100)}" if txs else random.choice([f"wallet{random.randint(1, 100)}", ""])
15999
+
16000
+ data_users.append((
16001
+ random.randint(100000, 999999),
16002
+ json.dumps({"USER_WALLET": wallet, "USER_UTM": utm, "USER_DT": entry_dt}),
16003
+ json.dumps({"USER_DAU": user_dau, "USER_MAU": user_mau, "USER_TXS": txs,
16004
+ "USER_PAYMENTS": payments, "USER_STATUSES": USER_STATUSES})
16005
+ ))
16006
+ print(f"gen {data_users=}")
16007
+
16008
+ r1 = await return_activity_metrics(bot, data_users, EXTRA_D, BASE_P, data_ents, schema_name)
16009
+ r2 = await return_unit_metrics(bot, data_users, EXTRA_D, BASE_P)
16010
+ r3 = await return_cohort_metrics(bot, data_users, EXTRA_D, BASE_P)
16011
+ r4 = await return_retention_metrics(bot, data_users, EXTRA_D, BASE_P)
16012
+ r5 = await return_profit_and_loss_metrics(bot, data_users, EXTRA_D, BASE_P)
16013
+ except Exception as e:
16014
+ logger.info(log_ % str(e))
16015
+ await asyncio.sleep(round(random.uniform(0, 1), 2))
16016
+
16017
+
16018
+ async def return_activity_metrics(bot, data_users, EXTRA_D, BASE_P, data_ents, schema_name):
16019
+ result = None
16020
+ try:
15942
16021
  metrics_by_month = defaultdict(lambda: {
15943
16022
  "dau": 0,
15944
16023
  "mau": 0,
@@ -15953,79 +16032,8 @@ async def return_activity_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
15953
16032
  seen_dau = set()
15954
16033
  wallets_set = set()
15955
16034
  users_set = set()
15956
- pay_set = set()
15957
16035
 
15958
16036
  def process_user_rows(rows):
15959
- # months = ["2025-06", "2025-07", "2025-08", "2025-09"]
15960
- # data_users = []
15961
- # for _ in range(3):
15962
- # # дата входа
15963
- # entry_month = random.choice(months)
15964
- # entry_day = random.randint(1, 28)
15965
- # entry_date = f"{entry_month}-{entry_day:02}"
15966
- # entry_dt_obj = datetime.strptime(entry_date, '%Y-%m-%d')
15967
- # entry_dt = f"{entry_dt_obj.strftime('%d-%m-%Y')}_{datetime.now().strftime('%H-%M-%S')}"
15968
- # utm = random.choice(["/start", "/startapp"])
15969
- #
15970
- # # месяцы от входа и дальше
15971
- # valid_months = [m for m in months if datetime.strptime(m + "-01", "%Y-%m-%d") >= entry_dt_obj.replace(day=1)]
15972
- # if not valid_months:
15973
- # valid_months = [entry_month]
15974
- #
15975
- # user_mau = sorted(random.sample(valid_months, k=random.randint(1, len(valid_months))))
15976
- # user_dau_dates = set()
15977
- # txs, payments = [], []
15978
- #
15979
- # # транзакция
15980
- # if user_mau and random.random() < 0.5:
15981
- # tx_month = random.choice(user_mau)
15982
- # tx_day = random.randint(1, 28)
15983
- # tx_date = f"{tx_month}-{tx_day:02}"
15984
- # dt_tx = datetime.strptime(tx_date, "%Y-%m-%d")
15985
- # if dt_tx >= entry_dt_obj:
15986
- # txs = [{
15987
- # "TYPE": random.choice(["don", "sub", "pst"]),
15988
- # "AMOUNT": str(random.randint(1, 10)),
15989
- # "ADDRESS": f"address{random.randint(1, 999)}",
15990
- # "DT_START": f"{dt_tx.strftime('%d-%m-%Y')}_12-00-00",
15991
- # }]
15992
- # user_dau_dates.add(tx_date)
15993
- #
15994
- # # платеж
15995
- # if user_mau and random.random() < 0.5:
15996
- # pay_month = random.choice(user_mau)
15997
- # pay_day = random.randint(1, 28)
15998
- # pay_date = f"{pay_month}-{pay_day:02}"
15999
- # dt_pay = datetime.strptime(pay_date, "%Y-%m-%d")
16000
- # if dt_pay >= entry_dt_obj:
16001
- # payments = [{
16002
- # "TYPE": random.choice(["don", "sub", "pst"]),
16003
- # "DT_START": f"{dt_pay.strftime('%d-%m-%Y')}_14-00-00",
16004
- # "DT_END": "0",
16005
- # "AMOUNT": str(random.randint(1, 10))
16006
- # }]
16007
- # user_dau_dates.add(pay_date)
16008
- #
16009
- # # вход в приложение
16010
- # user_dau_dates.add(entry_date)
16011
- #
16012
- # # остальные посещения
16013
- # for m in user_mau:
16014
- # day = random.randint(1, 28)
16015
- # visit = f"{m}-{day:02}"
16016
- # dt_visit = datetime.strptime(visit, "%Y-%m-%d")
16017
- # if dt_visit >= entry_dt_obj and random.random() < 0.7:
16018
- # user_dau_dates.add(visit)
16019
- #
16020
- # user_dau = sorted(user_dau_dates)
16021
- # wallet = f"wallet{random.randint(1, 100)}" if txs else random.choice([f"wallet{random.randint(1, 100)}", ""])
16022
- #
16023
- # data_users.append((
16024
- # random.randint(100000, 999999),
16025
- # json.dumps({"USER_WALLET": wallet, "USER_UTM": utm, "USER_DT": entry_dt}),
16026
- # json.dumps({"USER_DAU": user_dau, "USER_MAU": user_mau, "USER_TXS": txs, "USER_PAYMENTS": payments})
16027
- # ))
16028
-
16029
16037
  for USER_TID, USER_VARS, USER_LSTS in rows:
16030
16038
  USER_VARS = json.loads(USER_VARS or "{}")
16031
16039
  USER_LSTS = json.loads(USER_LSTS or "{}")
@@ -16081,6 +16089,8 @@ async def return_activity_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16081
16089
  key = "/startapp" if USER_UTM == "/startapp" else "/start"
16082
16090
  metrics_by_month[month_key][key] += 1
16083
16091
 
16092
+ process_user_rows(data_users)
16093
+
16084
16094
  for item in data_ents:
16085
16095
  ENT_TID = item[0]
16086
16096
  sql = f'SELECT USER_TID, USER_VARS, USER_LSTS FROM {schema_name}_{ENT_TID}.USER'
@@ -16088,11 +16098,6 @@ async def return_activity_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16088
16098
  print(f"schema_name {data_users=}")
16089
16099
  process_user_rows(data_users)
16090
16100
 
16091
- sql = f"SELECT USER_TID, USER_VARS, USER_LSTS FROM \"USER\""
16092
- data_users = await db_select_pg(sql, (), BASE_P)
16093
- print(f"{data_users=}")
16094
- process_user_rows(data_users)
16095
-
16096
16101
  all_months = sorted(metrics_by_month.keys())
16097
16102
  f_name = os.path.join(EXTRA_D, "1_activity_metrics.csv")
16098
16103
  with open(f_name, mode="w", encoding="utf-8", newline="") as csvfile:
@@ -16115,18 +16120,19 @@ async def return_activity_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16115
16120
  csvfile.write(f"Unique wallet count: {len(wallets_set)}\n")
16116
16121
  csvfile.write(f"Unique users count: {len(users_set)}\n")
16117
16122
 
16123
+ result = f_name
16118
16124
  thumb = types.FSInputFile(os.path.join(EXTRA_D, 'parse.jpg'))
16119
16125
  await bot.send_document(chat_id=my_tid, document=types.FSInputFile(f_name), thumbnail=thumb)
16120
16126
  except Exception as e:
16121
16127
  logger.info(log_ % str(e))
16122
16128
  await asyncio.sleep(round(random.uniform(0, 1), 2))
16129
+ finally:
16130
+ return result
16123
16131
 
16124
16132
 
16125
- async def return_unit_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16133
+ async def return_unit_metrics(bot, data_users, EXTRA_D):
16134
+ result = None
16126
16135
  try:
16127
- sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
16128
- data_users = await db_select_pg(sql, (), BASE_P)
16129
-
16130
16136
  metrics = defaultdict(lambda: {
16131
16137
  "new_users": 0,
16132
16138
  "sum_amount": 0.0,
@@ -16165,13 +16171,14 @@ async def return_unit_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16165
16171
  all_months = sorted(metrics.keys())
16166
16172
  cumulative_users = 0
16167
16173
  results = []
16168
-
16174
+ first_mrr = None
16175
+
16169
16176
  for idx, mo in enumerate(all_months):
16170
16177
  data = metrics[mo]
16171
16178
  new_u = data["new_users"]
16172
16179
  cumulative_users += new_u
16173
-
16174
16180
  MRR = data["sum_amount"]
16181
+
16175
16182
  def fmt(x):
16176
16183
  return f"{x:.2f}".rstrip("0").rstrip(".") if x is not None else ""
16177
16184
 
@@ -16209,8 +16216,8 @@ async def return_unit_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16209
16216
  "CAC": ""
16210
16217
  })
16211
16218
 
16212
- path = os.path.join(EXTRA_D, "2_unit_metrics.csv")
16213
- with open(path, "w", newline="", encoding="utf-8") as f:
16219
+ f_name = os.path.join(EXTRA_D, "2_unit_metrics.csv")
16220
+ with open(f_name, "w", newline="", encoding="utf-8") as f:
16214
16221
  writer = csv.writer(f)
16215
16222
  writer.writerow(["MO", "N", "MRR", "ARPU", "ARR", "ChurnR", "LTV1", "LTV2", "CMGR", "CAC"])
16216
16223
  for row in results:
@@ -16226,82 +16233,19 @@ async def return_unit_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16226
16233
  writer.writerow([])
16227
16234
  writer.writerow([f"Rev ~ ×{round(avg, 2)} monthly"])
16228
16235
 
16236
+ result = f_name
16229
16237
  thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
16230
- await bot.send_document(chat_id=my_tid, document=types.FSInputFile(path), thumbnail=thumb)
16238
+ await bot.send_document(chat_id=my_tid, document=types.FSInputFile(f_name), thumbnail=thumb)
16231
16239
  except Exception as e:
16232
16240
  logger.info(log_ % str(e))
16233
16241
  await asyncio.sleep(round(random.uniform(0, 1), 2))
16242
+ finally:
16243
+ return result
16234
16244
 
16235
16245
 
16236
- async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16246
+ async def return_cohort_metrics(bot, data_users, EXTRA_D):
16247
+ result = None
16237
16248
  try:
16238
- sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
16239
- data_users = await db_select_pg(sql, (), BASE_P)
16240
-
16241
- months = ["2025-06", "2025-07", "2025-08", "2025-09"]
16242
- data_users = []
16243
- for _ in range(30):
16244
- # дата входа
16245
- entry_month = random.choice(months)
16246
- entry_day = random.randint(1, 28)
16247
- entry_date = f"{entry_month}-{entry_day:02}"
16248
- entry_dt_obj = datetime.strptime(entry_date, '%Y-%m-%d')
16249
- entry_dt = f"{entry_dt_obj.strftime('%d-%m-%Y')}_{datetime.now().strftime('%H-%M-%S')}"
16250
- utm = random.choice(["/start", "/startapp"])
16251
-
16252
- # месяцы от входа и дальше
16253
- valid_months = [m for m in months if datetime.strptime(m + "-01", "%Y-%m-%d") >= entry_dt_obj.replace(day=1)]
16254
- if not valid_months:
16255
- valid_months = [entry_month]
16256
-
16257
- user_mau = sorted(random.sample(valid_months, k=random.randint(1, len(valid_months))))
16258
- user_dau_dates = set()
16259
- txs, payments = [], []
16260
-
16261
- # платеж
16262
- if user_mau:
16263
- pay_month = random.choice(user_mau)
16264
- pay_day = random.randint(1, 28)
16265
- pay_date = f"{pay_month}-{pay_day:02}"
16266
- dt_pay = datetime.strptime(pay_date, "%Y-%m-%d")
16267
- # if dt_pay >= entry_dt_obj:
16268
- payments = [{
16269
- "TYPE": random.choice(["don", "sub", "pst"]),
16270
- "DT_START": f"{dt_pay.strftime('%d-%m-%Y')}_14-00-00",
16271
- "DT_END": "0",
16272
- "AMOUNT": str(random.randint(1, 10))
16273
- }]
16274
- user_dau_dates.add(pay_date)
16275
-
16276
- # вход в приложение
16277
- user_dau_dates.add(entry_date)
16278
- for m in user_mau:
16279
- day = random.randint(1, 28)
16280
- visit = f"{m}-{day:02}"
16281
- dt_visit = datetime.strptime(visit, "%Y-%m-%d")
16282
- if dt_visit >= entry_dt_obj and random.random() < 0.7:
16283
- user_dau_dates.add(visit)
16284
-
16285
- # статусы (отток) с низкой вероятностью
16286
- USER_STATUSES = []
16287
- if random.random() < 0.2: # 10% шанс оттока
16288
- churn_month = random.choice(valid_months)
16289
- churn_day = random.randint(1, 28)
16290
- churn_date = f"{churn_month}-{churn_day:02}"
16291
- churn_ts = datetime.strptime(churn_date, "%Y-%m-%d").strftime("%d-%m-%Y") + "_23-59-59"
16292
- USER_STATUSES = [{random.choice(["left", "kicked"]): churn_ts}]
16293
-
16294
- user_dau = sorted(user_dau_dates)
16295
- wallet = f"wallet{random.randint(1, 100)}" if txs else random.choice([f"wallet{random.randint(1, 100)}", ""])
16296
-
16297
- data_users.append((
16298
- random.randint(100000, 999999),
16299
- json.dumps({"USER_WALLET": wallet, "USER_UTM": utm, "USER_DT": entry_dt}),
16300
- json.dumps({"USER_DAU": user_dau, "USER_MAU": user_mau, "USER_TXS": txs,
16301
- "USER_PAYMENTS": payments, "USER_STATUSES": USER_STATUSES})
16302
- ))
16303
- print(f"gen {data_users=}")
16304
-
16305
16249
  cohorts = defaultdict(set)
16306
16250
  activity_months = defaultdict(set)
16307
16251
 
@@ -16324,13 +16268,6 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16324
16268
  cohort_months = sorted(cohorts.keys())
16325
16269
  num_months = len(cohort_months)
16326
16270
 
16327
- def add_months(mo_str, n):
16328
- y, m = map(int, mo_str.split("-"))
16329
- total = m + n
16330
- new_y = y + (total - 1) // 12
16331
- new_m = (total - 1) % 12 + 1
16332
- return f"{new_y:04d}-{new_m:02d}"
16333
-
16334
16271
  # Собираем таблицу посменно по календарным месяцам
16335
16272
  table = []
16336
16273
  header = ["Месяц/Когорта"]
@@ -16383,90 +16320,27 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16383
16320
 
16384
16321
  avg_churn = (total_lost / total_start) if total_start else 0
16385
16322
 
16386
- path = os.path.join(EXTRA_D, "3_cohort_metrics.csv")
16387
- with open(path, "w", newline="", encoding="utf-8") as f:
16323
+ f_name = os.path.join(EXTRA_D, "3_cohort_metrics.csv")
16324
+ with open(f_name, "w", newline="", encoding="utf-8") as f:
16388
16325
  writer = csv.writer(f)
16389
16326
  for r in table:
16390
16327
  writer.writerow(r)
16391
16328
  writer.writerow([])
16392
16329
  writer.writerow([f"Churn ~ ×{avg_churn:.2f} monthly"])
16393
16330
 
16331
+ result = f_name
16394
16332
  thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
16395
- await bot.send_document(chat_id=my_tid, document=types.FSInputFile(path), thumbnail=thumb)
16333
+ await bot.send_document(chat_id=my_tid, document=types.FSInputFile(f_name), thumbnail=thumb)
16396
16334
  except Exception as e:
16397
16335
  logger.info(log_ % str(e))
16398
16336
  await asyncio.sleep(round(random.uniform(0, 1), 2))
16337
+ finally:
16338
+ return result
16399
16339
 
16400
16340
 
16401
- async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16341
+ async def return_retention_metrics(bot, data_users, EXTRA_D):
16342
+ result = None
16402
16343
  try:
16403
- sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
16404
- data_users = await db_select_pg(sql, (), BASE_P)
16405
-
16406
- months = ["2025-06", "2025-07", "2025-08", "2025-09"]
16407
- data_users = []
16408
- for _ in range(30):
16409
- # дата входа
16410
- entry_month = random.choice(months)
16411
- entry_day = random.randint(1, 28)
16412
- entry_date = f"{entry_month}-{entry_day:02}"
16413
- entry_dt_obj = datetime.strptime(entry_date, '%Y-%m-%d')
16414
- entry_dt = f"{entry_dt_obj.strftime('%d-%m-%Y')}_{datetime.now().strftime('%H-%M-%S')}"
16415
- utm = random.choice(["/start", "/startapp"])
16416
-
16417
- # месяцы от входа и дальше
16418
- valid_months = [m for m in months if datetime.strptime(m + "-01", "%Y-%m-%d") >= entry_dt_obj.replace(day=1)]
16419
- if not valid_months:
16420
- valid_months = [entry_month]
16421
-
16422
- user_mau = sorted(random.sample(valid_months, k=random.randint(1, len(valid_months))))
16423
- user_dau_dates = set()
16424
- txs, payments = [], []
16425
-
16426
- # платеж
16427
- if user_mau:
16428
- pay_month = random.choice(user_mau)
16429
- pay_day = random.randint(1, 28)
16430
- pay_date = f"{pay_month}-{pay_day:02}"
16431
- dt_pay = datetime.strptime(pay_date, "%Y-%m-%d")
16432
- # if dt_pay >= entry_dt_obj:
16433
- payments = [{
16434
- "TYPE": random.choice(["don", "sub", "pst"]),
16435
- "DT_START": f"{dt_pay.strftime('%d-%m-%Y')}_14-00-00",
16436
- "DT_END": "0",
16437
- "AMOUNT": str(random.randint(1, 10))
16438
- }]
16439
- user_dau_dates.add(pay_date)
16440
-
16441
- # вход в приложение
16442
- user_dau_dates.add(entry_date)
16443
- for m in user_mau:
16444
- day = random.randint(1, 28)
16445
- visit = f"{m}-{day:02}"
16446
- dt_visit = datetime.strptime(visit, "%Y-%m-%d")
16447
- if dt_visit >= entry_dt_obj and random.random() < 0.7:
16448
- user_dau_dates.add(visit)
16449
-
16450
- # статусы (отток) с низкой вероятностью
16451
- USER_STATUSES = []
16452
- if random.random() < 0.2: # 10% шанс оттока
16453
- churn_month = random.choice(valid_months)
16454
- churn_day = random.randint(1, 28)
16455
- churn_date = f"{churn_month}-{churn_day:02}"
16456
- churn_ts = datetime.strptime(churn_date, "%Y-%m-%d").strftime("%d-%m-%Y") + "_23-59-59"
16457
- USER_STATUSES = [{random.choice(["left", "kicked"]): churn_ts}]
16458
-
16459
- user_dau = sorted(user_dau_dates)
16460
- wallet = f"wallet{random.randint(1, 100)}" if txs else random.choice([f"wallet{random.randint(1, 100)}", ""])
16461
-
16462
- data_users.append((
16463
- random.randint(100000, 999999),
16464
- json.dumps({"USER_WALLET": wallet, "USER_UTM": utm, "USER_DT": entry_dt}),
16465
- json.dumps({"USER_DAU": user_dau, "USER_MAU": user_mau, "USER_TXS": txs,
16466
- "USER_PAYMENTS": payments, "USER_STATUSES": USER_STATUSES})
16467
- ))
16468
- print(f"gen {data_users=}")
16469
-
16470
16344
  rev_by_cohort = defaultdict(lambda: defaultdict(float))
16471
16345
  cohort_users = defaultdict(set)
16472
16346
 
@@ -16505,8 +16379,8 @@ async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16505
16379
  num_cohorts = len(cohort_months)
16506
16380
  first_cohort = cohort_months[0]
16507
16381
 
16508
- path = os.path.join(EXTRA_D, "4_retention_metrics.csv")
16509
- with open(path, "w", newline="", encoding="utf-8") as f:
16382
+ f_name = os.path.join(EXTRA_D, "4_retention_metrics.csv")
16383
+ with open(f_name, "w", newline="", encoding="utf-8") as f:
16510
16384
  writer = csv.writer(f)
16511
16385
  header = ["Месяц/Когорта"] + [
16512
16386
  f"{c} ({len(cohort_users[c])})" for c in cohort_months
@@ -16546,81 +16420,19 @@ async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16546
16420
  writer.writerow([])
16547
16421
  writer.writerow([f"NRR ~ ×{avg_multiplier:.2f} monthly"])
16548
16422
 
16423
+ result = f_name
16549
16424
  thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
16550
- await bot.send_document(chat_id=my_tid, document=types.FSInputFile(path), thumbnail=thumb)
16425
+ await bot.send_document(chat_id=my_tid, document=types.FSInputFile(f_name), thumbnail=thumb)
16551
16426
  except Exception as e:
16552
16427
  logger.info(log_ % str(e))
16553
16428
  await asyncio.sleep(round(random.uniform(0, 1), 2))
16429
+ finally:
16430
+ return result
16554
16431
 
16555
16432
 
16556
- async def return_profit_and_loss_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16433
+ async def return_profit_and_loss_metrics(bot, data_users, EXTRA_D):
16434
+ result = None
16557
16435
  try:
16558
- sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
16559
- data_users = await db_select_pg(sql, (), BASE_P)
16560
-
16561
- months = ["2025-06", "2025-07", "2025-08", "2025-09"]
16562
- data_users = []
16563
- for _ in range(30):
16564
- # дата входа
16565
- entry_month = random.choice(months)
16566
- entry_day = random.randint(1, 28)
16567
- entry_date = f"{entry_month}-{entry_day:02}"
16568
- entry_dt_obj = datetime.strptime(entry_date, '%Y-%m-%d')
16569
- entry_dt = f"{entry_dt_obj.strftime('%d-%m-%Y')}_{datetime.now().strftime('%H-%M-%S')}"
16570
- utm = random.choice(["/start", "/startapp"])
16571
-
16572
- # месяцы от входа и дальше
16573
- valid_months = [m for m in months if datetime.strptime(m + "-01", "%Y-%m-%d") >= entry_dt_obj.replace(day=1)]
16574
- if not valid_months:
16575
- valid_months = [entry_month]
16576
-
16577
- user_mau = sorted(random.sample(valid_months, k=random.randint(1, len(valid_months))))
16578
- user_dau_dates = set()
16579
- txs, payments = [], []
16580
-
16581
- # платеж
16582
- if user_mau:
16583
- pay_month = random.choice(user_mau)
16584
- pay_day = random.randint(1, 28)
16585
- pay_date = f"{pay_month}-{pay_day:02}"
16586
- dt_pay = datetime.strptime(pay_date, "%Y-%m-%d")
16587
- payments = [{
16588
- "TYPE": random.choice(["don", "sub", "pst"]),
16589
- "DT_START": f"{dt_pay.strftime('%d-%m-%Y')}_14-00-00",
16590
- "DT_END": "0",
16591
- "AMOUNT": str(random.randint(10, 1000))
16592
- }]
16593
- user_dau_dates.add(pay_date)
16594
-
16595
- # вход в приложение
16596
- user_dau_dates.add(entry_date)
16597
- for m in user_mau:
16598
- day = random.randint(1, 28)
16599
- visit = f"{m}-{day:02}"
16600
- dt_visit = datetime.strptime(visit, "%Y-%m-%d")
16601
- if dt_visit >= entry_dt_obj and random.random() < 0.7:
16602
- user_dau_dates.add(visit)
16603
-
16604
- # статусы (отток) с низкой вероятностью
16605
- USER_STATUSES = []
16606
- if random.random() < 0.2: # 10% шанс оттока
16607
- churn_month = random.choice(valid_months)
16608
- churn_day = random.randint(1, 28)
16609
- churn_date = f"{churn_month}-{churn_day:02}"
16610
- churn_ts = datetime.strptime(churn_date, "%Y-%m-%d").strftime("%d-%m-%Y") + "_23-59-59"
16611
- USER_STATUSES = [{random.choice(["left", "kicked"]): churn_ts}]
16612
-
16613
- user_dau = sorted(user_dau_dates)
16614
- wallet = f"wallet{random.randint(1, 100)}" if txs else random.choice([f"wallet{random.randint(1, 100)}", ""])
16615
-
16616
- data_users.append((
16617
- random.randint(100000, 999999),
16618
- json.dumps({"USER_WALLET": wallet, "USER_UTM": utm, "USER_DT": entry_dt}),
16619
- json.dumps({"USER_DAU": user_dau, "USER_MAU": user_mau, "USER_TXS": txs,
16620
- "USER_PAYMENTS": payments, "USER_STATUSES": USER_STATUSES})
16621
- ))
16622
- print(f"gen {data_users=}")
16623
-
16624
16436
  metrics = defaultdict(lambda: {"sum_amount": 0.0})
16625
16437
 
16626
16438
  for USER_TID, USER_VARS, USER_LSTS in data_users:
@@ -16666,8 +16478,8 @@ async def return_profit_and_loss_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P)
16666
16478
  fmt(NP)
16667
16479
  ])
16668
16480
 
16669
- path = os.path.join(EXTRA_D, "5_profit_and_loss_metrics.csv")
16670
- with open(path, "w", newline="", encoding="utf-8") as f:
16481
+ f_name = os.path.join(EXTRA_D, "5_profit_and_loss_metrics.csv")
16482
+ with open(f_name, "w", newline="", encoding="utf-8") as f:
16671
16483
  writer = csv.writer(f)
16672
16484
  writer.writerow([
16673
16485
  "Mo", "MRR", "COGS", "Gross Profit",
@@ -16676,12 +16488,14 @@ async def return_profit_and_loss_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P)
16676
16488
  for row in results:
16677
16489
  writer.writerow(row)
16678
16490
 
16491
+ result = f_name
16679
16492
  thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
16680
- await bot.send_document(chat_id=my_tid, document=types.FSInputFile(path), thumbnail=thumb)
16493
+ await bot.send_document(chat_id=my_tid, document=types.FSInputFile(f_name), thumbnail=thumb)
16681
16494
  except Exception as e:
16682
16495
  logger.info(log_ % str(e))
16683
16496
  await asyncio.sleep(round(random.uniform(0, 1), 2))
16684
-
16497
+ finally:
16498
+ return result
16685
16499
  # endregion
16686
16500
 
16687
16501
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yeref
3
- Version: 0.24.90
3
+ Version: 0.24.92
4
4
  Summary: desc-f
5
5
  Author: john smith
6
6
  Dynamic: author
File without changes
File without changes
File without changes
File without changes
File without changes