diff --git a/fir_client/src/components/apps/FirAppInfossupersign.vue b/fir_client/src/components/apps/FirAppInfossupersign.vue
index 79cf0e3..0e3065a 100644
--- a/fir_client/src/components/apps/FirAppInfossupersign.vue
+++ b/fir_client/src/components/apps/FirAppInfossupersign.vue
@@ -2,6 +2,15 @@
+
+
+
@@ -24,7 +33,12 @@
超级签名,iOS专用,需要配置好苹果开发者账户,方可开启
-
+
+ 配置专属苹果开发账户
+ 拥有
+ {{ currentapp.private_developer_number }} 个专属苹果开发者
+
+
@@ -91,9 +105,11 @@
+
+
diff --git a/fir_client/src/components/user/FirSuperSignBase.vue b/fir_client/src/components/user/FirSuperSignBase.vue
index f17ef50..b971b61 100644
--- a/fir_client/src/components/user/FirSuperSignBase.vue
+++ b/fir_client/src/components/user/FirSuperSignBase.vue
@@ -1,6 +1,14 @@
-
+
+
+
@@ -85,7 +93,7 @@
账户激活检测
-
+
保存
取消
@@ -178,12 +186,22 @@
+ placeholder="输入开发者ID"
+ style="width: 27%;margin-right: 10px;margin-bottom: 10px"/>
+
+
+
+
+
搜索
-
+
私有总设备量:{{ developer_used_info.all_usable_number }} 已经使用:【平台:{{
developer_used_info.all_use_number
}} 】【其他:{{ developer_used_info.other_used_sum }}】
@@ -208,11 +226,18 @@
+ width="200">
+
+
+ 开发者账户ID: {{ scope.row.issuer_id }}
+
+
开发者账户已使用设备数: {{ scope.row.developer_used_number }}
开发者账户可用设备数: {{ 100 - scope.row.developer_used_number }}
由于您设置可用设备数: {{ scope.row.usable_number }} ,所以现在可用设备数: {{
@@ -302,6 +327,46 @@
+
+
+
+
+ 签名了 {{ scope.row.app_used_number }} 个应用
+
+
+ {{ scope.row.app_used_number }}
+
+ {{ scope.row.app_used_number }}
+
+
+
+
+
+
+
+ 专属开发者被分配给了 {{ scope.row.app_private_number }} 个应用
+ 专属开发者一共分配了 {{ scope.row.app_private_usable_number }} 个设备名额
+ 专属开发者已经被专属应用使用了 {{ scope.row.app_private_used_number }} 个设备名额
+
+
+ 是
+
+ 否
+
+
+
+
{
+ callBack(data);
+ },
+ load,
+ true,
+ true
+ );
+}
+
/**应用举报 */
export function appReport(callBack, params, load = true) {
getData(
diff --git a/fir_client/vue.config.js b/fir_client/vue.config.js
index 3a2bcea..8345a2c 100644
--- a/fir_client/vue.config.js
+++ b/fir_client/vue.config.js
@@ -82,7 +82,7 @@ if (page) {
}
}
-const version='1.3.4';
+const version='1.3.6';
const pro_base_env = {
baseUrl: 'https://flyapps.cn',
diff --git a/fir_ser/api/migrations/0026_appledevelopertoappuse.py b/fir_ser/api/migrations/0026_appledevelopertoappuse.py
new file mode 100644
index 0000000..138e82b
--- /dev/null
+++ b/fir_ser/api/migrations/0026_appledevelopertoappuse.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.2.3 on 2021-12-13 16:43
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('api', '0025_delete_devicequeue'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='AppleDeveloperToAppUse',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('usable_number', models.IntegerField(default=100, verbose_name='可使用设备数')),
+ ('description', models.CharField(blank=True, default='', max_length=256, verbose_name='备注')),
+ ('created_time', models.DateTimeField(auto_now_add=True, verbose_name='添加时间')),
+ ('app_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.apps')),
+ ('developerid',
+ models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.appiosdeveloperinfo')),
+ ],
+ options={
+ 'verbose_name': '开发者专属于应用',
+ 'verbose_name_plural': '开发者专属于应用',
+ 'unique_together': {('app_id', 'developerid')},
+ },
+ ),
+ ]
diff --git a/fir_ser/api/models.py b/fir_ser/api/models.py
index 1d3a35a..a1ff987 100644
--- a/fir_ser/api/models.py
+++ b/fir_ser/api/models.py
@@ -599,3 +599,19 @@ class AppReportInfo(models.Model):
def __str__(self):
return "%s-%s" % (self.app_name, self.report_reason)
+
+
+class AppleDeveloperToAppUse(models.Model):
+ app_id = models.ForeignKey(to='Apps', on_delete=models.CASCADE)
+ developerid = models.ForeignKey(to='AppIOSDeveloperInfo', on_delete=models.CASCADE)
+ usable_number = models.IntegerField(verbose_name="可使用设备数", default=100)
+ description = models.CharField(verbose_name="备注", max_length=256, default='', blank=True)
+ created_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间")
+
+ class Meta:
+ verbose_name = '开发者专属于应用'
+ verbose_name_plural = "开发者专属于应用"
+ unique_together = ('app_id', 'developerid')
+
+ def __str__(self):
+ return "%s-%s" % (self.app_id.name, self.developerid.issuer_id)
diff --git a/fir_ser/api/urls.py b/fir_ser/api/urls.py
index 11d6947..9511bea 100644
--- a/fir_ser/api/urls.py
+++ b/fir_ser/api/urls.py
@@ -27,7 +27,7 @@ from api.views.receiveudids import IosUDIDView, TaskView
from api.views.report import ReportView
from api.views.storage import StorageView, CleanStorageView
from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView, SuperSignCertView, \
- DeviceUsedBillView, DeveloperDeviceView, DeviceUsedRankInfoView
+ DeviceUsedBillView, DeveloperDeviceView, DeviceUsedRankInfoView, AppleDeveloperBindAppsView
from api.views.thirdlogin import ValidWxChatToken, ThirdWxAccount
from api.views.uploads import AppAnalyseView, UploadView
@@ -64,6 +64,7 @@ urlpatterns = [
re_path("^supersign/cert$", SuperSignCertView.as_view()),
re_path("^supersign/bill$", DeviceUsedBillView.as_view()),
re_path("^supersign/rank$", DeviceUsedRankInfoView.as_view()),
+ re_path("^supersign/bind$", AppleDeveloperBindAppsView.as_view()),
re_path("^package_prices$", PriceView.as_view()),
re_path("^orders$", OrderView.as_view()),
re_path("^certification$", CertificationView.as_view()),
diff --git a/fir_ser/api/utils/app/supersignutils.py b/fir_ser/api/utils/app/supersignutils.py
index e61f245..b732ad9 100644
--- a/fir_ser/api/utils/app/supersignutils.py
+++ b/fir_ser/api/utils/app/supersignutils.py
@@ -16,7 +16,7 @@ from django.core.cache import cache
from django.db.models import Count
from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo, Apps, APPToDeveloper, \
- UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID, IosDeveloperPublicPoolBill, UserInfo
+ UDIDsyncDeveloper, DeveloperAppID, DeveloperDevicesID, IosDeveloperPublicPoolBill, UserInfo, AppleDeveloperToAppUse
from api.utils.app.iossignapi import ResignApp, AppDeveloperApiV2
from api.utils.baseutils import file_format_path, delete_app_profile_file, get_profile_full_path, format_apple_date, \
get_format_time, make_app_uuid, make_from_user_uuid
@@ -270,6 +270,31 @@ def run_function_by_lock(lock_key='', timeout=60 * 5):
return decorator
+def get_new_developer_by_app_obj(user_objs, app_obj, apple_to_app=False):
+ can_used_developer_pk_list = []
+ obj_base_filter = AppIOSDeveloperInfo.objects.filter(user_id__in=user_objs, is_actived=True, certid__isnull=False)
+ if apple_to_app:
+ # 存在指定开发者,则新设备优先注册到指定开发者
+ developer_obj_lists = obj_base_filter.filter(appledevelopertoappuse__app_id=app_obj)
+ else:
+ developer_obj_lists = obj_base_filter.exclude(appledevelopertoappuse__developerid__isnull=False)
+ developer_obj_lists = developer_obj_lists.distinct().order_by("created_time")
+ for developer_obj in developer_obj_lists:
+ # 通过开发者数限制进行过滤
+ used_number = get_developer_udided(developer_obj)[2] + get_developer_can_used_from_public_sign(
+ developer_obj.user_id)
+ if used_number < developer_obj.usable_number:
+ if apple_to_app:
+ apple_to_app_obj = AppleDeveloperToAppUse.objects.filter(app_id=app_obj,
+ developerid=developer_obj).first()
+ if apple_to_app_obj:
+ if used_number < apple_to_app_obj.usable_number:
+ can_used_developer_pk_list.append(developer_obj.pk)
+ else:
+ can_used_developer_pk_list.append(developer_obj.pk)
+ return can_used_developer_pk_list
+
+
def get_developer_user_by_app_udid(user_objs, udid, app_obj):
developer_udid_obj_list = UDIDsyncDeveloper.objects.filter(developerid__user_id__in=user_objs,
developerid__is_actived=True,
@@ -296,12 +321,11 @@ def get_developer_user_by_app_udid(user_objs, udid, app_obj):
developer_obj.user_id) < developer_obj.usable_number:
logger.info(f'app_obj:{app_obj} only and return')
return developer_obj, False
- can_used_developer_pk_list = []
- for developer_obj in AppIOSDeveloperInfo.objects.filter(user_id__in=user_objs, is_actived=True,
- certid__isnull=False).order_by("created_time"):
- if get_developer_udided(developer_obj)[2] + get_developer_can_used_from_public_sign(
- developer_obj.user_id) < developer_obj.usable_number:
- can_used_developer_pk_list.append(developer_obj.pk)
+
+ apple_to_app = AppleDeveloperToAppUse.objects.filter(app_id=app_obj).first()
+ can_used_developer_pk_list = get_new_developer_by_app_obj(user_objs, app_obj, apple_to_app)
+ if not can_used_developer_pk_list:
+ can_used_developer_pk_list = get_new_developer_by_app_obj(user_objs, app_obj)
# 查询开发者策略 按照最小注册设备数进行查找,这样可以分散,进而使应用趋向于一个开发者,为后期更新提供方便
if can_used_developer_pk_list:
diff --git a/fir_ser/api/utils/serializer.py b/fir_ser/api/utils/serializer.py
index 6b8a37a..fc651cf 100644
--- a/fir_ser/api/utils/serializer.py
+++ b/fir_ser/api/utils/serializer.py
@@ -1,6 +1,7 @@
import logging
import os
+from django.db.models import Sum
from rest_framework import serializers
from api import models
@@ -153,6 +154,11 @@ class AppsSerializer(serializers.ModelSerializer):
def get_preview_url(self, obj):
return get_redirect_server_domain(None, obj.user_id, get_app_domain_name(obj))
+ private_developer_number = serializers.SerializerMethodField()
+
+ def get_private_developer_number(self, obj):
+ return models.AppleDeveloperToAppUse.objects.filter(app_id=obj).count()
+
domain_name = serializers.SerializerMethodField()
def get_domain_name(self, obj):
@@ -450,6 +456,21 @@ class DeveloperSerializer(serializers.ModelSerializer):
developer_used_number = serializers.SerializerMethodField()
developer_used_other_number = serializers.SerializerMethodField()
use_number = serializers.SerializerMethodField()
+ app_used_number = serializers.SerializerMethodField()
+ is_disabled = serializers.SerializerMethodField()
+ app_private_number = serializers.SerializerMethodField()
+ app_private_used_number = serializers.SerializerMethodField()
+ app_usable_number = serializers.SerializerMethodField()
+ app_private_usable_number = serializers.SerializerMethodField()
+
+ def get_app_usable_number(self, obj):
+ app_id = self.context.get('app_id')
+ if app_id:
+ apple_to_app_obj = models.AppleDeveloperToAppUse.objects.filter(developerid=obj,
+ app_id__app_id=app_id).first()
+ if apple_to_app_obj:
+ return apple_to_app_obj.usable_number
+ return 0
def get_developer_used_number(self, obj):
return models.UDIDsyncDeveloper.objects.filter(developerid=obj).count()
@@ -457,9 +478,28 @@ class DeveloperSerializer(serializers.ModelSerializer):
def get_developer_used_other_number(self, obj):
return get_developer_udided(obj)[0]
+ def get_is_disabled(self, obj):
+ return bool(1 - obj.is_actived)
+
+ def get_app_private_number(self, obj):
+ return models.AppleDeveloperToAppUse.objects.filter(developerid=obj).count()
+
+ def get_app_private_usable_number(self, obj):
+ used_number = models.AppleDeveloperToAppUse.objects.filter(developerid=obj).values('usable_number').aggregate(
+ Sum('usable_number')).get('usable_number__sum')
+ if not used_number:
+ used_number = 0
+ return used_number
+
+ def get_app_private_used_number(self, obj):
+ return models.DeveloperDevicesID.objects.filter(developerid=obj, app_id__appledevelopertoappuse__developerid=obj).values('udid').distinct().count()
+
def get_use_number(self, obj):
return models.DeveloperDevicesID.objects.filter(developerid=obj).values('udid').distinct().count()
+ def get_app_used_number(self, obj):
+ return models.DeveloperAppID.objects.filter(developerid=obj).count()
+
class AdminDeveloperSerializer(DeveloperSerializer):
class Meta:
@@ -786,3 +826,37 @@ class AdminAppReportSerializer(AppReportSerializer):
def get_status_choices(self, obj):
return get_choices_dict(obj.status_choices)
+
+
+class AppleDeveloperToAppUseSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = models.AppleDeveloperToAppUse
+ # exclude = ["user_id", "to_user_id", "developer_info", "app_info", "udid_sync_info", "app_id"]
+ fields = ["issuer_id", "app_id", "created_time", "description", "usable_number"]
+
+ issuer_id = serializers.CharField(source="developerid.issuer_id")
+ app_id = serializers.CharField(source="app_id.app_id")
+
+
+class AppleDeveloperToAppUseAppsSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = models.Apps
+ fields = ["app_id", "name", "short", "bundle_id", "description", "app_usable_number", "app_used_number"]
+
+ app_usable_number = serializers.SerializerMethodField()
+ app_used_number = serializers.SerializerMethodField()
+
+ def get_app_usable_number(self, obj):
+ issuer_id = self.context.get('issuer_id')
+ if issuer_id:
+ apple_to_app_obj = models.AppleDeveloperToAppUse.objects.filter(developerid__issuer_id=issuer_id,
+ app_id=obj).first()
+ if apple_to_app_obj:
+ return apple_to_app_obj.usable_number
+ return 0
+
+ def get_app_used_number(self, obj):
+ issuer_id = self.context.get('issuer_id')
+ if issuer_id:
+ return models.DeveloperDevicesID.objects.filter(app_id=obj,developerid__issuer_id=issuer_id).count()
+ return 0
\ No newline at end of file
diff --git a/fir_ser/api/views/supersign.py b/fir_ser/api/views/supersign.py
index a230749..43e366e 100644
--- a/fir_ser/api/views/supersign.py
+++ b/fir_ser/api/views/supersign.py
@@ -13,13 +13,13 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import AppIOSDeveloperInfo, APPSuperSignUsedInfo, AppUDID, IosDeveloperPublicPoolBill, \
- UDIDsyncDeveloper
+ UDIDsyncDeveloper, AppleDeveloperToAppUse, Apps
from api.utils.app.supersignutils import IosUtils
from api.utils.auth import ExpiringTokenAuthentication, SuperSignPermission
from api.utils.modelutils import get_user_public_used_sign_num, get_user_public_sign_num
from api.utils.response import BaseResponse
from api.utils.serializer import DeveloperSerializer, SuperSignUsedSerializer, DeviceUDIDSerializer, BillInfoSerializer, \
- DeveloperDeviceSerializer
+ DeveloperDeviceSerializer, AppleDeveloperToAppUseSerializer, AppleDeveloperToAppUseAppsSerializer
from api.utils.storage.caches import CleanSignDataState
from api.utils.utils import get_developer_devices, get_choices_dict
@@ -41,17 +41,26 @@ class DeveloperView(APIView):
res = BaseResponse()
- app_id = request.query_params.get("appid", None)
+ issuer_id = request.query_params.get("issuer_id", '')
+ app_id = request.query_params.get("app_id", '')
+ developer_choice = request.query_params.get("developer_choice", None)
developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=request.user)
+
+ if developer_choice and developer_choice in ['private', 'public']:
+ if developer_choice == 'public':
+ developer_obj = developer_obj.exclude(appledevelopertoappuse__developerid__isnull=False)
+ else:
+ developer_obj = developer_obj.filter(appledevelopertoappuse__developerid__isnull=False)
+ developer_obj = developer_obj.distinct()
res.use_num = get_developer_devices(developer_obj)
- if app_id:
- developer_obj = developer_obj.filter(issuer_id=app_id)
+ if issuer_id:
+ developer_obj = developer_obj.filter(issuer_id=issuer_id)
page_obj = PageNumber()
app_page_serializer = page_obj.paginate_queryset(queryset=developer_obj.order_by("-updated_time"),
request=request,
view=self)
- developer_serializer = DeveloperSerializer(app_page_serializer, many=True, )
+ developer_serializer = DeveloperSerializer(app_page_serializer, many=True, context={'app_id': app_id})
res.data = developer_serializer.data
res.count = developer_obj.count()
@@ -223,14 +232,14 @@ class DeveloperView(APIView):
def base_super_sign_used_info(request):
udid = request.query_params.get("udid", None)
bundle_id = request.query_params.get("bundleid", None)
- developer_id = request.query_params.get("appid", None)
+ issuer_id = request.query_params.get("issuer_id", None)
mine = True
super_sign_used_objs = APPSuperSignUsedInfo.objects.filter(developerid__user_id=request.user, )
if not super_sign_used_objs:
super_sign_used_objs = APPSuperSignUsedInfo.objects.filter(user_id=request.user, )
mine = False
- if developer_id:
- super_sign_used_objs = super_sign_used_objs.filter(developerid__issuer_id=developer_id)
+ if issuer_id:
+ super_sign_used_objs = super_sign_used_objs.filter(developerid__issuer_id=issuer_id)
if udid:
super_sign_used_objs = super_sign_used_objs.filter(udid__udid__udid=udid)
if bundle_id:
@@ -299,10 +308,10 @@ class DeveloperDeviceView(APIView):
res = BaseResponse()
udid = request.query_params.get("udid", None)
- developer_id = request.query_params.get("appid", None)
+ issuer_id = request.query_params.get("issuer_id", None)
super_sign_used_objs = UDIDsyncDeveloper.objects.filter(developerid__user_id=request.user, )
- if developer_id:
- super_sign_used_objs = super_sign_used_objs.filter(developerid__issuer_id=developer_id)
+ if issuer_id:
+ super_sign_used_objs = super_sign_used_objs.filter(developerid__issuer_id=issuer_id)
if udid:
super_sign_used_objs = super_sign_used_objs.filter(udid=udid)
page_obj = PageNumber()
@@ -318,7 +327,7 @@ class DeveloperDeviceView(APIView):
res = BaseResponse()
pk = request.query_params.get("id", None)
app_id = request.query_params.get("aid", None)
- app_udid_obj = AppUDID.objects.filter(pk=pk)
+ app_udid_obj = AppUDID.objects.filter(pk=pk, app_id__user_id=request.user)
if app_udid_obj:
super_sign_used_obj = APPSuperSignUsedInfo.objects.filter(udid=app_udid_obj.first()).first()
if super_sign_used_obj and super_sign_used_obj.developerid.user_id.pk == request.user.pk:
@@ -430,7 +439,8 @@ class DeviceUsedRankInfoView(APIView):
app_used_sign_objs = APPSuperSignUsedInfo.objects.filter(user_id=request.user)
if appnamesearch:
app_used_sign_objs = app_used_sign_objs.filter(
- Q(app_id__name=appnamesearch) | Q(app_id__bundle_id=appnamesearch))
+ Q(app_id__name=appnamesearch) | Q(app_id__bundle_id=appnamesearch) | Q(
+ developerid__issuer_id=appnamesearch))
if end_time and start_time:
try:
start_time = datetime.date.fromtimestamp(int(start_time) / 1000)
@@ -455,3 +465,93 @@ class DeviceUsedRankInfoView(APIView):
new_app_used_sign_infos.append(new_app_used_info)
res.data = new_app_used_sign_infos
return Response(res.dict)
+
+
+class AppleDeveloperBindAppsView(APIView):
+ authentication_classes = [ExpiringTokenAuthentication, ]
+ permission_classes = [SuperSignPermission, ]
+
+ def get(self, request):
+ res = BaseResponse()
+ act = request.query_params.get("act", '')
+ issuer_id = request.query_params.get("issuer_id", '')
+ app_id = request.query_params.get("app_id", '')
+ if act == 'apps':
+ apps_obj_list = Apps.objects.filter(user_id=request.user, type=1).all()
+ app_serializer = AppleDeveloperToAppUseAppsSerializer(apps_obj_list, many=True,
+ context={'issuer_id': issuer_id})
+ else:
+ apple_to_app_obj = AppleDeveloperToAppUse.objects.filter(app_id__user_id=request.user)
+ if issuer_id:
+ apple_to_app_obj = apple_to_app_obj.filter(developerid__issuer_id=issuer_id)
+ if app_id:
+ apple_to_app_obj = apple_to_app_obj.filter(app_id__app_id=app_id)
+
+ app_serializer = AppleDeveloperToAppUseSerializer(apple_to_app_obj.all(), many=True)
+ res.data = app_serializer.data
+ return Response(res.dict)
+
+ def post(self, request):
+ res = BaseResponse()
+ issuer_id = request.data.get('issuer_id', '')
+ app_id = request.data.get('app_id', '')
+ choices_data = request.data.get('choices_data', [])
+ logger.info(f"change apple to app data:{request.data}")
+ many_obj = []
+ if app_id:
+ app_obj = Apps.objects.filter(app_id=app_id, type=1, user_id=request.user).first()
+
+ issuer_id_list = [apple_to_app['developerid__issuer_id'] for apple_to_app in
+ AppleDeveloperToAppUse.objects.filter(app_id=app_obj).values(
+ 'developerid__issuer_id').all().distinct()]
+
+ add_issuer_ids = list(set(choices_data) - set(issuer_id_list))
+ remove_issuer_ids = list(set(issuer_id_list) - set(choices_data))
+
+ for item in add_issuer_ids:
+ developer_obj = AppIOSDeveloperInfo.objects.filter(issuer_id=item, user_id=request.user).first()
+ if developer_obj:
+ many_obj.append(AppleDeveloperToAppUse(developerid=developer_obj, app_id=app_obj))
+ AppleDeveloperToAppUse.objects.filter(developerid__issuer_id__in=remove_issuer_ids, app_id=app_obj).delete()
+
+ if issuer_id:
+ developer_obj = AppIOSDeveloperInfo.objects.filter(issuer_id=issuer_id, user_id=request.user).first()
+ app_id_list = [apple_to_app['app_id__app_id'] for apple_to_app in
+ AppleDeveloperToAppUse.objects.filter(developerid=developer_obj).values(
+ 'app_id__app_id').all().distinct()]
+
+ add_app_ids = list(set(choices_data) - set(app_id_list))
+ remove_app_ids = list(set(app_id_list) - set(choices_data))
+
+ for item in add_app_ids:
+ app_obj = Apps.objects.filter(app_id=item, type=1, user_id=request.user).first()
+ if app_obj:
+ many_obj.append(AppleDeveloperToAppUse(developerid=developer_obj, app_id=app_obj))
+ AppleDeveloperToAppUse.objects.filter(developerid=developer_obj, app_id__app_id__in=remove_app_ids,
+ app_id__user_id=request.user).delete()
+
+ if many_obj:
+ AppleDeveloperToAppUse.objects.bulk_create(many_obj)
+ return Response(res.dict)
+
+ def put(self, request):
+ res = BaseResponse()
+ issuer_id = request.data.get('issuer_id', '')
+ app_id = request.data.get('app_id', '')
+ infos = request.data.get('infos', {})
+ logger.info(f"change apple to app data:{request.data}")
+ if issuer_id and not app_id:
+ app_id = infos.get('app_id', '')
+ if app_id and not issuer_id:
+ issuer_id = infos.get('issuer_id', '')
+ if app_id and issuer_id:
+ try:
+ app_usable_number = int(infos.get('app_usable_number', 100))
+ if 0 < app_usable_number < 101:
+ AppleDeveloperToAppUse.objects.filter(developerid__issuer_id=issuer_id,
+ app_id__app_id=app_id, app_id__user_id=request.user).update(
+ usable_number=int(app_usable_number))
+
+ except Exception as e:
+ logger.error(f'update app developer used failed infos:{infos} Exception:{e}')
+ return Response(res.dict)