lyh 1 year ago
parent
commit
aee3e333db

+ 31 - 0
apps/foundation/models.py

@@ -13,11 +13,23 @@ class Option(models.Model):
     USED_VEHICLE_BRAND = 0
     USED_VEHICLE_BRAND = 0
     MAINT_TYPE = 1
     MAINT_TYPE = 1
     PRODUCT_CATEGORY = 2
     PRODUCT_CATEGORY = 2
+    VEHICLE_GEARBOX = 3
+    VEHICLE_COLOR = 4
+    VEHICLE_EMISSION = 5
+    VEHICLE_DISPLACEMENT = 6
+    VEHICLE_SEAT_COUNT = 7
+    VEHICLE_OIL = 8
 
 
     TYPE_CHOICES = (
     TYPE_CHOICES = (
         (USED_VEHICLE_BRAND, u'二手车品牌'),
         (USED_VEHICLE_BRAND, u'二手车品牌'),
         (MAINT_TYPE, u'服务类型'),
         (MAINT_TYPE, u'服务类型'),
         (PRODUCT_CATEGORY, u'商品类别'),
         (PRODUCT_CATEGORY, u'商品类别'),
+        (VEHICLE_GEARBOX, u'汽车变速箱'),
+        (VEHICLE_COLOR, u'汽车颜色'),
+        (VEHICLE_EMISSION, u'汽车排放标准'),
+        (VEHICLE_DISPLACEMENT, u'汽车排量'),
+        (VEHICLE_SEAT_COUNT, u'汽车座位数'),
+        (VEHICLE_OIL, u'汽车燃油类型'),
     )
     )
 
 
     type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, verbose_name=u"类别")
     type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, verbose_name=u"类别")
@@ -135,3 +147,22 @@ class Config(models.Model):
             return row.value
             return row.value
         except:
         except:
             return ''
             return ''
+
+    @staticmethod
+    def getConfigByText(text):
+        if text == 'wechat_appid':
+            property = Config.KEY_WECHAT_APPID
+        elif text == 'wechat_session_key':
+            property = Config.KEY_WECHAT_SESSION_KEY
+        elif text == 'abutment_xgj':
+            property = Config.KEY_ABUTMENT_XGJ
+        elif text == 'xgj_session_key':
+            property = Config.KEY_XGJ_SESSION_KEY
+        elif text == 'xgj_ip':
+            property = Config.KEY_XGJ_IP
+
+        try:
+            row = Config.objects.get(property=property)
+            return row.value
+        except:
+            return ''

+ 2 - 1
apps/foundation/urls.py

@@ -7,7 +7,8 @@ from .views import *
 
 
 urlpatterns = [
 urlpatterns = [
     url(r'option/dict/$', OptionDictView.as_view()),
     url(r'option/dict/$', OptionDictView.as_view()),
-    url(r'search/$', OptionSearchSearch.as_view()),
+    url(r'option/search/$', OptionSearchSearch.as_view()),
+    url(r'config/search/$', ConfigSearchSearch.as_view()),
 ]
 ]
 
 
 router = SimpleRouter()
 router = SimpleRouter()

+ 14 - 1
apps/foundation/views.py

@@ -51,10 +51,14 @@ class OptionViewSet(CustomModelViewSet):
 class OptionSearchSearch(APIView):
 class OptionSearchSearch(APIView):
     def get(self, request):
     def get(self, request):
         type = request.GET.get('type')
         type = request.GET.get('type')
+        types = request.GET.get('types')
         keyword = request.GET.get('keyword')
         keyword = request.GET.get('keyword')
-        rows = Option.objects.filter(delete=False, enable=True, tenant=request.user.employee.tenant)
+        rows = Option.objects.filter(delete=False, enable=True).order_by('type')
         if type:
         if type:
             rows = rows.filter(type=int(type))
             rows = rows.filter(type=int(type))
+        if types:
+            types = types.split(',')
+            rows = rows.filter(type__in=types)
 
 
         if keyword:
         if keyword:
             rows = rows.filter(name__icontains=keyword)
             rows = rows.filter(name__icontains=keyword)
