增加设备消化账单

publicsignpoll
youngS 4 years ago
parent 7d781de388
commit 50da6044a4
  1. 2
      fir_client/src/components/FirDownload.vue
  2. 2
      fir_client/src/components/ShortDownload.vue
  3. 128
      fir_client/src/components/user/FirSuperSignBase.vue
  4. 15
      fir_client/src/restful/index.js
  5. 1
      fir_ser/api/migrations/0015_iosdeveloperpublicpoolbill_remoteclientinfo.py
  6. 26
      fir_ser/api/migrations/0018_devicequeue.py
  7. 17
      fir_ser/api/migrations/0019_iosdeveloperpublicpoolbill_udid.py
  8. 9
      fir_ser/api/models.py
  9. 2
      fir_ser/api/tasks.py
  10. 3
      fir_ser/api/urls.py
  11. 66
      fir_ser/api/utils/app/supersignutils.py
  12. 44
      fir_ser/api/utils/serializer.py
  13. 15
      fir_ser/api/utils/utils.py
  14. 2
      fir_ser/api/views/apps.py
  15. 25
      fir_ser/api/views/supersign.py

@ -612,7 +612,7 @@
} }
} else if (data.code === 1002) { } else if (data.code === 1002) {
window.location.href = location.href.replace(location.search, ''); window.location.href = location.href.replace(location.search, '');
}else if (data.code === 302 && data.data) { } else if (data.code === 302 && data.data) {
window.location.href = data.data; window.location.href = data.data;
} else { } else {
if (data.msg) { if (data.msg) {

@ -597,7 +597,7 @@
} }
} else if (data.code === 1002) { } else if (data.code === 1002) {
window.location.href = location.href.replace(location.search, ''); window.location.href = location.href.replace(location.search, '');
}else if (data.code === 302 && data.data) { } else if (data.code === 302 && data.data) {
window.location.href = data.data; window.location.href = data.data;
} else { } else {
this.iserror = true; this.iserror = true;

@ -126,6 +126,7 @@
<el-table-column <el-table-column
fixed fixed
prop="issuer_id" prop="issuer_id"
align="center"
label="用户 issuer_id" label="用户 issuer_id"
width="300"> width="300">
<template slot-scope="scope"> <template slot-scope="scope">
@ -147,6 +148,7 @@
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="is_actived" prop="is_actived"
align="center"
label="是否激活" label="是否激活"
width="110"> width="110">
<template slot-scope="scope"> <template slot-scope="scope">
@ -160,6 +162,7 @@
<el-table-column <el-table-column
prop="certid" prop="certid"
label="账户状态" label="账户状态"
align="center"
width="100"> width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<el-popover trigger="hover" placement="top"> <el-popover trigger="hover" placement="top">
@ -178,6 +181,7 @@
<el-table-column <el-table-column
prop="usable_number" prop="usable_number"
label="可用设备" label="可用设备"
align="center"
width="60"> width="60">
<template slot-scope="scope"> <template slot-scope="scope">
<el-popover trigger="hover" placement="top"> <el-popover trigger="hover" placement="top">
@ -194,6 +198,7 @@
<el-table-column <el-table-column
prop="use_number" prop="use_number"
align="center"
label="设备消耗" label="设备消耗"
width="60"> width="60">
<template slot-scope="scope"> <template slot-scope="scope">
@ -211,9 +216,11 @@
:formatter="formatter" :formatter="formatter"
prop="cert_expire_time" prop="cert_expire_time"
label="证书到期时间" label="证书到期时间"
align="center"
width="160"> width="160">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center"
prop="description" prop="description"
label="备注" label="备注"
> >
@ -221,6 +228,7 @@
<el-table-column <el-table-column
fixed="right" fixed="right"
label="操作" label="操作"
align="center"
width="150"> width="150">
<template slot-scope="scope"> <template slot-scope="scope">
@ -322,38 +330,45 @@
style="width: 100%"> style="width: 100%">
<el-table-column <el-table-column
fixed fixed
align="center"
prop="device_udid" prop="device_udid"
label="设备ID" label="设备ID"
> >
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="device_name" prop="device_name"
align="center"
label="设备名称" label="设备名称"
width="120"> width="120">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="bundle_id" prop="bundle_id"
align="center"
label="应用ID" label="应用ID"
width="180"> width="180">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="bundle_name" prop="bundle_name"
align="center"
label="应用名称" label="应用名称"
width="160"> width="160">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="developer_id" prop="developer_id"
label="开发者ID" label="开发者ID"
align="center"
width="200"> width="200">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
v-if="$store.state.userinfo&&$store.state.userinfo.role == 3" v-if="$store.state.userinfo&&$store.state.userinfo.role == 3"
prop="other_uid" prop="other_uid"
align="center"
label="被使用户uid"> label="被使用户uid">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:formatter="deviceformatter" :formatter="deviceformatter"
prop="created_time" prop="created_time"
align="center"
label="授权时间" label="授权时间"
width="160"> width="160">
</el-table-column> </el-table-column>
@ -386,6 +401,7 @@
<el-table-column <el-table-column
fixed fixed
align="center"
prop="udid" prop="udid"
label="设备ID" label="设备ID"
> >
@ -403,33 +419,39 @@
<el-table-column <el-table-column
prop="imei" prop="imei"
label="imei" label="imei"
width="180"> align="center"
width="160">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="product" prop="product"
label="设备名称" label="设备名称"
align="center"
width="100"> width="100">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="version" prop="version"
label="设备型号" label="设备型号"
align="center"
width="100"> width="100">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="serial" prop="serial"
label="设备序列号" label="设备序列号"
width="150"> align="center"
width="140">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
v-if="$store.state.userinfo&&$store.state.userinfo.role == 3" v-if="$store.state.userinfo&&$store.state.userinfo.role == 3"
prop="other_uid" prop="other_uid"
align="center"
label="被使用户uid"> label="被使用户uid">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:formatter="deviceformatter" :formatter="deviceformatter"
prop="created_time" prop="created_time"
label="添加时间" label="添加时间"
align="center"
width="160"> width="160">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -445,10 +467,91 @@
@click="udidDeleteFun(scope)">删除 @click="udidDeleteFun(scope)">删除
</el-button> </el-button>
<el-tag v-else> <el-tag v-else>
不允许操作 ...
</el-tag>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="设备消耗账单" name="devicesbill">
<el-input
style="width: 30%;margin-right: 30px;margin-bottom: 10px"
v-model="udidsearch"
clearable
placeholder="输入UDID"/>
<el-button type="primary" icon="el-icon-search" @click="handleCurrentChange(pagination.currentPage)">
搜索
</el-button>
<el-table
:data="app_bill_lists"
v-loading="loading"
border
stripe
style="width: 100%">
<el-table-column
fixed
prop="udid"
align="center"
label="设备ID"
>
</el-table-column>
<el-table-column
prop="product"
label="设备名称"
align="center"
width="100">
</el-table-column>
<el-table-column
width="100"
prop="app_name"
align="center"
label="消费者"
>
</el-table-column>
<el-table-column
prop="remote_addr"
align="center"
label="客户端IP"
width="100">
</el-table-column>
<el-table-column
prop="action"
label="账单类型"
align="center"
width="100">
</el-table-column>
<el-table-column
prop="description"
label="备注"
align="center"
width="200">
</el-table-column>
<el-table-column
:formatter="deviceformatter"
align="center"
prop="created_time"
label="生成日期"
width="160">
</el-table-column>
<el-table-column
label="设备状态"
align="center"
width="110">
<template slot-scope="scope">
<el-tag v-if="scope.row.is_used===false" type="info">已经释放</el-tag>
<el-tag v-else>
使用中
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-tab-pane> </el-tab-pane>
@ -470,7 +573,7 @@
<script> <script>
import {iosdeveloper, iosdevices, iosdevicesudid, developercert} from "@/restful"; import {iosdeveloper, iosdevices, iosdevicesudid, developercert, DeviceBillInfo} from "@/restful";
import {getUserInfoFun, removeAaary} from "@/utils"; import {getUserInfoFun, removeAaary} from "@/utils";
export default { export default {
@ -480,6 +583,7 @@
fileList: [], fileList: [],
app_developer_lists: [], app_developer_lists: [],
app_devices_lists: [], app_devices_lists: [],
app_bill_lists: [],
app_udid_lists: [], app_udid_lists: [],
activeName: "iosdeveloper", activeName: "iosdeveloper",
udidsearch: "", udidsearch: "",
@ -693,7 +797,10 @@
// this.dialogaddDeveloperVisible=true; // this.dialogaddDeveloperVisible=true;
} else if (tabname === "iosdeveloper") { } else if (tabname === "iosdeveloper") {
this.iosdeveloperFun({"methods": "GET", "data": data}) this.iosdeveloperFun({"methods": "GET", "data": data})
} else if (tabname === "devicesbill") {
this.iosdevicebillFun({"methods": "GET", "data": data})
} }
}, },
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
handleClick(tab, event) { handleClick(tab, event) {
@ -780,6 +887,19 @@
} }
}, params) }, params)
}, },
iosdevicebillFun(data) {
this.loading = true;
DeviceBillInfo(data => {
if (data.code === 1000) {
this.app_bill_lists = data.data;
this.pagination.total = data.count;
} else {
this.$message.error("操作失败了 " + data.msg);
}
this.loading = false
}, data)
},
iosdevicesudidFun(action, data, scope) { iosdevicesudidFun(action, data, scope) {
if (action !== 'GET') { if (action !== 'GET') {
this.loadingfun = this.$loading({ this.loadingfun = this.$loading({

@ -692,3 +692,18 @@ export function advertinfo(callBack, params, load = true) {
true true
); );
} }
/**签名账单 */
export function DeviceBillInfo(callBack, params, load = true) {
getData(
params.methods,
USERSEVER + '/supersign/bill',
params.data,
data => {
callBack(data);
},
load,
true,
true
);
}

@ -39,6 +39,7 @@ class Migration(migrations.Migration):
('udid_info', models.JSONField(blank=True, max_length=256, null=True, verbose_name='设备id信息')), ('udid_info', models.JSONField(blank=True, max_length=256, null=True, verbose_name='设备id信息')),
('developer_info', models.JSONField(blank=True, max_length=256, null=True, verbose_name='开发者信息')), ('developer_info', models.JSONField(blank=True, max_length=256, null=True, verbose_name='开发者信息')),
('description', models.CharField(blank=True, default='', max_length=128, verbose_name='操作描述')), ('description', models.CharField(blank=True, default='', max_length=128, verbose_name='操作描述')),
('remote_addr', models.GenericIPAddressField(verbose_name='远程IP地址')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='添加时间')), ('created_time', models.DateTimeField(auto_now_add=True, verbose_name='添加时间')),
('to_user_id', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, ('to_user_id', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
related_name='to_user_id', to=settings.AUTH_USER_MODEL, related_name='to_user_id', to=settings.AUTH_USER_MODEL,

@ -0,0 +1,26 @@
# Generated by Django 3.2.3 on 2021-11-03 14:25
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0017_developerappid_profile_id'),
]
operations = [
migrations.CreateModel(
name='DeviceQueue',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('udid', models.CharField(db_index=True, max_length=64, verbose_name='udid唯一标识')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='访问时间')),
('app_id',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.apps', verbose_name='应用id')),
('developerid',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.appiosdeveloperinfo',
verbose_name='所使用苹果开发者账户')),
],
),
]

@ -0,0 +1,17 @@
# Generated by Django 3.2.3 on 2021-11-03 17:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0018_devicequeue'),
]
operations = [
migrations.AddField(
model_name='iosdeveloperpublicpoolbill',
name='udid',
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='设备udid'),
),
]

@ -536,6 +536,7 @@ class IosDeveloperPublicPoolBill(models.Model):
number = models.IntegerField(verbose_name="消耗次数", default=1) number = models.IntegerField(verbose_name="消耗次数", default=1)
app_info = models.JSONField(max_length=256, verbose_name="属于哪个APP", null=True, blank=True) app_info = models.JSONField(max_length=256, verbose_name="属于哪个APP", null=True, blank=True)
udid_info = models.JSONField(max_length=256, verbose_name="设备id信息", null=True, blank=True) udid_info = models.JSONField(max_length=256, verbose_name="设备id信息", null=True, blank=True)
udid = models.CharField(max_length=64, verbose_name="设备udid", null=True, blank=True)
developer_info = models.JSONField(max_length=256, verbose_name="开发者信息", null=True, blank=True) developer_info = models.JSONField(max_length=256, verbose_name="开发者信息", null=True, blank=True)
udid_sync_info = models.ForeignKey(to="UDIDsyncDeveloper", on_delete=models.SET_NULL, verbose_name="关联同步设备信息", udid_sync_info = models.ForeignKey(to="UDIDsyncDeveloper", on_delete=models.SET_NULL, verbose_name="关联同步设备信息",
null=True, blank=True) null=True, blank=True)
@ -543,6 +544,7 @@ class IosDeveloperPublicPoolBill(models.Model):
# udid = models.ForeignKey(to="AppUDID", on_delete=models.CASCADE, verbose_name="所消耗的udid",null=True,blank=True) # udid = models.ForeignKey(to="AppUDID", on_delete=models.CASCADE, verbose_name="所消耗的udid",null=True,blank=True)
# developerid = models.ForeignKey(to="AppIOSDeveloperInfo", on_delete=models.CASCADE, verbose_name="所使用苹果开发者账户",null=True,blank=True) # developerid = models.ForeignKey(to="AppIOSDeveloperInfo", on_delete=models.CASCADE, verbose_name="所使用苹果开发者账户",null=True,blank=True)
description = models.CharField(verbose_name="操作描述", max_length=128, default='', blank=True) description = models.CharField(verbose_name="操作描述", max_length=128, default='', blank=True)
remote_addr = models.GenericIPAddressField(verbose_name="远程IP地址")
created_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间") created_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间")
class Meta: class Meta:
@ -568,3 +570,10 @@ class RemoteClientInfo(models.Model):
def __str__(self): def __str__(self):
return "%s-%s" % (self.remote_addr, self.description) return "%s-%s" % (self.remote_addr, self.description)
class DeviceQueue(models.Model):
app_id = models.ForeignKey(to='Apps', on_delete=models.CASCADE, verbose_name="应用id")
udid = models.CharField(max_length=64, verbose_name="udid唯一标识", db_index=True)
developerid = models.ForeignKey(to="AppIOSDeveloperInfo", on_delete=models.CASCADE, verbose_name="所使用苹果开发者账户")
created_time = models.DateTimeField(auto_now_add=True, verbose_name="访问时间")

