|
@@ -19,7 +19,7 @@ from django.db.models import Q
|
|
|
from django.views import View
|
|
|
|
|
|
from Model.models import UnicomComboOrderInfo, UnicomCombo, Order_Model, UnicomDeviceInfo, UnicomFlowPush, \
|
|
|
- IotCardUsageHistory, AccessNumberTaskQueue, IotCardOrderUsageHistory
|
|
|
+ IotCardUsageHistory, AccessNumberTaskQueue, IotCardOrderUsageHistory, OperatingCosts
|
|
|
from Object.RedisObject import RedisObject
|
|
|
from Object.ResponseObject import ResponseObject
|
|
|
from Object.TelecomObject import TelecomObject
|
|
@@ -72,6 +72,8 @@ class UnicomComboTaskView(View):
|
|
|
return self.get_access_number_change_task(response)
|
|
|
elif operation == 'queryTotalTrafficToday':
|
|
|
return self.query_total_traffic_today(response)
|
|
|
+ elif operation == 'createMonthlyCost':
|
|
|
+ return self.query_4G_order_info(response)
|
|
|
else:
|
|
|
return response.json(414)
|
|
|
|
|
@@ -678,3 +680,176 @@ class UnicomComboTaskView(View):
|
|
|
IotCardOrderUsageHistory.objects.bulk_create(iccid_list)
|
|
|
except Exception as e:
|
|
|
logger.error('统计4G卡日用量异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def query_4G_order_info(cls, response):
|
|
|
+ # 获取当前月的开始时间戳
|
|
|
+ first_timestamp, last_timestamp = cls.get_current_month_range()
|
|
|
+ # 统计条件失效时间大于当月开始时间(6月成本账单)统计范围订单创建时间大于5月1号的套餐
|
|
|
+ # 查询APP上显示的套餐
|
|
|
+ u_order_qs = UnicomComboOrderInfo.objects.filter(expire_time__gte=first_timestamp, combo__is_show=True
|
|
|
+ , created_time__gte=1714492800) \
|
|
|
+ .exclude(combo_id__in=[24, 26, 34]).values('status', 'combo__expiration_days', 'flow_total_usage',
|
|
|
+ 'combo__flow_total', 'order_id',
|
|
|
+ 'activation_time', 'expire_time', 'created_time', 'iccid'
|
|
|
+ ).order_by('created_time')
|
|
|
+ asy = threading.Thread(target=UnicomComboTaskView.created_flow_monthly_cost,
|
|
|
+ args=(u_order_qs, first_timestamp, last_timestamp))
|
|
|
+ asy.start()
|
|
|
+ print(datetime.datetime.today())
|
|
|
+ print(u_order_qs.count())
|
|
|
+ # 查询APP不显示购买的套餐 执行异步
|
|
|
+ u_order_qs = UnicomComboOrderInfo.objects.filter(expire_time__gte=first_timestamp, combo__is_show=False
|
|
|
+ , created_time__gte=1714492800) \
|
|
|
+ .exclude(combo_id__in=[24, 26, 34]).values('status', 'combo__expiration_days', 'flow_total_usage',
|
|
|
+ 'combo__flow_total', 'order_id',
|
|
|
+ 'activation_time', 'expire_time', 'created_time', 'iccid'
|
|
|
+ ).order_by('created_time')
|
|
|
+ asy = threading.Thread(target=UnicomComboTaskView.created_flow_monthly_cost,
|
|
|
+ args=(u_order_qs, first_timestamp, last_timestamp))
|
|
|
+ asy.start()
|
|
|
+ print(u_order_qs.count())
|
|
|
+ return response.json(0)
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def created_flow_monthly_cost(cls, u_order_qs, first_timestamp, last_timestamp):
|
|
|
+ print(f'开始了{datetime.datetime.now()}')
|
|
|
+ first_date = int(datetime.datetime.fromtimestamp(first_timestamp).strftime('%Y%m%d'))
|
|
|
+ costs_list = []
|
|
|
+ for item in u_order_qs:
|
|
|
+ try:
|
|
|
+ # 查询订单是否存在
|
|
|
+ order_qs = Order_Model.objects.filter(orderID=item['order_id'], status=1).values('orderID', 'UID',
|
|
|
+ 'payTime', 'price',
|
|
|
+ 'store_meal_name')
|
|
|
+
|
|
|
+ if not order_qs.exists():
|
|
|
+ continue
|
|
|
+
|
|
|
+ u_order = item
|
|
|
+
|
|
|
+ price = float(order_qs[0]['price'])
|
|
|
+
|
|
|
+ day_average_price = 0 # 收入分摊/天 订单金额/套餐总天数
|
|
|
+
|
|
|
+ if price > day_average_price:
|
|
|
+ expiration_days = int(u_order['combo__expiration_days'])
|
|
|
+ day_average_price = price / expiration_days
|
|
|
+
|
|
|
+ # 套餐到期时间与当月结算时间相差天数=剩余使用天数
|
|
|
+ expire_time = datetime.datetime.fromtimestamp(u_order['expire_time'])
|
|
|
+ month_time = datetime.datetime.fromtimestamp(last_timestamp)
|
|
|
+ # 剩余使用天数
|
|
|
+ days_diff = (expire_time - month_time).days
|
|
|
+
|
|
|
+ # 当月结算时间与套餐创建时间相差天数=当月结算天数
|
|
|
+ if u_order['created_time'] >= first_timestamp:
|
|
|
+ c_time = datetime.datetime.fromtimestamp(u_order['created_time'])
|
|
|
+ else:
|
|
|
+ c_time = datetime.datetime.fromtimestamp(first_timestamp)
|
|
|
+ settlement_days = (month_time - c_time).days + 1
|
|
|
+ settlement_days = 0 if settlement_days < 0 else settlement_days
|
|
|
+
|
|
|
+ # 组装当月成本账单结构
|
|
|
+ costs_vo = {
|
|
|
+ 'settlement_days': settlement_days, # 当月结算天数
|
|
|
+ 'order_id': order_qs[0]['orderID'],
|
|
|
+ 'uid': order_qs[0]['UID'],
|
|
|
+ 'day_average_price': Decimal(day_average_price).quantize(Decimal('0.0000')), # 收入分摊/天
|
|
|
+ 'purchase_quantity': u_order['combo__flow_total'],
|
|
|
+ 'start_time': u_order['created_time'],
|
|
|
+ 'end_time': u_order['expire_time'],
|
|
|
+ 'created_time': last_timestamp,
|
|
|
+ 'remaining_usage_time': days_diff, # 剩余使用时间
|
|
|
+ 'time': first_timestamp,
|
|
|
+ 'country_name': '中国',
|
|
|
+ 'order_type': '4G',
|
|
|
+ 'region': '国内',
|
|
|
+ 'price': order_qs[0]['price']
|
|
|
+ }
|
|
|
+ days = int(u_order['combo__expiration_days'])
|
|
|
+ if settlement_days > 0 and price > 0:
|
|
|
+ # 实际收入/套餐总天数*结算天数
|
|
|
+ costs_vo['monthly_income'] = Decimal((price - price * 0.0054) / days * settlement_days).quantize(
|
|
|
+ Decimal('0.0000'))
|
|
|
+ month_average_price = day_average_price * settlement_days if day_average_price > 0 else 0
|
|
|
+ # 收入分摊/天*当月使用天数
|
|
|
+ costs_vo['month_average_price'] = Decimal(month_average_price).quantize(Decimal('0.00'))
|
|
|
+
|
|
|
+ # 使用filter()方法进行查询
|
|
|
+ uos_qs = UnicomComboOrderInfo.objects.filter(
|
|
|
+ iccid=u_order['iccid'], expire_time__gte=first_timestamp
|
|
|
+ ).exclude(combo_id__in=[24, 26, 34])
|
|
|
+ con = uos_qs.count()
|
|
|
+ profit_margin = 0
|
|
|
+ cost = 2
|
|
|
+ profit = 0 # 当月利润
|
|
|
+
|
|
|
+ # 查询IOT卡订单用量历史
|
|
|
+ n_flow = IotCardOrderUsageHistory.objects.filter(
|
|
|
+ order_id=u_order['order_id'],
|
|
|
+ cycle__gte=first_date
|
|
|
+ ).order_by('-cycle_date')
|
|
|
+
|
|
|
+ cost = cost if not uos_qs.exists() else cost / con # 联通4G单卡月租2元/对应套餐数量 当月成本分摊
|
|
|
+ if n_flow.exists():
|
|
|
+ # 查询IOT卡订单用量历史
|
|
|
+ old_flow = IotCardOrderUsageHistory.objects.filter(
|
|
|
+ order_id=u_order['order_id'],
|
|
|
+ cycle__lt=first_date
|
|
|
+ ).order_by('-cycle_date')
|
|
|
+ old_use_flow = float(old_flow.first().total_traffic if old_flow.exists() else 0)
|
|
|
+ n_user_flow = float(n_flow.first().total_traffic)
|
|
|
+ actual_flow = n_user_flow - old_use_flow if n_user_flow > 0 else 0
|
|
|
+ costs_vo['actual_flow'] = actual_flow
|
|
|
+ # 基础分摊成本
|
|
|
+
|
|
|
+ flow_cost = 0
|
|
|
+ # 流量使用成本
|
|
|
+ if actual_flow > 0:
|
|
|
+ flow_cost = (actual_flow / 1024 * 0.4)
|
|
|
+ cost = cost + flow_cost
|
|
|
+ if 'monthly_income' in costs_vo:
|
|
|
+ profit = float(costs_vo['monthly_income']) - cost
|
|
|
+ profit_margin = profit / cost * (1 * 100)
|
|
|
+ costs_vo['actual_flow'] = Decimal(actual_flow).quantize(Decimal('0.00'))
|
|
|
+ elif price > 0:
|
|
|
+ if 'monthly_income' in costs_vo:
|
|
|
+ profit = float(costs_vo['monthly_income']) - cost
|
|
|
+ profit_margin = profit / cost * (1 * 100)
|
|
|
+ costs_vo['flow_cost'] = Decimal(cost).quantize(Decimal('0.00'))
|
|
|
+ costs_vo['profit'] = Decimal(profit).quantize(Decimal('0.00'))
|
|
|
+ costs_vo['profit_margin'] = Decimal(profit_margin).quantize(Decimal('0.00'))
|
|
|
+ fee = price * 0.0054 if price > 0 else 0
|
|
|
+ costs_vo['fee'] = Decimal(fee).quantize(Decimal('0.00'))
|
|
|
+ costs_vo['real_income'] = Decimal(price - fee).quantize(Decimal('0.00'))
|
|
|
+ costs_vo['expire'] = order_qs[0]['store_meal_name']
|
|
|
+ costs_list.append(OperatingCosts(**costs_vo))
|
|
|
+ # # 批量插入操作,每300条记录插入一次
|
|
|
+ if len(costs_list) >= 300:
|
|
|
+ OperatingCosts.objects.bulk_create(costs_list)
|
|
|
+ costs_list = []
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ logger.error('统计4G卡日用量异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
+ continue
|
|
|
+ # 插入剩余的记录
|
|
|
+ if costs_list:
|
|
|
+ OperatingCosts.objects.bulk_create(costs_list)
|
|
|
+ return True
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def get_current_month_range():
|
|
|
+ # 获取当前日期
|
|
|
+ today = datetime.datetime.today()
|
|
|
+ # 获取当前月份第一天
|
|
|
+ first_day = today.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
|
|
+ # 获取下个月第一天
|
|
|
+ next_month = today.replace(day=28) + datetime.timedelta(days=4) # 跳过了2月份的28号日期
|
|
|
+ last_day = next_month - datetime.timedelta(days=next_month.day)
|
|
|
+
|
|
|
+ # 转换为时间戳
|
|
|
+ first_timestamp = int(first_day.timestamp())
|
|
|
+ last_timestamp = int(last_day.timestamp())
|
|
|
+
|
|
|
+ return first_timestamp, last_timestamp
|