@@ -62,6 +66,7 @@ class OptionSearchSearch(APIView):
         data = []
         data = []
         for row in rows:
         for row in rows:
             item ={
             item ={
+                'type': row.type,
                 'value': row.id,
                 'value': row.id,
                 'id': row.id,
                 'id': row.id,
                 'name': row.name,
                 'name': row.name,
@@ -96,3 +101,11 @@ class ConfigViewSet(CustomModelViewSet):
                         Config.objects.create(property=item['key'], value=item['value'])
                         Config.objects.create(property=item['key'], value=item['value'])
             tenant_log(self.request.user, BizLog.INSERT, u'修改系统设置', data)
             tenant_log(self.request.user, BizLog.INSERT, u'修改系统设置', data)
         return response_ok()
         return response_ok()
+
+
+class ConfigSearchSearch(APIView):
+    def get(self, request):
+        type = request.GET.get('type')
+        value = Config.getConfigByText(type)
+
+        return response_ok(value)

+ 13 - 3
apps/store/models.py

@@ -5,14 +5,14 @@ from django.db import models
 from utils.exceptions import CustomError
 from utils.exceptions import CustomError
 
 
 from apps.images.models import Images
 from apps.images.models import Images
-
+from apps.vehicle.models import Brand
 
 
 class Shop(models.Model):
 class Shop(models.Model):
     name = models.CharField(max_length=100, verbose_name=u"名称")
     name = models.CharField(max_length=100, verbose_name=u"名称")
     addr = models.CharField(max_length=1000, verbose_name=u'地址')
     addr = models.CharField(max_length=1000, verbose_name=u'地址')
     tel = models.CharField(max_length=50, verbose_name=u'电话')
     tel = models.CharField(max_length=50, verbose_name=u'电话')
-    longitude = models.FloatField(verbose_name=u"经度")
-    latitude = models.FloatField(verbose_name=u"纬度")
+    longitude = models.FloatField(verbose_name=u"经度", null=True)
+    latitude = models.FloatField(verbose_name=u"纬度", null=True)
     img = models.ForeignKey(Images, verbose_name=u'图片', on_delete=models.PROTECT, null=True)
     img = models.ForeignKey(Images, verbose_name=u'图片', on_delete=models.PROTECT, null=True)
     sort = models.PositiveSmallIntegerField(verbose_name=u'排序', help_text=u'越小越靠前', default=0)
     sort = models.PositiveSmallIntegerField(verbose_name=u'排序', help_text=u'越小越靠前', default=0)
     enabled = models.BooleanField(verbose_name=u"在用", default=True)
     enabled = models.BooleanField(verbose_name=u"在用", default=True)
@@ -41,3 +41,13 @@ class Shop(models.Model):
         if not instance:
         if not instance:
             raise CustomError(u'未找到相应的门店信息')
             raise CustomError(u'未找到相应的门店信息')
         return instance
         return instance
+
+
+class StoreBrand(models.Model):
+    store = models.ForeignKey(Shop, verbose_name=u'门店', on_delete=models.PROTECT)
+    brand = models.ForeignKey(Brand, verbose_name=u'品牌', on_delete=models.PROTECT)
+
+    class Meta:
+        db_table = 'store_brand'
+        verbose_name = u'门店品牌'
+        default_permissions = ()

+ 30 - 1
apps/store/serializers.py

@@ -2,13 +2,18 @@
 
 
 from django.conf import settings
 from django.conf import settings
 from rest_framework import serializers
 from rest_framework import serializers
-from apps.store.models import Shop
+from apps.store.models import Shop, StoreBrand
 from apps.images.models import Images
 from apps.images.models import Images
+from apps.vehicle.models import Brand
+
+from utils.exceptions import CustomError
 
 
 
 
 class ShopSerializer(serializers.ModelSerializer):
 class ShopSerializer(serializers.ModelSerializer):
     enabled_text = serializers.SerializerMethodField()
     enabled_text = serializers.SerializerMethodField()
     img_url = serializers.SerializerMethodField()
     img_url = serializers.SerializerMethodField()
+    brands = serializers.SerializerMethodField()
+    brand_text = serializers.SerializerMethodField()
 
 
     def get_enabled_text(self, obj):
     def get_enabled_text(self, obj):
         if obj.enabled:
         if obj.enabled:
@@ -20,6 +25,19 @@ class ShopSerializer(serializers.ModelSerializer):
             return '%s%s' % (settings.MEDIA_URL, obj.img.picture)
             return '%s%s' % (settings.MEDIA_URL, obj.img.picture)
         return ''
         return ''
 
 
+    def get_brands(self, obj):
+        brand_rows = StoreBrand.objects.filter(store=obj)
+        if brand_rows.count() > 0:
+            return [brand_row.brand_id for brand_row in brand_rows]
+        return []
+
+    def get_brand_text(self, obj):
+        brand_rows = StoreBrand.objects.filter(store=obj)
+        data = []
+        for brand_row in brand_rows:
+            data.append(brand_row.brand.name)
+        return ','.join(data)
+
     class Meta:
     class Meta:
         model = Shop
         model = Shop
         fields = '__all__'
         fields = '__all__'
@@ -29,5 +47,16 @@ class ShopSerializer(serializers.ModelSerializer):
         file = self.context['request'].FILES.get('image', None)
         file = self.context['request'].FILES.get('image', None)
         if file:
         if file:
             validated_data['img'] = Images.objects.employee_addnew(user, Images.SHOP_FILE, file)
             validated_data['img'] = Images.objects.employee_addnew(user, Images.SHOP_FILE, file)
+
         instance = super(ShopSerializer, self).create(validated_data)
         instance = super(ShopSerializer, self).create(validated_data)
+
+        brands = self.context['request'].data.get('brands')
+        if brands:
+            brands = brands.split(',')
+            for item in brands:
+                brand = Brand.objects.filter(id=int(item), enabled=True, delete=False).first()
+
+                if not brand:
+                    raise CustomError(u'所选择的品牌不存在或不可用或已被删除')
+                StoreBrand.objects.create(store=instance, brand=brand)
         return instance
         return instance

+ 40 - 21
apps/store/views.py

@@ -11,7 +11,8 @@ from utils.exceptions import CustomError
 from apps.foundation.models import BizLog, Config
 from apps.foundation.models import BizLog, Config
 from apps.account import tenant_log
 from apps.account import tenant_log
 from apps.images.models import Images
 from apps.images.models import Images
-from apps.store.models import Shop
+from apps.store.models import Shop, StoreBrand
+from apps.vehicle.models import Brand
 from apps.store.filters import ShopFilter
 from apps.store.filters import ShopFilter
 from .serializers import ShopSerializer
 from .serializers import ShopSerializer
 from hashlib import md5
 from hashlib import md5
@@ -27,14 +28,12 @@ class ShopViewSet(CustomModelViewSet):
         f = ShopFilter(self.request.GET, queryset=queryset)
         f = ShopFilter(self.request.GET, queryset=queryset)
         return f.qs
         return f.qs
 
 
-    @permission_required('shop.add_shop')
     def perform_create(self, serializer):
     def perform_create(self, serializer):
         super(ShopViewSet, self).perform_create(serializer)
         super(ShopViewSet, self).perform_create(serializer)
         instance = serializer.instance
         instance = serializer.instance
         validated_data = serializer.validated_data
         validated_data = serializer.validated_data
         tenant_log(self.request.user, BizLog.INSERT, u'添加门店[%s],id=%d' % (instance.name, instance.id),validated_data)
         tenant_log(self.request.user, BizLog.INSERT, u'添加门店[%s],id=%d' % (instance.name, instance.id),validated_data)
 
 
-    @permission_required('shop.delete_shop')
     def destroy(self, request, *args, **kwargs):
     def destroy(self, request, *args, **kwargs):
         with transaction.atomic():
         with transaction.atomic():
             instance = self.get_object()
             instance = self.get_object()
@@ -46,6 +45,7 @@ class ShopViewSet(CustomModelViewSet):
     @action(methods=['post'], detail=True)
     @action(methods=['post'], detail=True)
     def update_shop(self, request, pk):
     def update_shop(self, request, pk):
         file = request.FILES.get('image', None)
         file = request.FILES.get('image', None)
+        brands = request.POST.get('brands')
         user = request.user
         user = request.user
         instance = self.get_object()
         instance = self.get_object()
 
 
@@ -59,6 +59,17 @@ class ShopViewSet(CustomModelViewSet):
 
 
             tenant_log(user, BizLog.UPDATE, u'修改门店[%s],id=%d' % (instance.name, instance.id), request.data)
             tenant_log(user, BizLog.UPDATE, u'修改门店[%s],id=%d' % (instance.name, instance.id), request.data)
 
 
+            StoreBrand.objects.filter(store=instance).delete()
+
+            if brands:
+                brands = brands.split(',')
+                for item in brands:
+                    brand = Brand.objects.filter(id=int(item), enabled=True, delete=False).first()
+
+                    if not brand:
+                        raise CustomError(u'所选择的品牌不存在或不可用或已被删除')
+                    StoreBrand.objects.create(store=instance, brand=brand)
+
             if file:
             if file:
                 old_img = instance.img
                 old_img = instance.img
                 img = Images.objects.employee_addnew(user.employee, Images.SHOP_FILE, file)
                 img = Images.objects.employee_addnew(user.employee, Images.SHOP_FILE, file)
@@ -71,21 +82,13 @@ class ShopViewSet(CustomModelViewSet):
 
 
     @action(methods=['get'], detail=False)
     @action(methods=['get'], detail=False)
     def update_company(self, request):
     def update_company(self, request):
-        print('00000000000000000000000000000000')
-
         with transaction.atomic():
         with transaction.atomic():
             xgj_ip = Config.getConfigValue(Config.KEY_XGJ_IP)
             xgj_ip = Config.getConfigValue(Config.KEY_XGJ_IP)
             xgj_session_key = Config.getConfigValue(Config.KEY_XGJ_SESSION_KEY)
             xgj_session_key = Config.getConfigValue(Config.KEY_XGJ_SESSION_KEY)
-            print('3333333333333')
-            print(xgj_ip)
-            print(xgj_session_key)
             if not xgj_ip:
             if not xgj_ip:
-                print('111111111111')
                 raise CustomError(u'没有配置销管佳地址,请前往基础设置中配置!')
                 raise CustomError(u'没有配置销管佳地址,请前往基础设置中配置!')
 
 
-            print('444444444444444444444')
             if not xgj_session_key:
             if not xgj_session_key:
-                print('22222222222')
                 raise CustomError(u'没有配置销管佳密钥,请前往基础设置中配置!')
                 raise CustomError(u'没有配置销管佳密钥,请前往基础设置中配置!')
             ts = timezone.now().strftime('%Y%m%d%H%M%S')
             ts = timezone.now().strftime('%Y%m%d%H%M%S')
             token = xgj_session_key + ts
             token = xgj_session_key + ts
@@ -94,14 +97,30 @@ class ShopViewSet(CustomModelViewSet):
             m.update(token.encode("utf8"))
             m.update(token.encode("utf8"))
             sign = m.hexdigest()
             sign = m.hexdigest()
 
 
-            # url = xgj_ip + 'wechat/applet/member/company/?ts=' + ts + '&sign=' + sign
-            # param = {}
-            # result = requests.post(url=url, data=json.dumps(param))
-            # result = result.json()
-            #
-            # if not result['success']:
-            #     if 'errors' in result:
-            #         raise CustomError(u'请求失败--' + str(result['errors']))
-            #     else:
-            #         raise CustomError(u'请求失败')
+            url = xgj_ip + 'wechat/applet/member/company/?ts=' + ts + '&sign=' + sign
+            param = {}
+            result = requests.post(url=url, data=json.dumps(param))
+            result = result.json()
+            if result['success']:
+                data = result['data']
+                for item in data:
+                    store = Shop.objects.filter(xgj_id=item['id']).first()
+                    if store:
+                        store.delete = False
+                        store.save()
+                    else:
+                        Shop.objects.create(
+                            name=item['name'],
+                            addr=item['company_address'],
+                            tel=item['company_tel'],
+                            is_xgj=False,
+                            xgj_id=item['id'],
+                        )
+
+                tenant_log(request.user, BizLog.UPDATE, u'更新销管佳门店')
+            else:
+                if 'errors' in result:
+                    raise CustomError(u'请求失败--' + str(result['errors']))
+                else:
+                    raise CustomError(u'请求失败')
         return response_ok()
         return response_ok()

+ 8 - 7
apps/usedvehicle/models.py

@@ -15,24 +15,25 @@ class UsedVehicle(models.Model):
         (STOCK, u'在库'),
         (STOCK, u'在库'),
         (SALE, u'已售'),
         (SALE, u'已售'),
     )
     )