@ -28,7 +28,7 @@ def run_sign_task(format_udid_info, short, client_ip):
return '签名余额不足' return '签名余额不足'
with cache.lock("%s_%s_%s" % ('run_sign_task', app_obj.app_id, ios_obj.developer_obj.issuer_id), timeout=60 * 10): with cache.lock("%s_%s_%s" % ('run_sign_task', app_obj.app_id, ios_obj.developer_obj.issuer_id), timeout=60 * 10):
ios_obj.get_developer_auth() ios_obj.get_developer_auth()
status, msg = ios_obj.sign(client_ip) status, msg = ios_obj.sign_ipa(client_ip)
if not status: if not status:
code = msg.get("code", -1) code = msg.get("code", -1)
if code == 0: if code == 0:

@ -25,7 +25,7 @@ from api.views.logout import LogoutView
from api.views.order import PriceView, OrderView, PaySuccess from api.views.order import PriceView, OrderView, PaySuccess
from api.views.receiveudids import IosUDIDView, TaskView from api.views.receiveudids import IosUDIDView, TaskView
from api.views.storage import StorageView from api.views.storage import StorageView
from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView, SuperSignCertView from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView, SuperSignCertView, DeviceUsedBillView
from api.views.thirdlogin import ValidWxChatToken, ThirdWxAccount from api.views.thirdlogin import ValidWxChatToken, ThirdWxAccount
from api.views.uploads import AppAnalyseView, UploadView from api.views.uploads import AppAnalyseView, UploadView
@ -56,6 +56,7 @@ urlpatterns = [
re_path("^supersign/devices$", SuperSignUsedView.as_view()), re_path("^supersign/devices$", SuperSignUsedView.as_view()),
re_path("^supersign/udid$", AppUDIDUsedView.as_view()), re_path("^supersign/udid$", AppUDIDUsedView.as_view()),
re_path("^supersign/cert$", SuperSignCertView.as_view()), re_path("^supersign/cert$", SuperSignCertView.as_view()),
re_path("^supersign/bill$", DeviceUsedBillView.as_view()),
re_path("^package_prices$", PriceView.as_view()), re_path("^package_prices$", PriceView.as_view()),
re_path("^orders$", OrderView.as_view()), re_path("^orders$", OrderView.as_view()),
re_path("^certification$", CertificationView.as_view()), re_path("^certification$", CertificationView.as_view()),

@ -205,16 +205,13 @@ def get_ios_developer_public_num(user_obj):
used_number = IosDeveloperPublicPoolBill.objects.filter(user_id=user_obj, action=0, used_number = IosDeveloperPublicPoolBill.objects.filter(user_id=user_obj, action=0,
udid_sync_info__isnull=False).aggregate( udid_sync_info__isnull=False).aggregate(
number=Sum('number')) number=Sum('number'))
if add_number: add_number = add_number.get("number", 0)
add_number = add_number.get("number", 0) if not add_number:
if not add_number: add_number = -99
return False used_number = used_number.get("number", 0)
used_number = used_number.get("number", 0) if not used_number:
if not used_number: used_number = 0
used_number = 0 return add_number - used_number
if add_number - used_number > 0:
return True
return False
def get_developer_user_by_app_udid(user_obj, udid): def get_developer_user_by_app_udid(user_obj, udid):
@ -234,25 +231,32 @@ def get_developer_user_by_app_udid(user_obj, udid):
for developer_obj in AppIOSDeveloperInfo.objects.filter(user_id=user_obj, is_actived=True, for developer_obj in AppIOSDeveloperInfo.objects.filter(user_id=user_obj, is_actived=True,
certid__isnull=False).order_by("created_time"): certid__isnull=False).order_by("created_time"):
if get_developer_udided(developer_obj)[1] < developer_obj.usable_number: if get_developer_udided(developer_obj)[1] < developer_obj.usable_number:
return developer_obj return developer_obj, False
return None return None, None
return developer_obj return developer_obj, True
def get_developer_obj_by_others(user_obj, udid): def get_developer_obj_by_others(user_obj, udid):
result = get_developer_user_by_app_udid(user_obj, udid) result, is_exist = get_developer_user_by_app_udid(user_obj, udid)
if result: if result:
return result return result
if not get_ios_developer_public_num(user_obj):
return None
receive_user_obj_list = IosDeveloperPublicPoolBill.objects.filter(to_user_id=user_obj).all() receive_user_obj_list = IosDeveloperPublicPoolBill.objects.filter(to_user_id=user_obj).all()
for receive_user_obj in receive_user_obj_list: for receive_user_obj in receive_user_obj_list:
result = get_developer_user_by_app_udid(receive_user_obj.user_id, udid) result, is_exist = get_developer_user_by_app_udid(receive_user_obj.user_id, udid)
if result is None: if result is None:
continue continue
else: else:
logger.warning(f"user receive_user_obj {receive_user_obj.user_id} developer to sign") f_count = get_ios_developer_public_num(user_obj)
return result if not is_exist and f_count > 0:
logger.warning(f"user receive_user_obj {receive_user_obj.user_id} developer to sign")
return result
if is_exist:
if f_count > 0:
return result
if f_count == 0 and udid in [x.get('udid__udid__udid') for x in
APPSuperSignUsedInfo.objects.filter(user_id=user_obj).values(
'udid__udid__udid').all()]:
return result
return None return None
@ -453,7 +457,9 @@ class IosUtils(object):
developer_info=BillDeveloperInfoSerializer( developer_info=BillDeveloperInfoSerializer(
self.developer_obj).data, self.developer_obj).data,
udid_info=BillUdidInfoSerializer(udid_obj).data, action=0, udid_info=BillUdidInfoSerializer(udid_obj).data, action=0,
number=1, udid_sync_info=udid_sync_info number=1, udid_sync_info=udid_sync_info,
remote_addr=client_ip,
udid=self.udid
) )
@staticmethod @staticmethod
@ -511,13 +517,7 @@ class IosUtils(object):
d_result['msg'] = msg d_result['msg'] = msg
return True, d_result return True, d_result
def sign(self, client_ip, sign_try_attempts=3): def check_sign_permission(self):
"""
:param client_ip:
:param sign_try_attempts:
:return: status, result
:des: 仅用于苹果设备发送设备udid签名使用
"""
d_result = {'code': 0, 'msg': 'success'} d_result = {'code': 0, 'msg': 'success'}
state, used_num = check_app_sign_limit(self.app_obj) state, used_num = check_app_sign_limit(self.app_obj)
if not state: if not state:
@ -537,7 +537,19 @@ class IosUtils(object):
d_result['msg'] = msg d_result['msg'] = msg
logger.error(d_result) logger.error(d_result)
return False, d_result return False, d_result
return True, d_result
def sign_ipa(self, client_ip, sign_try_attempts=3):
"""
:param client_ip:
:param sign_try_attempts:
:return: status, result
:des: 仅用于苹果设备发送设备udid签名使用
"""
status, msg = self.check_sign_permission()
if not status:
return status, msg
d_result = {'code': 0, 'msg': 'success'}
app_udid_obj = AppUDID.objects.filter(app_id=self.app_obj, udid__udid=self.udid, app_udid_obj = AppUDID.objects.filter(app_id=self.app_obj, udid__udid=self.udid,
udid__developerid=self.developer_obj).first() udid__developerid=self.developer_obj).first()
if app_udid_obj and app_udid_obj.is_download: if app_udid_obj and app_udid_obj.is_download:

