diff --git a/fir_client/src/components/apps/FirAppInfossupersign.vue b/fir_client/src/components/apps/FirAppInfossupersign.vue
index 6c35f4a..a051fee 100644
--- a/fir_client/src/components/apps/FirAppInfossupersign.vue
+++ b/fir_client/src/components/apps/FirAppInfossupersign.vue
@@ -19,7 +19,7 @@
                     
                 
                 清理开发者账户脏数据
+                           style="margin-left: 20px" size="small" type="info" plain>清理该应用脏数据
                 
                 超级签名,iOS专用,需要配置好苹果开发者账户,方可开启
 
diff --git a/fir_client/src/components/user/FirSuperSignBase.vue b/fir_client/src/components/user/FirSuperSignBase.vue
index 0b1c4da..6fc9599 100644
--- a/fir_client/src/components/user/FirSuperSignBase.vue
+++ b/fir_client/src/components/user/FirSuperSignBase.vue
@@ -341,6 +341,11 @@
                             label="开发者ID"
                             width="200">
                     
+                    
+                    
                     
                     
+                    
+                    
                     '''
 
 
-def get_post_udid_url(request, short):
-    server_domain = get_http_server_domain(request)
-    path_info_lists = [server_domain, "udid", short]
-    udid_url = "/".join(path_info_lists)
-    return udid_url
-
-
 def get_auth_form_developer(developer_obj):
     if developer_obj.issuer_id:
         auth = {
@@ -201,28 +194,14 @@ def err_callback(func, *args, **kwargs):
     return wrapper
 
 
-def get_server_domain_from_request(request, server_domain):
-    if not server_domain or not server_domain.startswith("http"):
-        http_host = request.META.get('HTTP_HOST')
-        server_protocol = request.META.get('SERVER_PROTOCOL')
-        protocol = 'https'
-        if server_protocol == 'HTTP/1.1':
-            protocol = 'http'
-        server_domain = "%s://%s" % (protocol, http_host)
-    return server_domain
-
-
-def get_http_server_domain(request):
-    server_domain = SERVER_DOMAIN.get('POST_UDID_DOMAIN', None)
-    return get_server_domain_from_request(request, server_domain)
-
-
 def get_ios_developer_public_num(user_obj):
-    ios_developer_base_obj = IosDeveloperPublicPoolBill.objects.filter(user_id=user_obj)
-    add_number = ios_developer_base_obj.filter(action=1).aggregate(number=Sum('number'))
-    used_number = ios_developer_base_obj.filter(action=0).aggregate(number=Sum('number'))
+    add_number = IosDeveloperPublicPoolBill.objects.filter(to_user_id=user_obj, action__in=[1, 2]).aggregate(
+        number=Sum('number'))
+    used_number = IosDeveloperPublicPoolBill.objects.filter(user_id=user_obj, action=0).aggregate(number=Sum('number'))
     if add_number:
         add_number = add_number.get("number", 0)
+        if not add_number:
+            return False
         used_number = used_number.get("number", 0)
         if not used_number:
             used_number = 0
@@ -231,29 +210,7 @@ def get_ios_developer_public_num(user_obj):
     return False
 
 
-def get_redirect_server_domain(request, user_obj=None, app_domain_name=None):
-    is_https = False
-    if user_obj:
-        if app_domain_name and len(app_domain_name) > 3:
-            domain_name = app_domain_name
-        else:
-            domain_name = get_user_domain_name(user_obj)
-            if not domain_name:
-                is_https, domain_name = get_user_default_domain_name(user_obj.default_domain_name)
-    elif app_domain_name and len(app_domain_name) > 3:
-        domain_name = app_domain_name
-    else:
-        is_https, domain_name = get_user_default_domain_name(get_min_default_domain_cname_obj(True))
-    protocol = 'http'
-    if is_https:
-        protocol = 'https'
-    server_domain = "%s://%s" % (protocol, domain_name)
-    return get_server_domain_from_request(request, server_domain)
-
-
-
-def get_developer_user_by_app_udid(user_obj,udid):
-
+def get_developer_user_by_app_udid(user_obj, udid):
     use_device_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=udid,
                                                          user_id=user_obj, developerid__is_actived=True,
                                                          developerid__certid__isnull=False).first()
@@ -274,24 +231,24 @@ def get_developer_user_by_app_udid(user_obj,udid):
             return None
     return developer_obj
 
+
 def get_developer_obj_by_others(user_obj, udid):
     result = get_developer_user_by_app_udid(user_obj, udid)
     if result:
         return result
     if not get_ios_developer_public_num(user_obj):
         return None
-    admin_user_obj_list = UserInfo.objects.filter(is_active=True, role=3, is_staff=True).all()
-    for admin_user_obj in admin_user_obj_list:
-        result = get_developer_user_by_app_udid(admin_user_obj,udid)
+    receive_user_obj_list = IosDeveloperPublicPoolBill.objects.filter(to_user_id=user_obj).all()
+    for receive_user_obj in receive_user_obj_list:
+        result = get_developer_user_by_app_udid(receive_user_obj.user_id, udid)
         if result is None:
             continue
         else:
-            logger.warning(f"user admin {admin_user_obj} developer to sign")
+            logger.warning(f"user receive_user_obj {receive_user_obj.user_id} developer to sign")
             return result
     return None
 
 
-
 class IosUtils(object):
     def __init__(self, udid_info, user_obj, app_obj=None):
         self.developer_obj = None
@@ -468,7 +425,7 @@ class IosUtils(object):
         logger.info(f"update sign file end, now upload {storage_obj.storage} {random_file_name}.ipa file")
         return storage_obj.upload_file(os.path.join(MEDIA_ROOT, random_file_name + ".ipa"))
 
-    def update_developer_used_data(self):
+    def update_developer_used_data(self, client_ip):
         udid_obj = AppUDID.objects.filter(app_id=self.app_obj, udid=self.udid_info.get('udid')).first()
         udid_obj.is_download = True
         udid_obj.save(update_fields=['is_download'])
@@ -476,12 +433,15 @@ class IosUtils(object):
                                                       user_id=self.user_obj,
                                                       developerid=self.developer_obj,
                                                       udid=udid_obj)
-        IosDeveloperPublicPoolBill.objects.update_or_create(app_id=self.app_obj,
-                                                      user_id=self.user_obj,
-                                                      developerid=self.developer_obj,
-                                                      udid=udid_obj,action=0,number=1)
+        IosDeveloperPublicPoolBill.objects.update_or_create(user_id=self.user_obj,
+                                                            app_info=BillAppInfoSerializer(self.app_obj).data,
+                                                            developer_info=BillDeveloperInfoSerializer(
+                                                                self.developer_obj).data,
+                                                            udid_info=BillUdidInfoSerializer(udid_obj).data, action=0,
+                                                            number=1)
+
     @staticmethod
-    def update_sign_data(user_obj, app_obj, developer_obj,random_file_name, release_obj,udid):
+    def update_sign_data(user_obj, app_obj, developer_obj, random_file_name, release_obj, udid):
         # 更新新签名的ipa包
         if IosUtils.update_sign_file_name(user_obj, app_obj, developer_obj, release_obj,
                                           random_file_name):
@@ -502,7 +462,8 @@ class IosUtils(object):
             logger.info(f"app_id {app_obj} download profile success. time:{start_time - d_time}")
             random_file_name = make_from_user_uuid(developer_obj.user_id)
             release_obj = AppReleaseInfo.objects.filter(app_id=app_obj, is_master=True).first()
-            status, e_result = IosUtils.exec_sign(developer_obj.user_id, app_obj, developer_obj, random_file_name, release_obj)
+            status, e_result = IosUtils.exec_sign(developer_obj.user_id, app_obj, developer_obj, random_file_name,
+                                                  release_obj)
             if status:
                 s_time1 = time.time()
                 logger.info(f"app_id {app_obj} exec sign ipa success. time:{s_time1 - start_time}")
@@ -513,7 +474,8 @@ class IosUtils(object):
                         d_result['msg'] = '数据更新失败,请稍后重试'
                         return status, d_result
                 else:
-                    if not IosUtils.update_sign_data(user_obj, app_obj, developer_obj,random_file_name, release_obj,udid):
+                    if not IosUtils.update_sign_data(user_obj, app_obj, developer_obj, random_file_name, release_obj,
+                                                     udid):
                         d_result['code'] = 1004
                         d_result['msg'] = '数据更新失败,请稍后重试'
                         return status, d_result
@@ -532,7 +494,7 @@ class IosUtils(object):
         d_result['msg'] = msg
         return True, d_result
 
-    def sign(self, sign_try_attempts=3):
+    def sign(self, client_ip, sign_try_attempts=3):
         """
         :param sign_try_attempts:
         :return:  status, result
@@ -571,7 +533,8 @@ class IosUtils(object):
                 with cache.lock("%s_%s_%s" % ('run_sign', self.app_obj.app_id, self.developer_obj.issuer_id),
                                 timeout=60 * 10):
                     logger.info("start run_sign ...")
-                    return IosUtils.run_sign(self.user_obj, self.app_obj, self.developer_obj, 1, self.udid_info.get('udid'), time.time(),
+                    return IosUtils.run_sign(self.user_obj, self.app_obj, self.developer_obj, 1,
+                                             self.udid_info.get('udid'), time.time(),
                                              None)
 
         logger.info("udid %s not exists app_id %s ,need sign" % (self.udid_info.get('udid'), self.app_obj))
@@ -629,7 +592,7 @@ class IosUtils(object):
                                                           developerid=self.developer_obj,
                                                           app_id=self.app_obj)
 
-            self.update_developer_used_data()
+            self.update_developer_used_data(client_ip)
 
         if not self.developer_obj:
             d_result['code'] = 1005
@@ -638,7 +601,8 @@ class IosUtils(object):
             return False, d_result
         with cache.lock("%s_%s_%s" % ('run_sign', self.app_obj.app_id, self.developer_obj.issuer_id), timeout=60 * 10):
             logger.info("start run_sign ...")
-            return IosUtils.run_sign(self.user_obj, self.app_obj, self.developer_obj, download_flag, self.udid_info.get('udid'), start_time,
+            return IosUtils.run_sign(self.user_obj, self.app_obj, self.developer_obj, download_flag,
+                                     self.udid_info.get('udid'), start_time,
                                      result)
 
     @staticmethod
@@ -689,6 +653,10 @@ class IosUtils(object):
             IosUtils.do_disable_device(developer_obj, udid_lists, udid_obj, auth)
             SuperSignUsed_obj.delete()
 
+            app_udid_obj = UDIDsyncDeveloper.objects.filter(developerid=developer_obj,
+                                                            udid=udid_obj.udid).first()
+            DeveloperDevicesID.objects.filter(udid=app_udid_obj, developerid=developer_obj, app_id=app_obj).delete()
+
     @staticmethod
     def clean_app_by_user_obj(app_obj):
         """
@@ -701,7 +669,7 @@ class IosUtils(object):
 
         for developer_id in developer_id_lists:
             developer_obj = AppIOSDeveloperInfo.objects.filter(pk=developer_id[0]).first()
-            if developer_obj:
+            if developer_obj and developer_obj.user_id == app_obj.user_id:
                 IosUtils.clean_app_by_developer_obj(app_obj, developer_obj)
                 delete_app_to_dev_and_file(developer_obj, app_obj.id)
                 IosUtils.clean_udid_by_app_obj(app_obj, developer_obj)
diff --git a/fir_ser/api/utils/baseutils.py b/fir_ser/api/utils/baseutils.py
index b1957ab..3c22219 100644
--- a/fir_ser/api/utils/baseutils.py
+++ b/fir_ser/api/utils/baseutils.py
@@ -6,27 +6,38 @@
 
 import os, re, time
 
-from django.db.models import Count
 import datetime
-import random
 from django.utils import timezone
-from fir_ser.settings import SUPER_SIGN_ROOT
-from api.models import AppReleaseInfo, UserDomainInfo, DomainCnameInfo, UserAdDisplayInfo
-from api.utils.app.randomstrings import make_app_uuid
+
+from fir_ser.settings import SUPER_SIGN_ROOT, SERVER_DOMAIN
 from django.core.validators import validate_email
 from django.core.exceptions import ValidationError
 import logging
 from dns.resolver import Resolver
+import uuid
 
 logger = logging.getLogger(__name__)
 
 
-def get_app_d_count_by_app_id(app_id):
-    d_count = 1
-    binary_size = AppReleaseInfo.objects.filter(is_master=True, app_id__app_id=app_id).values('binary_size').first()
-    if binary_size and binary_size.get('binary_size', 0) > 0:
-        d_count += binary_size.get('binary_size') // 1024 // 1024 // 100
-    return d_count
+def make_from_user_uuid(userinfo):
+    user_id = userinfo.uid
+    random_str = uuid.uuid1().__str__().split("-")[0:-1]
+    user_ran_str = uuid.uuid5(uuid.NAMESPACE_DNS, user_id).__str__().split("-")
+    user_ran_str.extend(random_str)
+    new_str = "".join(user_ran_str)
+    return new_str
+
+
+def make_app_uuid(userinfo, bundleid):
+    user_id = userinfo.uid
+    app_uuid = uuid.uuid5(uuid.NAMESPACE_DNS, "%s" % (user_id + bundleid)).__str__().split("-")
+    fapp_uuid = "".join(app_uuid)
+    return fapp_uuid
+
+
+def make_random_uuid():
+    random_str = uuid.uuid1().__str__().split("-")
+    return "".join(random_str)
 
 
 def file_format_path(user_obj, auth=None):
@@ -173,31 +184,32 @@ def get_cname_from_domain(domain):
         return str(None)
 
 
-def get_user_domain_name(obj, domain_type=1):
-    domain_name = UserDomainInfo.objects.filter(user_id=obj, is_enable=True, app_id=None,
-                                                domain_type=domain_type).values_list('domain_name').first()
-    if domain_name:
-        return domain_name[0]
-    return ''
-
-
-def get_app_domain_name(obj):
-    domain_name = UserDomainInfo.objects.filter(app_id=obj, is_enable=True, domain_type=2).values_list(
-        'domain_name').first()
-    if domain_name:
-        return domain_name[0]
-    return ''
-
-
 def get_user_default_domain_name(domain_cname_obj):
     if domain_cname_obj:
         return domain_cname_obj.is_https, domain_cname_obj.domain_record
     return None, None
 
 
-def get_min_default_domain_cname_obj(is_system=True):
-    return min(DomainCnameInfo.objects.annotate(Count('userinfo')).filter(is_enable=True, is_system=is_system),
-               key=lambda x: x.userinfo__count)
+def get_server_domain_from_request(request, server_domain):
+    if not server_domain or not server_domain.startswith("http"):
+        http_host = request.META.get('HTTP_HOST')
+        server_protocol = request.META.get('SERVER_PROTOCOL')
+        protocol = 'https'
+        if server_protocol == 'HTTP/1.1':
+            protocol = 'http'
+        server_domain = "%s://%s" % (protocol, http_host)
+    return server_domain
+
+
+def get_http_server_domain(request):
+    server_domain = SERVER_DOMAIN.get('POST_UDID_DOMAIN', None)
+    return get_server_domain_from_request(request, server_domain)
+
+
+def get_post_udid_url(request, short):
+    server_domain = get_http_server_domain(request)
+    path_info_lists = [server_domain, "udid", short]
+    return "/".join(path_info_lists)
 
 
 def format_apple_date(s_date):
@@ -223,35 +235,6 @@ def check_app_password(app_password, password):
     return True
 
 
-def get_filename_form_file(filename):
-    file_id_list = filename.split('.')
-    if file_id_list[-1] in ['ipa', 'apk']:
-        app_release_obj = AppReleaseInfo.objects.filter(release_id='.'.join(file_id_list[0:-1])).first()
-        if app_release_obj:
-            app_obj = app_release_obj.app_id
-            if app_obj.type == 0:
-                f_type = '.apk'
-            else:
-                f_type = '.ipa'
-            return f"{app_obj.name}-{app_release_obj.app_version}-{app_obj.short}{f_type}"
-    return filename
-
-
-def check_app_domain_name_access(app_obj, access_domain_name, user_obj, extra_domain=None):
-    if app_obj and access_domain_name:
-        domain_list = []
-        if extra_domain:
-            domain_list.append(extra_domain)
-        app_domain_name = get_app_domain_name(app_obj)
-        if app_domain_name: domain_list.append(app_domain_name)
-        user_domain_name = get_user_domain_name(user_obj)
-        if user_domain_name: domain_list.append(user_domain_name)
-        user_qr_domain_name = get_user_domain_name(user_obj, 0)
-        if user_qr_domain_name: domain_list.append(user_qr_domain_name)
-        if access_domain_name in domain_list:
-            return True
-
-
 def get_real_ip_address(request):
     if request.META.get('HTTP_X_FORWARDED_FOR', None):
         return request.META.get('HTTP_X_FORWARDED_FOR')
@@ -261,21 +244,7 @@ def get_real_ip_address(request):
 
 def get_origin_domain_name(request):
     meta = request.META
-    return meta.get('HTTP_ORIGIN', meta.get('HTTP_REFERER', 'http://xxx/xxx')).split('//')[-1].split('/')[0]
-
-
-def ad_random_weight(user_obj):
-    ad_info_list = UserAdDisplayInfo.objects.filter(user_id=user_obj, is_enable=True).order_by('-created_time')
-    total = sum([ad_info.weight for ad_info in ad_info_list])  # 权重求和
-    ra = random.uniform(0, total)  # 在0与权重和之前获取一个随机数
-    curr_sum = 0
-    ret = ad_info_list.first()
-    for ad_info in ad_info_list:
-        curr_sum += ad_info.weight  # 在遍历中,累加当前权重值
-        if ra <= curr_sum:  # 当随机数<=当前权重和时,返回权重key
-            ret = ad_info
-            break
-    return ret
+    return request.META.get('HTTP_ORIGIN', meta.get('HTTP_REFERER', 'http://xxx/xxx')).split('//')[-1].split('/')[0]
 
 
 def format_get_uri(domain, short, data):
diff --git a/fir_ser/api/utils/modelutils.py b/fir_ser/api/utils/modelutils.py
new file mode 100644
index 0000000..eb3a0d4
--- /dev/null
+++ b/fir_ser/api/utils/modelutils.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+# project: 4月 
+# author: NinEveN
+# date: 2021/4/16
+
+
+from django.db.models import Count
+import random
+from api.models import AppReleaseInfo, UserDomainInfo, DomainCnameInfo, UserAdDisplayInfo, RemoteClientInfo
+import logging
+from urllib.parse import urljoin
+
+from api.utils.baseutils import get_server_domain_from_request, get_user_default_domain_name, get_real_ip_address, \
+    get_origin_domain_name
+
+logger = logging.getLogger(__name__)
+
+
+def get_app_d_count_by_app_id(app_id):
+    d_count = 1
+    binary_size = AppReleaseInfo.objects.filter(is_master=True, app_id__app_id=app_id).values('binary_size').first()
+    if binary_size and binary_size.get('binary_size', 0) > 0:
+        d_count += binary_size.get('binary_size') // 1024 // 1024 // 100
+    return d_count
+
+
+def get_user_domain_name(obj, domain_type=1):
+    domain_name = UserDomainInfo.objects.filter(user_id=obj, is_enable=True, app_id=None,
+                                                domain_type=domain_type).values_list('domain_name').first()
+    if domain_name:
+        return domain_name[0]
+    return ''
+
+
+def get_app_domain_name(obj):
+    domain_name = UserDomainInfo.objects.filter(app_id=obj, is_enable=True, domain_type=2).values_list(
+        'domain_name').first()
+    if domain_name:
+        return domain_name[0]
+    return ''
+
+
+def get_min_default_domain_cname_obj(is_system=True):
+    return min(DomainCnameInfo.objects.annotate(Count('userinfo')).filter(is_enable=True, is_system=is_system),
+               key=lambda x: x.userinfo__count)
+
+
+def get_filename_form_file(filename):
+    file_id_list = filename.split('.')
+    if file_id_list[-1] in ['ipa', 'apk']:
+        app_release_obj = AppReleaseInfo.objects.filter(release_id='.'.join(file_id_list[0:-1])).first()
+        if app_release_obj:
+            app_obj = app_release_obj.app_id
+            if app_obj.type == 0:
+                f_type = '.apk'
+            else:
+                f_type = '.ipa'
+            return f"{app_obj.name}-{app_release_obj.app_version}-{app_obj.short}{f_type}"
+    return filename
+
+
+def ad_random_weight(user_obj):
+    ad_info_list = UserAdDisplayInfo.objects.filter(user_id=user_obj, is_enable=True).order_by('-created_time')
+    total = sum([ad_info.weight for ad_info in ad_info_list])  # 权重求和
+    ra = random.uniform(0, total)  # 在0与权重和之前获取一个随机数
+    curr_sum = 0
+    ret = ad_info_list.first()
+    for ad_info in ad_info_list:
+        curr_sum += ad_info.weight  # 在遍历中,累加当前权重值
+        if ra <= curr_sum:  # 当随机数<=当前权重和时,返回权重key
+            ret = ad_info
+            break
+    return ret
+
+
+def add_remote_info_from_request(request, description):
+    meta_info = request.META
+    remote_info = {
+        'user_agent': meta_info.get('HTTP_USER_AGENT'),
+        'remote_addr': get_real_ip_address(request),
+        'method': meta_info.get('REQUEST_METHOD'),
+        'uri_info': urljoin(meta_info.get('PATH_INFO'), meta_info.get('QUERY_STRING')),
+        'a_domain': get_origin_domain_name(request),
+        'description': description
+    }
+    RemoteClientInfo.objects.create(**remote_info)
+
+
+def get_redirect_server_domain(request, user_obj=None, app_domain_name=None):
+    is_https = False
+    if user_obj:
+        if app_domain_name and len(app_domain_name) > 3:
+            domain_name = app_domain_name
+        else:
+            domain_name = get_user_domain_name(user_obj)
+            if not domain_name:
+                is_https, domain_name = get_user_default_domain_name(user_obj.default_domain_name)
+    elif app_domain_name and len(app_domain_name) > 3:
+        domain_name = app_domain_name
+    else:
+        is_https, domain_name = get_user_default_domain_name(get_min_default_domain_cname_obj(True))
+    protocol = 'http'
+    if is_https:
+        protocol = 'https'
+    server_domain = "%s://%s" % (protocol, domain_name)
+    return get_server_domain_from_request(request, server_domain)
+
+
+def check_app_domain_name_access(app_obj, access_domain_name, user_obj, extra_domain=None):
+    if app_obj and access_domain_name:
+        domain_list = []
+        if extra_domain:
+            domain_list.append(extra_domain)
+        app_domain_name = get_app_domain_name(app_obj)
+        if app_domain_name: domain_list.append(app_domain_name)
+        user_domain_name = get_user_domain_name(user_obj)
+        if user_domain_name: domain_list.append(user_domain_name)
+        user_qr_domain_name = get_user_domain_name(user_obj, 0)
+        if user_qr_domain_name: domain_list.append(user_qr_domain_name)
+        if access_domain_name in domain_list:
+            return True
diff --git a/fir_ser/api/utils/serializer.py b/fir_ser/api/utils/serializer.py
index d8425f5..d47cc91 100644
--- a/fir_ser/api/utils/serializer.py
+++ b/fir_ser/api/utils/serializer.py
@@ -2,8 +2,7 @@ from rest_framework import serializers
 from api import models
 from api.utils.TokenManager import make_token
 from api.utils.app.apputils import bytes2human
-from api.utils.app.supersignutils import get_redirect_server_domain
-from api.utils.baseutils import get_user_domain_name, get_app_domain_name
+from api.utils.modelutils import get_user_domain_name, get_app_domain_name, get_redirect_server_domain
 from api.utils.storage.storage import Storage
 from api.utils.utils import get_developer_udided, get_choices_dict, get_choices_name_from_key
 from api.utils.storage.caches import get_user_free_download_times, get_user_cert_auth_status
@@ -467,13 +466,14 @@ class AdminDeveloperSerializer(DeveloperSerializer):
 class SuperSignUsedSerializer(serializers.ModelSerializer):
     class Meta:
         model = models.APPSuperSignUsedInfo
-        fields = ["created_time", "device_udid", "device_name", "developer_id", "bundle_id", "bundle_name"]
+        fields = ["created_time", "device_udid", "device_name", "developer_id", "bundle_id", "bundle_name", "other_uid"]
 
     device_udid = serializers.SerializerMethodField()
     device_name = serializers.SerializerMethodField()
     developer_id = serializers.SerializerMethodField()
     bundle_id = serializers.SerializerMethodField()
     bundle_name = serializers.SerializerMethodField()
+    other_uid = serializers.SerializerMethodField()
 
     def get_device_udid(self, obj):
         return obj.udid.udid
@@ -493,6 +493,15 @@ class SuperSignUsedSerializer(serializers.ModelSerializer):
     def get_bundle_name(self, obj):
         return obj.app_id.name
 
+    def get_other_uid(self, obj):
+        user_obj = self.context.get('user_obj')
+        role = 0
+        if user_obj:
+            role = user_obj.role
+        if role == 3:
+            if obj.user_id != obj.developerid.user_id:
+                return obj.user_id.uid
+
 
 class AdminSuperSignUsedSerializer(SuperSignUsedSerializer):
     class Meta:
@@ -530,6 +539,17 @@ class DeviceUDIDSerializer(serializers.ModelSerializer):
     bundle_id = serializers.SerializerMethodField()
     bundle_name = serializers.SerializerMethodField()
     is_mine = serializers.SerializerMethodField()
+    other_uid = serializers.SerializerMethodField()
+
+    def get_other_uid(self, obj):
+        user_obj = self.context.get('user_obj')
+        role = 0
+        if user_obj:
+            role = user_obj.role
+        if role == 3:
+            super_user_obj = models.APPSuperSignUsedInfo.objects.filter(udid=obj, app_id=obj.app_id).first()
+            if super_user_obj.developerid.user_id != obj.app_id.user_id:
+                return obj.app_id.user_id.uid
 
     def get_is_mine(self, obj):
         return self.context.get('mine')
@@ -682,3 +702,21 @@ class AppAdInfoSerializer(UserAdInfoSerializer):
 
     def get_ad_pic(self, obj):
         return get_download_url_from_context(self, obj, '', obj.ad_pic, True)
+
+
+class BillAppInfoSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = models.Apps
+        fields = ["pk", "app_id", "user_id", "name", "type", "bundle_id", "updated_time"]
+
+
+class BillDeveloperInfoSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = models.AppIOSDeveloperInfo
+        fields = ["pk", "issuer_id", "user_id", "certid"]
+
+
+class BillUdidInfoSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = models.AppUDID
+        fields = ["pk", "app_id", "udid", "product", "serial", "version", "imei", "iccid"]
diff --git a/fir_ser/api/utils/storage/aliyunApi.py b/fir_ser/api/utils/storage/aliyunApi.py
index e4b7f90..c367907 100644
--- a/fir_ser/api/utils/storage/aliyunApi.py
+++ b/fir_ser/api/utils/storage/aliyunApi.py
@@ -18,7 +18,7 @@ import logging
 from oss2 import SizedFileAdapter, determine_part_size
 from oss2.models import PartInfo
 
-from api.utils.baseutils import get_filename_form_file
+from api.utils.modelutils import get_filename_form_file
 
 logger = logging.getLogger(__name__)
 
diff --git a/fir_ser/api/utils/storage/caches.py b/fir_ser/api/utils/storage/caches.py
index 5edd109..dfd2ad2 100644
--- a/fir_ser/api/utils/storage/caches.py
+++ b/fir_ser/api/utils/storage/caches.py
@@ -13,7 +13,8 @@ from django.utils import timezone
 from fir_ser.settings import CACHE_KEY_TEMPLATE, SERVER_DOMAIN, SYNC_CACHE_TO_DATABASE, DEFAULT_MOBILEPROVISION, \
     USER_FREE_DOWNLOAD_TIMES, AUTH_USER_FREE_DOWNLOAD_TIMES
 from api.utils.storage.storage import Storage, LocalStorage
-from api.utils.baseutils import get_app_d_count_by_app_id, get_app_domain_name, check_app_password, get_user_domain_name
+from api.utils.modelutils import get_app_d_count_by_app_id, get_app_domain_name, get_user_domain_name
+from api.utils.baseutils import check_app_password
 import logging
 from django.db.models import F
 
diff --git a/fir_ser/api/utils/utils.py b/fir_ser/api/utils/utils.py
index 4c60de9..fd93f27 100644
--- a/fir_ser/api/utils/utils.py
+++ b/fir_ser/api/utils/utils.py
@@ -5,10 +5,11 @@
 # date: 2020/5/7
 import os, datetime, random
 import binascii
+
+from api.utils.modelutils import get_app_d_count_by_app_id
 from fir_ser.settings import SERVER_DOMAIN, CAPTCHA_LENGTH, MEDIA_ROOT, CACHE_KEY_TEMPLATE
 from api.models import APPSuperSignUsedInfo, APPToDeveloper, \
     UDIDsyncDeveloper, UserInfo, AppReleaseInfo, AppScreenShot, Token, DeveloperDevicesID, UserAdDisplayInfo
-from api.utils.storage.caches import get_app_d_count_by_app_id
 from api.utils.storage.localApi import LocalStorage
 from api.utils.storage.storage import Storage
 from api.utils.tempcaches import TmpCache
diff --git a/fir_ser/api/views/apps.py b/fir_ser/api/views/apps.py
index 1191d8a..430cb34 100644
--- a/fir_ser/api/views/apps.py
+++ b/fir_ser/api/views/apps.py
@@ -19,7 +19,7 @@ from api.utils.serializer import AppsSerializer, AppReleaseSerializer, AppsListS
 from rest_framework.pagination import PageNumberPagination
 import logging
 from api.utils.utils import delete_local_files, delete_app_screenshots_files
-from api.utils.baseutils import get_user_domain_name, get_app_domain_name
+from api.utils.modelutils import get_user_domain_name, get_app_domain_name
 from api.base_views import app_delete
 
 logger = logging.getLogger(__name__)
@@ -113,7 +113,7 @@ class AppInfoView(APIView):
             if app_obj:
                 app_serializer = AppsSerializer(app_obj, context={"storage": Storage(request.user)})
                 res.data = app_serializer.data
-                count = APPToDeveloper.objects.filter(app_id=app_obj).count()
+                count = APPToDeveloper.objects.filter(app_id=app_obj, developerid__user_id=request.user).count()
                 res.data["count"] = count
             else:
                 logger.error(f"app_id:{app_id} is not found in user:{request.user}")
@@ -226,7 +226,7 @@ class AppInfoView(APIView):
                         if developer_count == 0 and not get_ios_developer_public_num(request.user):
                             logger.error(f"app_id:{app_id} can't open super_sign,owner has no ios developer")
                             res.code = 1008
-                            res.msg = "超级签开发者不存在,无法开启"
+                            res.msg = "超级签余额不足,无法开启"
                             return Response(res.dict)
                         app_obj.issupersign = data.get("issupersign", app_obj.issupersign)
                         update_fields.append("issupersign")
diff --git a/fir_ser/api/views/domain.py b/fir_ser/api/views/domain.py
index 28e2688..10df95e 100644
--- a/fir_ser/api/views/domain.py
+++ b/fir_ser/api/views/domain.py
@@ -6,8 +6,8 @@
 from rest_framework.pagination import PageNumberPagination
 from rest_framework.views import APIView
 
-from api.utils.baseutils import is_valid_domain, get_cname_from_domain, get_user_domain_name, \
-    get_min_default_domain_cname_obj
+from api.utils.baseutils import is_valid_domain, get_cname_from_domain
+from api.utils.modelutils import get_user_domain_name, get_min_default_domain_cname_obj
 from api.utils.response import BaseResponse
 from api.utils.auth import ExpiringTokenAuthentication, DownloadQrPermission
 from rest_framework.response import Response
@@ -15,7 +15,7 @@ from api.models import UserDomainInfo, Apps
 import logging
 
 from api.utils.serializer import DomainNameSerializer
-from api.utils.storage.caches import del_cache_response_by_short, reset_app_wx_easy_type, reset_short_response_cache
+from api.utils.storage.caches import del_cache_response_by_short, reset_app_wx_easy_type
 from api.utils.utils import get_choices_dict
 
 logger = logging.getLogger(__name__)
diff --git a/fir_ser/api/views/download.py b/fir_ser/api/views/download.py
index 4fca11a..d8dfca4 100644
--- a/fir_ser/api/views/download.py
+++ b/fir_ser/api/views/download.py
@@ -10,9 +10,8 @@ from api.utils.TokenManager import verify_token
 from api.utils.response import BaseResponse
 from rest_framework.response import Response
 from fir_ser import settings
-from api.utils.app.randomstrings import make_random_uuid
 from api.utils.app.apputils import make_resigned
-from api.utils.app.supersignutils import make_sign_udid_mobile_config, get_post_udid_url, get_redirect_server_domain
+from api.utils.app.supersignutils import make_sign_udid_mobile_config
 from api.utils.storage.storage import Storage, get_local_storage
 from api.utils.storage.caches import get_app_instance_by_cache, get_download_url_by_cache, set_app_download_by_cache, \
     del_cache_response_by_short, consume_user_download_times, check_app_permission
@@ -22,9 +21,11 @@ from api.utils.serializer import AppsShortSerializer, AppAdInfoSerializer
 from api.models import Apps, AppReleaseInfo, APPToDeveloper, APPSuperSignUsedInfo
 from django.http import FileResponse
 import logging
-from api.utils.baseutils import get_profile_full_path, get_app_domain_name, get_filename_form_file, \
-    check_app_domain_name_access, get_real_ip_address, get_origin_domain_name, ad_random_weight, format_get_uri
+from api.utils.baseutils import get_profile_full_path, make_random_uuid, get_real_ip_address, get_origin_domain_name, \
+    format_get_uri, get_post_udid_url
 from api.utils.throttle import VisitShortThrottle, InstallShortThrottle, InstallThrottle1, InstallThrottle2
+from api.utils.modelutils import get_app_domain_name, get_filename_form_file, check_app_domain_name_access, \
+    ad_random_weight, get_redirect_server_domain
 
 logger = logging.getLogger(__name__)
 
diff --git a/fir_ser/api/views/login.py b/fir_ser/api/views/login.py
index 75e800b..0065dc4 100644
--- a/fir_ser/api/views/login.py
+++ b/fir_ser/api/views/login.py
@@ -10,7 +10,8 @@ from rest_framework.views import APIView
 from api.utils.utils import get_captcha, valid_captcha, \
     get_sender_sms_token, is_valid_sender_code, get_sender_email_token, get_random_username, \
     check_username_exists, set_user_token
-from api.utils.baseutils import is_valid_phone, is_valid_email, get_min_default_domain_cname_obj, get_real_ip_address
+from api.utils.baseutils import is_valid_phone, is_valid_email, get_real_ip_address
+from api.utils.modelutils import get_min_default_domain_cname_obj
 from api.utils.auth import ExpiringTokenAuthentication
 from api.utils.response import BaseResponse
 from fir_ser.settings import REGISTER, LOGIN, CHANGER
diff --git a/fir_ser/api/views/receiveudids.py b/fir_ser/api/views/receiveudids.py
index 49ff1f7..f64f12d 100644
--- a/fir_ser/api/views/receiveudids.py
+++ b/fir_ser/api/views/receiveudids.py
@@ -3,9 +3,8 @@
 # project: 3月
 # author: liuyu
 # date: 2020/3/6
-from api.utils.app.randomstrings import make_random_uuid
-from api.utils.app.supersignutils import udid_bytes_to_dict, get_redirect_server_domain, make_sign_udid_mobile_config, \
-    get_post_udid_url, get_http_server_domain, get_server_domain_from_request
+from api.utils.app.supersignutils import udid_bytes_to_dict, make_sign_udid_mobile_config, IosUtils
+
 from api.models import Apps
 from django.views import View
 from django.http import HttpResponsePermanentRedirect, FileResponse, HttpResponse
@@ -18,7 +17,8 @@ from fir_ser.celery import app
 import logging
 from rest_framework.views import APIView
 
-from api.utils.baseutils import get_app_domain_name
+from api.utils.baseutils import get_real_ip_address, get_http_server_domain, make_random_uuid
+from api.utils.modelutils import get_app_domain_name, get_redirect_server_domain
 from celery.exceptions import TimeoutError
 
 logger = logging.getLogger(__name__)
@@ -41,7 +41,9 @@ class IosUDIDView(View):
                     if res.code != 1000:
                         msg = "&msg=%s" % res.msg
                     else:
-                        c_task = run_sign_task.apply_async((format_udid_info, short))
+                        client_ip = get_real_ip_address(request)
+                        logger.info(f"client_ip {client_ip} short {short} app_info {app_info}")
+                        c_task = run_sign_task.apply_async((format_udid_info, short, client_ip))
                         task_id = c_task.id
                         logger.info(f"sign app {app_info} task_id:{task_id}")
                         try:
diff --git a/fir_ser/api/views/supersign.py b/fir_ser/api/views/supersign.py
index dfe8c72..91b3205 100644
--- a/fir_ser/api/views/supersign.py
+++ b/fir_ser/api/views/supersign.py
@@ -190,11 +190,11 @@ 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)
-    mine = False
-    super_sign_used_objs = APPSuperSignUsedInfo.objects.filter(user_id=request.user, )
+    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(developerid__user_id=request.user, )
-        mine = True
+        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 udid:
@@ -215,7 +215,8 @@ class SuperSignUsedView(APIView):
         app_page_serializer = page_obj.paginate_queryset(queryset=super_sign_used_objs.order_by("-created_time"),
                                                          request=request,
                                                          view=self)
-        app_serializer = SuperSignUsedSerializer(app_page_serializer, many=True, context={'mine': mine})
+        app_serializer = SuperSignUsedSerializer(app_page_serializer, many=True,
+                                                 context={'mine': mine, 'user_obj': request.user})
         res.data = app_serializer.data
         res.count = super_sign_used_objs.count()
         return Response(res.dict)
@@ -228,12 +229,13 @@ class AppUDIDUsedView(APIView):
     def get(self, request):
         res = BaseResponse()
         super_sign_used_objs, mine = base_super_sign_used_info(request)
-        app_udid_objs = AppUDID.objects.filter(app_id__appsupersignusedinfo__in=super_sign_used_objs)
+        app_udid_objs = AppUDID.objects.filter(app_id__appsupersignusedinfo__in=super_sign_used_objs).distinct()
         page_obj = PageNumber()
         app_page_serializer = page_obj.paginate_queryset(queryset=app_udid_objs.order_by("-created_time"),
                                                          request=request,
                                                          view=self)
-        app_serializer = DeviceUDIDSerializer(app_page_serializer, many=True, context={'mine': mine} )
+        app_serializer = DeviceUDIDSerializer(app_page_serializer, many=True,
+                                              context={'mine': mine, 'user_obj': request.user})
         res.data = app_serializer.data
         res.count = app_udid_objs.count()
         return Response(res.dict)
diff --git a/fir_ser/api/views/uploads.py b/fir_ser/api/views/uploads.py
index 3f316ab..536d01b 100644
--- a/fir_ser/api/views/uploads.py
+++ b/fir_ser/api/views/uploads.py
@@ -5,18 +5,16 @@
 # date: 2020/3/6
 from api.utils.TokenManager import verify_token
 from api.utils.app.apputils import get_random_short, save_app_infos
-from api.utils.baseutils import get_app_domain_name
+from api.utils.modelutils import get_app_domain_name, get_redirect_server_domain
 from api.utils.storage.storage import Storage
 from api.utils.storage.caches import upload_file_tmp_name, del_cache_response_by_short
 from api.models import Apps, AppReleaseInfo, UserInfo, AppScreenShot, CertificationInfo, UserAdDisplayInfo
-from api.utils.app.randomstrings import make_app_uuid
+from api.utils.baseutils import make_app_uuid, make_from_user_uuid
 from rest_framework.views import APIView
 from api.utils.response import BaseResponse
 from api.utils.auth import ExpiringTokenAuthentication
-from api.utils.app.randomstrings import make_from_user_uuid
 from rest_framework.response import Response
 from fir_ser import settings
-from api.utils.app.supersignutils import get_redirect_server_domain
 from api.tasks import run_resign_task
 import os, json, logging
 
diff --git a/fir_ser/cli.py b/fir_ser/cli.py
index 5a40655..b217f9b 100644
--- a/fir_ser/cli.py
+++ b/fir_ser/cli.py
@@ -332,7 +332,7 @@ class AppInfo(object):
 
 
 def check_depends():
-    cmd_list = ['--upgrade pip', 'setuptools-rust', 'oss2', 'requests-toolbelt', 'androguard', 'qiniu','requests']
+    cmd_list = ['--upgrade pip', 'setuptools-rust', 'oss2', 'requests-toolbelt', 'androguard', 'qiniu', 'requests']
     for cmd in cmd_list:
         os.system('pip install %s' % cmd)