-    brand = models.ForeignKey(Option, verbose_name=u'品牌', on_delete=models.PROTECT)
+    brand = models.ForeignKey(Option, verbose_name=u'品牌', related_name='usedvehicle_brand_ref_option', on_delete=models.PROTECT)
     number = models.CharField(max_length=20, verbose_name=u'车牌号')
     number = models.CharField(max_length=20, verbose_name=u'车牌号')
     model = models.CharField(max_length=200, verbose_name=u'车型')
     model = models.CharField(max_length=200, verbose_name=u'车型')
     status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"状态", default=STOCK)
     status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"状态", default=STOCK)
     guide_price = models.IntegerField(verbose_name=u'指导价')
     guide_price = models.IntegerField(verbose_name=u'指导价')
     sale_price = models.IntegerField(verbose_name=u'售价')
     sale_price = models.IntegerField(verbose_name=u'售价')
-    gearbox = models.CharField(max_length=200, verbose_name=u"变速箱类型", blank=True, null=True)
-    color = models.CharField(max_length=20, verbose_name=u"颜色")
-    displacement = models.CharField(max_length=20, verbose_name=u"排量")
-    emission = models.CharField(max_length=20, verbose_name=u"排放标准")
+    gearbox = models.ForeignKey(Option, verbose_name=u"变速箱类型", related_name='usedvehicle_brand_ref_gearbox', on_delete=models.PROTECT)
+    color = models.ForeignKey(Option, verbose_name=u"颜色", related_name='usedvehicle_brand_ref_color', on_delete=models.PROTECT)
+    displacement = models.ForeignKey(Option, verbose_name=u"排量", related_name='usedvehicle_brand_ref_displacement', on_delete=models.PROTECT)
+    emission = models.ForeignKey(Option, verbose_name=u"排放标准", related_name='usedvehicle_brand_ref_emission', on_delete=models.PROTECT)
     address = models.CharField(max_length=50, verbose_name=u"车辆所在地", blank=True, null=True)
     address = models.CharField(max_length=50, verbose_name=u"车辆所在地", blank=True, null=True)