@ -727,3 +727,47 @@ class BillUdidInfoSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.AppUDID model = models.AppUDID
fields = ["pk", "app_id", "udid", "product", "serial", "version", "imei", "iccid"] fields = ["pk", "app_id", "udid", "product", "serial", "version", "imei", "iccid"]
udid = serializers.SerializerMethodField()
def get_udid(self, obj):
return obj.udid.udid
class BillInfoSerializer(serializers.ModelSerializer):
class Meta:
model = models.IosDeveloperPublicPoolBill
exclude = ["user_id", "to_user_id", "developer_info", "app_info", "udid_sync_info"]
app_name = serializers.SerializerMethodField()
product = serializers.SerializerMethodField()
action = serializers.SerializerMethodField()
description = serializers.SerializerMethodField()
is_used = serializers.SerializerMethodField()
def get_is_used(self, obj):
if obj.udid_sync_info or obj.to_user_id:
return True
return False
def get_action(self, obj):
return get_choices_name_from_key(obj.action_choices, obj.action)
def get_app_name(self, obj):
if obj.app_info:
return obj.app_info.get('name')
elif obj.to_user_id:
return obj.user_id.first_name
def get_product(self, obj):
if obj.udid_info:
return obj.udid_info.get('product')
def get_description(self, obj):
if obj.udid_info:
return f"{self.get_app_name(obj)}-{self.get_action(obj)} -{obj.number} 设备数"
if obj.to_user_id:
if obj.to_user_id == self.context.get('user_obj'):
return f"{obj.user_id.first_name}-{self.get_action(obj)} +{obj.number} 设备数"
else:
return f"{obj.to_user_id.first_name} {self.get_action(obj)} -{obj.number} 设备数"