-    seat_count = models.IntegerField(verbose_name=u"座位数")
+    seat_count = models.ForeignKey(Option, verbose_name=u"座位数", related_name='usedvehicle_brand_ref_seat_count', on_delete=models.PROTECT)
     thumbnail = models.ForeignKey(Images, verbose_name=u'缩略图', on_delete=models.PROTECT,
     thumbnail = models.ForeignKey(Images, verbose_name=u'缩略图', on_delete=models.PROTECT,
                                   related_name=u'usedvehicle_thumbnail', null=True)
                                   related_name=u'usedvehicle_thumbnail', null=True)
     plate_date = models.DateField(verbose_name=u"上牌日期", blank=True, null=True)
     plate_date = models.DateField(verbose_name=u"上牌日期", blank=True, null=True)
     factory_date = models.DateField(verbose_name=u"出厂日期", blank=True, null=True)
     factory_date = models.DateField(verbose_name=u"出厂日期", blank=True, null=True)
-    oil_type = models.CharField(max_length=20, verbose_name=u"燃油类型")
+    oil_type = models.ForeignKey(Option, verbose_name=u"燃油类型", related_name='usedvehicle_brand_ref_oil_type', on_delete=models.PROTECT)
     mileage = models.FloatField(verbose_name=u"车辆里程")
     mileage = models.FloatField(verbose_name=u"车辆里程")
+    years = models.IntegerField(verbose_name=u'年限', null=True)
     notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)
     notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)
     delete = models.BooleanField(verbose_name=u"删除", default=False)
     delete = models.BooleanField(verbose_name=u"删除", default=False)
 
 

+ 13 - 0
apps/usedvehicle/serializers.py

@@ -1,4 +1,6 @@
 # coding=utf-8
 # coding=utf-8
+import datetime
+from django.utils import timezone
 from django.conf import settings
 from django.conf import settings
 from rest_framework import serializers
 from rest_framework import serializers
 from .models import UsedVehicle, UsedVehicleImg
 from .models import UsedVehicle, UsedVehicleImg
@@ -7,6 +9,12 @@ from .models import UsedVehicle, UsedVehicleImg
 class UsedVehicleSerializer(serializers.ModelSerializer):
 class UsedVehicleSerializer(serializers.ModelSerializer):
     status_text = serializers.CharField(source='get_status_display', read_only=True)
     status_text = serializers.CharField(source='get_status_display', read_only=True)
     brand_name = serializers.CharField(source='brand.name', read_only=True)
     brand_name = serializers.CharField(source='brand.name', read_only=True)
+    gearbox_name = serializers.CharField(source='gearbox.name', read_only=True)
+    color_name = serializers.CharField(source='color.name', read_only=True)
+    displacement_name = serializers.CharField(source='displacement.name', read_only=True)
+    emission_name = serializers.CharField(source='emission.name', read_only=True)
+    seat_count_name = serializers.CharField(source='seat_count.name', read_only=True)
+    oil_type_name = serializers.CharField(source='emission.name', read_only=True)
     plate_date = serializers.DateField(format='%Y-%m-%d')
     plate_date = serializers.DateField(format='%Y-%m-%d')
     factory_date = serializers.DateField(format='%Y-%m-%d')
     factory_date = serializers.DateField(format='%Y-%m-%d')
     thumbnail_url = serializers.SerializerMethodField()
     thumbnail_url = serializers.SerializerMethodField()
@@ -22,6 +30,11 @@ class UsedVehicleSerializer(serializers.ModelSerializer):
 
 
     def create(self, validated_data):
     def create(self, validated_data):
         instance = super(UsedVehicleSerializer, self).create(validated_data)
         instance = super(UsedVehicleSerializer, self).create(validated_data)
+        factory_date = self.context['request'].data.get('factory_date')
+        if factory_date:
+            years = int((timezone.now().date() -  datetime.datetime.strptime(factory_date, '%H:%M:%S')).days / 365)
+            instance.years = years
+            instance.save()
         return instance
         return instance
 
 
     def update(self, instance, validated_data):
     def update(self, instance, validated_data):

+ 6 - 0
apps/usedvehicle/views.py

@@ -58,6 +58,7 @@ class UsedVehicleViewSet(CustomModelViewSet):
         instance = self.get_object()
         instance = self.get_object()
         user = request.user
         user = request.user
         thumbnail = request.FILES.get('image', None)
         thumbnail = request.FILES.get('image', None)
+        factory_date = request.POST.get('factory_date')
 
 
         with transaction.atomic():
         with transaction.atomic():
             serializer = self.get_serializer(instance, data=request.data)
             serializer = self.get_serializer(instance, data=request.data)
@@ -67,6 +68,11 @@ class UsedVehicleViewSet(CustomModelViewSet):
             tenant_log(self.request.user, BizLog.UPDATE, u'修改二手车[%s],id=%d' % (instance.number, instance.id),
             tenant_log(self.request.user, BizLog.UPDATE, u'修改二手车[%s],id=%d' % (instance.number, instance.id),
                        request.data)
                        request.data)
 
 
+            if factory_date:
+                years = int((timezone.now() - datetime.datetime.strptime(factory_date, '%Y-%m-%d')).days / 365)
+                instance.years = years
+                instance.save()
+
             if thumbnail:
             if thumbnail:
                 old_thumbnail = instance.thumbnail
                 old_thumbnail = instance.thumbnail
                 thumbnail = Images.objects.employee_addnew(user, Images.USEDVEHICLE_THUMBNAIL, thumbnail)
                 thumbnail = Images.objects.employee_addnew(user, Images.USEDVEHICLE_THUMBNAIL, thumbnail)

+ 1 - 7
apps/vehicle/filters.py

@@ -4,7 +4,7 @@ import django_filters
 
 
 from django.db.models import Q
 from django.db.models import Q
 
 
-from apps.vehicle.models import Brand, Series, Model, VehicleImg, VehicleModelImg
+from apps.vehicle.models import Brand, Series, Model, VehicleImg
 
 
 
 
 class BrandFilter(django_filters.FilterSet):
 class BrandFilter(django_filters.FilterSet):
@@ -60,9 +60,3 @@ class VehicleImgFilter(django_filters.FilterSet):
         model = VehicleImg
         model = VehicleImg
         fields = '__all__'
         fields = '__all__'
 
 
-
-class VehicleModelImgFilter(django_filters.FilterSet):
-
-    class Meta:
-        model = VehicleModelImg
-        fields = '__all__'

+ 0 - 9
apps/vehicle/models.py

@@ -108,12 +108,3 @@ class VehicleImg(models.Model):
         verbose_name = u'整车图片'
         verbose_name = u'整车图片'
         default_permissions = ()
         default_permissions = ()
 
 
-class VehicleModelImg(models.Model):
-    vehicle_model = models.ForeignKey(Model, verbose_name=u'车型', on_delete=models.PROTECT)
-    img = models.ForeignKey(Images, verbose_name=u'图片', on_delete=models.PROTECT)
-
-    class Meta:
-        db_table = 'vehicle_model_img'
-        verbose_name = u'车型图片'
-        default_permissions = ()
-

+ 1 - 13
apps/vehicle/serializers.py

@@ -3,7 +3,7 @@
 import json
 import json
 from django.conf import settings
 from django.conf import settings
 from rest_framework import serializers
 from rest_framework import serializers
-from apps.vehicle.models import Brand, Series, Model, VehicleImg, VehicleModelImg
+from apps.vehicle.models import Brand, Series, Model, VehicleImg
 from apps.images.models import Images
 from apps.images.models import Images
 from utils.booleancharfield import PriceShowCharField
 from utils.booleancharfield import PriceShowCharField
 from utils.exceptions import CustomError
 from utils.exceptions import CustomError
@@ -120,15 +120,3 @@ class VehicleImgSerializer(serializers.ModelSerializer):
         model = VehicleImg
         model = VehicleImg
         fields = '__all__'
         fields = '__all__'
 
 
-
-class VehicleModelImgSerializer(serializers.ModelSerializer):
-    img_url = serializers.SerializerMethodField()
-
-    def get_img_url(self, obj):
-        if obj.img:
-            return '%s%s' % (settings.MEDIA_URL, obj.img.picture)
-        return ''
-
-    class Meta:
-        model = VehicleModelImg
-        fields = '__all__'

+ 1 - 1
apps/vehicle/urls.py

@@ -9,6 +9,7 @@ urlpatterns = [
     url(r'dict/$', DictView.as_view()),
     url(r'dict/$', DictView.as_view()),
     url(r'series/search/$', VehicleSeriesSearch.as_view()),
     url(r'series/search/$', VehicleSeriesSearch.as_view()),
     url(r'model/search/$', VehicleModelSearch.as_view()),
     url(r'model/search/$', VehicleModelSearch.as_view()),
+    url(r'brand/search/$', VehicleBrandSearch.as_view()),
 ]
 ]
 
 
 router = SimpleRouter()
 router = SimpleRouter()
@@ -16,5 +17,4 @@ router.register(r'brand', VehicleBrandViewSet)
 router.register(r'series', VehicleSeriesViewSet)
 router.register(r'series', VehicleSeriesViewSet)
 router.register(r'model', VehicleModelViewSet)
 router.register(r'model', VehicleModelViewSet)
 router.register(r'images', VehicleImageViewSet)
 router.register(r'images', VehicleImageViewSet)
-router.register(r'model_images', VehicleModelImageViewSet)
 urlpatterns += router.urls
 urlpatterns += router.urls

+ 23 - 23
apps/vehicle/views.py

@@ -11,9 +11,9 @@ from utils.permission import permission_required, isLogin
 from utils.custom_modelviewset import CustomModelViewSet
 from utils.custom_modelviewset import CustomModelViewSet
 from utils.exceptions import CustomError
 from utils.exceptions import CustomError
 from apps.images.models import Images
 from apps.images.models import Images
-from apps.vehicle.models import Brand, Series, Model, VehicleModelImg, VehicleImg
-from apps.vehicle.filters import BrandFilter, SeriesFilter, ModelFilter, VehicleImgFilter, VehicleModelImgFilter
-from .serializers import BrandSerializer, SeriesSerializer, ModelSerializer, VehicleImgSerializer, VehicleModelImgSerializer
+from apps.vehicle.models import Brand, Series, Model, VehicleImg
+from apps.vehicle.filters import BrandFilter, SeriesFilter, ModelFilter, VehicleImgFilter
+from .serializers import BrandSerializer, SeriesSerializer, ModelSerializer, VehicleImgSerializer
 from apps.account import tenant_log
 from apps.account import tenant_log
 from apps.foundation.models import BizLog
 from apps.foundation.models import BizLog
 
 