@ -75,20 +75,21 @@ def get_developer_devices(developer_obj_lists):
def get_captcha(): def get_captcha():
cptch_key = CaptchaStore.generate_key() captcha_key = CaptchaStore.generate_key()
cptch_image = captcha_image_url(cptch_key) captcha_image = captcha_image_url(captcha_key)
CaptchaStore.remove_expired() CaptchaStore.remove_expired()
local_storage = LocalStorage(**SERVER_DOMAIN.get("IOS_PMFILE_DOWNLOAD_DOMAIN")) local_storage = LocalStorage(**SERVER_DOMAIN.get("IOS_PMFILE_DOWNLOAD_DOMAIN"))
return {"cptch_image": "/".join([local_storage.get_base_url(), cptch_image.strip("/"), '']), "cptch_key": cptch_key, return {"captcha_image": "/".join([local_storage.get_base_url(), captcha_image.strip("/"), '']),
"captcha_key": captcha_key,
"length": CAPTCHA_LENGTH} "length": CAPTCHA_LENGTH}
def valid_captcha(cptch_key, code, username): def valid_captcha(captcha_key, code, username):
if username: if username:
challenge = CaptchaStore.objects.filter(hashkey=cptch_key).values("challenge").first() challenge = CaptchaStore.objects.filter(hashkey=captcha_key).values("challenge").first()
logger.info(f"cptch_key:{cptch_key} code:{code} challenge:{challenge}") logger.info(f"captcha_key:{captcha_key} code:{code} challenge:{challenge}")
if challenge: if challenge:
if cptch_key and code and code.strip(" ").lower() == challenge.get("challenge").lower(): if captcha_key and code and code.strip(" ").lower() == challenge.get("challenge").lower():
return True return True
return False return False