@@ -245,29 +245,29 @@ class VehicleImageViewSet(CustomModelViewSet):
         return response_ok()
         return response_ok()
 
 
 
 
-class VehicleModelImageViewSet(CustomModelViewSet):
+class VehicleBrandSearch(APIView):
     permission_classes = [isLogin, ]
     permission_classes = [isLogin, ]
-    queryset = VehicleModelImg.objects.filter()
-    serializer_class = VehicleModelImgSerializer
 
 
-    def filter_queryset(self, queryset):
-        f = VehicleModelImgFilter(self.request.GET, queryset=queryset)
-        return f.qs
-
-    def list(self, request, *args, **kwargs):
-        queryset = self.filter_queryset(self.get_queryset())
-        serializer = self.get_serializer(queryset, many=True)
-        return response_ok(serializer.data)
-
-    def destroy(self, request, *args, **kwargs):
-        with transaction.atomic():
-            instance = self.get_object()
+    def get(self, request):
+        keyword = request.GET.get('keyword')
+        rows = Brand.objects.filter(delete=False, enabled=True)
+        if keyword:
+            rows = rows.filter(
+                Q(name__icontains=keyword) |
+                Q(brand__name__icontains=keyword)
+            )
 
 
-            tenant_log(self.request.user, BizLog.DELETE, u'删除车型[%s]车型图片,id=%d' % (instance.vehicle_model.name, instance.vehicle_model.id))
-            img = instance.img
-            instance.delete()
-            img.del_images()
-        return response_ok()
+        data = []
+        for row in rows:
+            item = {
+                'value': row.id,
+                'id': row.id,
+                'name': row.name,
+                'notes': row.notes
+            }
+            data.append(item)
+
+        return response_ok(data)
 
 
 class VehicleSeriesSearch(APIView):
 class VehicleSeriesSearch(APIView):
     permission_classes = [isLogin, ]
     permission_classes = [isLogin, ]

+ 0 - 3
uis/views/index.html

@@ -155,9 +155,6 @@
                 <dd data-name="nav">
                 <dd data-name="nav">
                   <a lay-href="option/index.html">系统选项</a>
                   <a lay-href="option/index.html">系统选项</a>
                 </dd>
                 </dd>
-                <dd data-name="nav">
-                  <a lay-href="customer/customer.html">客户管理</a>
-                </dd>
                 <dd data-name="nav">
                 <dd data-name="nav">
                   <a lay-href="account/employee.html">人员管理</a>
                   <a lay-href="account/employee.html">人员管理</a>
                 </dd>
                 </dd>

+ 50 - 19
uis/views/store/edit.html

@@ -38,7 +38,13 @@
                                     <input type="text" name="tel" placeholder="请输入电话" lay-verify="required" autocomplete="off" class="layui-input">
                                     <input type="text" name="tel" placeholder="请输入电话" lay-verify="required" autocomplete="off" class="layui-input">
                                 </div>
                                 </div>
                             </div>
                             </div>
-                            <div>
+                             <div class="layui-form-item">
+                                <label class="layui-form-label">品牌:</label>
+                                <div class="layui-input-block">
+                                  <select name="brands" xm-select="manager_brands"></select>
+                                </div>
+                            </div>
+                            <div class="layui-form-item">
                               <label class="layui-form-label">排序:</label>
                               <label class="layui-form-label">排序:</label>
                               <div class="layui-input-block">
                               <div class="layui-input-block">
                                 <input type="text" name="sort" placeholder="请输入排序" lay-verify="numberGez"  autocomplete="off" class="layui-input">
                                 <input type="text" name="sort" placeholder="请输入排序" lay-verify="numberGez"  autocomplete="off" class="layui-input">
@@ -90,10 +96,11 @@
   }).extend({
   }).extend({
     index: 'lib/index',
     index: 'lib/index',
     formSelects: 'formSelects-v4'
     formSelects: 'formSelects-v4'
-  }).use(['index', 'form', 'utils', 'upload'], function(){
+  }).use(['index', 'form', 'utils', 'upload', 'formSelects'], function(){
     var $ = layui.$
     var $ = layui.$
     ,admin = layui.admin
     ,admin = layui.admin
     ,upload = layui.upload
     ,upload = layui.upload
+    ,formSelects = layui.formSelects
     ,form = layui.form;
     ,form = layui.form;
     var id = layui.view.getParameterByName('id');
     var id = layui.view.getParameterByName('id');
     var longitude = null;
     var longitude = null;
@@ -108,26 +115,49 @@
             $('#show_lat').html(latitude);
             $('#show_lat').html(latitude);
         }
         }
     }, false);
     }, false);