@ -224,7 +224,7 @@ class AppInfoView(APIView):
# res.msg = "超级签余额不足,无法开启" # res.msg = "超级签余额不足,无法开启"
# return Response(res.dict) # return Response(res.dict)
developer_count = AppIOSDeveloperInfo.objects.filter(user_id=request.user).count() developer_count = AppIOSDeveloperInfo.objects.filter(user_id=request.user).count()
if developer_count == 0 and not get_ios_developer_public_num(request.user): if developer_count == 0 and get_ios_developer_public_num(request.user) < 0:
logger.error(f"app_id:{app_id} can't open super_sign,owner has no ios developer") logger.error(f"app_id:{app_id} can't open super_sign,owner has no ios developer")
res.code = 1008 res.code = 1008
res.msg = "超级签余额不足,无法开启" res.msg = "超级签余额不足,无法开启"

@ -5,16 +5,17 @@
# date: 2020/3/4 # date: 2020/3/4
import logging import logging
from django.db.models import Q
from django.http.response import FileResponse from django.http.response import FileResponse
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from api.models import AppIOSDeveloperInfo, APPSuperSignUsedInfo, AppUDID from api.models import AppIOSDeveloperInfo, APPSuperSignUsedInfo, AppUDID, IosDeveloperPublicPoolBill
from api.utils.app.supersignutils import IosUtils from api.utils.app.supersignutils import IosUtils
from api.utils.auth import ExpiringTokenAuthentication, SuperSignPermission from api.utils.auth import ExpiringTokenAuthentication, SuperSignPermission
from api.utils.response import BaseResponse from api.utils.response import BaseResponse
from api.utils.serializer import DeveloperSerializer, SuperSignUsedSerializer, DeviceUDIDSerializer from api.utils.serializer import DeveloperSerializer, SuperSignUsedSerializer, DeviceUDIDSerializer, BillInfoSerializer
from api.utils.utils import get_developer_devices, get_choices_dict from api.utils.utils import get_developer_devices, get_choices_dict
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -306,3 +307,23 @@ class SuperSignCertView(APIView):
res.msg = str(result['err_info']) res.msg = str(result['err_info'])
return Response(res.dict) return Response(res.dict)
return Response(res.dict) return Response(res.dict)
class DeviceUsedBillView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
permission_classes = [SuperSignPermission, ]
def get(self, request):
res = BaseResponse()
udid = request.query_params.get("udid", None)
page_obj = PageNumber()
user_used_list = IosDeveloperPublicPoolBill.objects.filter(Q(to_user_id=request.user) | Q(user_id=request.user))
if udid:
user_used_list = user_used_list.filter(udid=udid)
app_page_serializer = page_obj.paginate_queryset(queryset=user_used_list.order_by("-created_time"),
request=request,
view=self)
app_serializer = BillInfoSerializer(app_page_serializer, many=True, context={'user_obj': request.user})
res.data = app_serializer.data
res.count = user_used_list.count()
return Response(res.dict)

Loading…
Cancel
Save