-    if(id){
-        var editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata)); // 框架有Bug所以这么转换
-        if (editdata.longitude && editdata.latitude) {
-            longitude = editdata.longitude;
-            latitude = editdata.latitude;
-            $('#show_lng').html(longitude);
-            $('#show_lat').html(latitude);
-            reloadMap(latitude, longitude);
-        } else {
+
+    formSelects.value('manager_brands', []);
+    admin.req({
+        url: '/vehicle/brand/search/'
+        ,done: function(res){
+            var _nodes = res.data;
+            formSelects.data('manager_brands', 'local', {
+            arr: _nodes,
+            tree: {
+                //在点击节点的时候, 如果没有子级数据, 会触发此事件
+                nextClick: function(id, item, callback){
+                    return false;
+                    },
+                }
+            });
+            //formSelects.value('manager_range', manages);
+            loadData();
+        }
+    });
+
+    var loadData = function () {
+        if(id){
+            var editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata)); // 框架有Bug所以这么转换
+            if (editdata.longitude && editdata.latitude) {
+                longitude = editdata.longitude;
+                latitude = editdata.latitude;
+                $('#show_lng').html(longitude);
+                $('#show_lat').html(latitude);
+                reloadMap(latitude, longitude);
+            } else {
+                var markurl = 'https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=6NVBZ-YA43F-UHLJY-JS3WK-26HQH-7ZBLM&referer=myapp';
+                $('#markPage').attr('src',markurl);
+            }
+            if(editdata.img_url){
+                $('#demo1').attr('src', editdata.img_url);
+            }
+            formSelects.value('manager_brands', editdata.brands);
+            form.val("component-form-element", editdata);
+        }else{
             var markurl = 'https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=6NVBZ-YA43F-UHLJY-JS3WK-26HQH-7ZBLM&referer=myapp';
             var markurl = 'https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=6NVBZ-YA43F-UHLJY-JS3WK-26HQH-7ZBLM&referer=myapp';
             $('#markPage').attr('src',markurl);
             $('#markPage').attr('src',markurl);
         }
         }
-        if(editdata.img_url){
-            $('#demo1').attr('src', editdata.img_url);
-        }
-        form.val("component-form-element", editdata);
-    }else{
-        var markurl = 'https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=6NVBZ-YA43F-UHLJY-JS3WK-26HQH-7ZBLM&referer=myapp';
-        $('#markPage').attr('src',markurl);
-    }
+    };
 
 
     function reloadMap(lat, lng) {
     function reloadMap(lat, lng) {
         var markurl = 'https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=6NVBZ-YA43F-UHLJY-JS3WK-26HQH-7ZBLM&referer=myapp&coord=' + lat + ',' + lng;
         var markurl = 'https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=6NVBZ-YA43F-UHLJY-JS3WK-26HQH-7ZBLM&referer=myapp&coord=' + lat + ',' + lng;
@@ -159,6 +189,7 @@
              name: function(){return form_data.field.name;},
              name: function(){return form_data.field.name;},
              addr: function(){return form_data.field.addr;},
              addr: function(){return form_data.field.addr;},
              tel: function(){return form_data.field.tel;},
              tel: function(){return form_data.field.tel;},
+             brands: function(){return form_data.field.brands;},
              latitude: function(){return form_data.field.latitude;},
              latitude: function(){return form_data.field.latitude;},
              longitude: function(){return form_data.field.longitude;},
              longitude: function(){return form_data.field.longitude;},
              enabled: function(){
              enabled: function(){

+ 15 - 2
uis/views/store/index.html

@@ -72,7 +72,19 @@
         ,admin = layui.admin
         ,admin = layui.admin
         ,form = layui.form;
         ,form = layui.form;
 
 
-
+    admin.req({
+        url: '/foundation/config/search/?type=abutment_xgj',
+        done: function (res) {
+            if (res.data == 'true') {
+                $('#btn_add').hide();
+                $('#btn_upload_company').show();
+            }else{
+                $('#btn_add').show();
+                $('#btn_upload_company').hide();
+            }
+            form.render();
+        }
+    });
     table.render({
     table.render({
       elem: '#datagrid'
       elem: '#datagrid'
       ,url: '/store/'
       ,url: '/store/'
@@ -80,6 +92,7 @@
         {field:'name', title:'名称',width: 200}
         {field:'name', title:'名称',width: 200}
        ,{field:'tel', title:'电话',width: 200}
        ,{field:'tel', title:'电话',width: 200}
        ,{field:'addr', title:'地址',width: 200}
        ,{field:'addr', title:'地址',width: 200}
+       ,{field:'brand_text', title:'经营品牌',width: 200}
        ,{field:'enabled_text', title:'在用',width: 80}
        ,{field:'enabled_text', title:'在用',width: 80}
        ,{field:'sort', title:'排序', width:80}
        ,{field:'sort', title:'排序', width:80}
         ,{width:120, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}
         ,{width:120, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}
@@ -128,7 +141,7 @@
                 layer.close(index);
                 layer.close(index);
                 layui.admin.req({
                 layui.admin.req({
                     notice: true
                     notice: true
-                    ,url: '/shop/'+data.id + '/'
+                    ,url: '/store/'+data.id + '/'
                     ,type: 'delete'
                     ,type: 'delete'
                     ,done: function(res){
                     ,done: function(res){
                         table.reload('datagrid',{});
                         table.reload('datagrid',{});

+ 40 - 14
uis/views/usedvehicle/edit.html

@@ -56,27 +56,31 @@
                   </div>
                   </div>
                 </div>
                 </div>
                 <div>
                 <div>
-                  <label class="layui-form-label">变速箱:</label>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>变速箱:</label>
                   <div class="layui-input-block">
                   <div class="layui-input-block">
-                    <input type="text" name="gearbox"  placeholder="请输入变速箱类型" autocomplete="off" class="layui-input">
+                    <select id="id_gearbox" name="gearbox" lay-verify="required">
+                    </select>
                   </div>
                   </div>
                 </div>
                 </div>
                  <div>
                  <div>
                   <label class="layui-form-label"><font color='red' size="4">*</font>颜色:</label>
                   <label class="layui-form-label"><font color='red' size="4">*</font>颜色:</label>
                   <div class="layui-input-block">
                   <div class="layui-input-block">
-                    <input type="text" name="color" lay-verify="required" placeholder="请输入颜色" autocomplete="off" class="layui-input">
+                    <select id="id_color" name="color" lay-verify="required">
+                    </select>
                   </div>
                   </div>
                 </div>
                 </div>
                 <div>
                 <div>
                   <label class="layui-form-label"><font color='red' size="4">*</font>排量:</label>
                   <label class="layui-form-label"><font color='red' size="4">*</font>排量:</label>
                   <div class="layui-input-block">
                   <div class="layui-input-block">
-                    <input type="text" name="displacement" lay-verify="required" placeholder="请输入排量" autocomplete="off" class="layui-input">
+                    <select id="id_displacement" name="displacement" lay-verify="required">
+                    </select>
                   </div>
                   </div>
                 </div>
                 </div>
                 <div>
                 <div>
                   <label class="layui-form-label"><font color='red' size="4">*</font>排放标准:</label>
                   <label class="layui-form-label"><font color='red' size="4">*</font>排放标准:</label>
                   <div class="layui-input-block">
                   <div class="layui-input-block">
-                    <input type="text" name="emission" lay-verify="required" placeholder="请输入排放标准" autocomplete="off" class="layui-input">
+                    <select id="id_emission" name="emission" lay-verify="required">
+                    </select>
                   </div>
                   </div>
                 </div>
                 </div>
                 <div>
                 <div>
@@ -88,7 +92,8 @@
                 <div>
                 <div>
                   <label class="layui-form-label"><font color='red' size="4">*</font>座位数:</label>
                   <label class="layui-form-label"><font color='red' size="4">*</font>座位数:</label>
                   <div class="layui-input-block">
                   <div class="layui-input-block">
-                    <input type="text" name="seat_count" lay-verify="required|intGeZ" placeholder="请输入座位数" autocomplete="off" class="layui-input">
+                    <select id="id_seat_count" name="seat_count" lay-verify="required">
+                    </select>
                   </div>
                   </div>
                 </div>
                 </div>
                 <div>
                 <div>
@@ -106,7 +111,8 @@
                 <div>
                 <div>
                   <label class="layui-form-label"><font color='red' size="4">*</font>燃油类型:</label>
                   <label class="layui-form-label"><font color='red' size="4">*</font>燃油类型:</label>
                   <div class="layui-input-block">
                   <div class="layui-input-block">
-                    <input type="text" name="oil_type" lay-verify="required" placeholder="请输入燃油类型" autocomplete="off" class="layui-input">
+                    <select id="id_oil_type" name="oil_type" lay-verify="required">
+                    </select>
                   </div>
                   </div>
                 </div>
                 </div>
                 <div>
                 <div>
@@ -164,14 +170,34 @@
     });
     });
 
 
     admin.req({
     admin.req({
-        url: '/foundation/option/?type=0',
+        url: '/foundation/option/search/?types=0,3,4,5,6,7,8',
         done: function (res) {
         done: function (res) {
-            var brands = res.data;
-            var type_node = $('#id_brand');
-            for (var i in brands) {
-                var pid = brands[i].id;
-                var value = brands[i].name;
-                type_node.append("<option value='" + pid + "'>" + value + "</option>");
+            var data = res.data;
+            var brand_node = $('#id_brand');
+            var gearbox_node = $('#id_gearbox');
+            var color_node = $('#id_color');
+            var displacement_node = $('#id_displacement');
+            var emission_node = $('#id_emission');
+            var seat_count_node = $('#id_seat_count');
+            var oil_type_node = $('#id_oil_type');
+            for (var i in data) {
+                var pid = data[i].id;
+                var value = data[i].name;
+                if (data[i].type == '0') {
+                    brand_node.append("<option value='" + pid + "'>" + value + "</option>");
+                }else if (data[i].type == '3'){
+                    gearbox_node.append("<option value='" + pid + "'>" + value + "</option>");
+                }else if (data[i].type == '4'){
+                    color_node.append("<option value='" + pid + "'>" + value + "</option>");
+                }else if (data[i].type == '5'){
+                    emission_node.append("<option value='" + pid + "'>" + value + "</option>");
+                }else if (data[i].type == '6'){
+                    displacement_node.append("<option value='" + pid + "'>" + value + "</option>");
+                }else if (data[i].type == '7'){
+                    seat_count_node.append("<option value='" + pid + "'>" + value + "</option>");
+                }else if (data[i].type == '8'){
+                    oil_type_node.append("<option value='" + pid + "'>" + value + "</option>");
+                }
             }
             }
             form.render();
             form.render();
             loadData();
             loadData();

+ 6 - 6
uis/views/usedvehicle/index.html

@@ -105,15 +105,15 @@
        ,{field:'status_text', title:'状态',width: 100}
        ,{field:'status_text', title:'状态',width: 100}
        ,{field:'guide_price', title:'指导价',width: 100}
        ,{field:'guide_price', title:'指导价',width: 100}
        ,{field:'sale_price', title:'售价',width: 100}
        ,{field:'sale_price', title:'售价',width: 100}
-       ,{field:'gearbox', title:'变速箱类型',width: 100}
-       ,{field:'color', title:'颜色',width: 100}
-       ,{field:'displacement', title:'排量',width: 100}
-       ,{field:'emission', title:'排放标准',width: 100}
+       ,{field:'gearbox_name', title:'变速箱类型',width: 100}
+       ,{field:'color_name', title:'颜色',width: 100}
+       ,{field:'displacement_name', title:'排量',width: 100}
+       ,{field:'emission_name', title:'排放标准',width: 100}
        ,{field:'address', title:'车辆所在地',width: 100}
        ,{field:'address', title:'车辆所在地',width: 100}
-       ,{field:'seat_count', title:'座位数',width: 100}
+       ,{field:'seat_count_name', title:'座位数',width: 100}
        ,{field:'plate_date', title:'上牌日期',width: 120}
        ,{field:'plate_date', title:'上牌日期',width: 120}
        ,{field:'factory_date', title:'出厂日期',width: 120}
        ,{field:'factory_date', title:'出厂日期',width: 120}
-       ,{field:'oil_type', title:'燃油类型',width: 100}
+       ,{field:'oil_type_name', title:'燃油类型',width: 100}
        ,{field:'mileage', title:'车辆里程',width: 100}
        ,{field:'mileage', title:'车辆里程',width: 100}
        ,{field:'notes', title:'备注',width: 150}
        ,{field:'notes', title:'备注',width: 150}
         ,{width:200, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}
         ,{width:200, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}