ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Django用admin开发的产康中心进销存系统-3

2021-04-02 19:30:23  阅读:163  来源: 互联网

标签:产康 verbose 进销存 self admin models class def name


1.基本设定(basic)模块

1.1.models.py 设定

1.1.1.单位

商品的单位种类,例如:瓶/盒/次…等。

class Unit(models.Model):
    title = models.CharField(max_length=16, unique=True, verbose_name='名称')

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = '单位'
        verbose_name_plural = verbose_name

1.1.2.合作门店

class Store(models.Model):
    title = models.CharField(max_length=16, unique=True, verbose_name='名称')

    def __str__(self):
        return '{}-{}'.format(self.pk, self.title)

    class Meta:
        verbose_name = '合作门店'
        verbose_name_plural = verbose_name

1.1.3.员工

class Employee(models.Model):
    title = models.CharField(max_length=16, verbose_name='姓名')
    mobile = models.CharField(max_length=11, blank=True, verbose_name='手机电话')
    store = models.ForeignKey(Store, verbose_name='所属门店', on_delete=models.PROTECT)
    entry_date = models.DateField(verbose_name='入职日期')
    departure_date = models.DateField(blank=True, null=True, verbose_name='离职日期')
    basic_wage = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='底薪', default=0)
    created = models.DateTimeField(auto_now_add=True, verbose_name='建立时间')
    create_user = models.ForeignKey('auth.User', verbose_name='建立人员', on_delete=models.PROTECT,
                                    related_name='employee_create_user')
    updated = models.DateTimeField(verbose_name='异动时间', null=True)
    update_user = models.ForeignKey('auth.User', verbose_name='异动人员', on_delete=models.PROTECT,
                                    related_name='employee_update_user', null=True)

    def __str__(self):
        return '{}-{}'.format(self.pk, self.title)

    class Meta:
        verbose_name = '员工'
        verbose_name_plural = verbose_name

1.1.4.顾客

class Customer(models.Model):
    title = models.CharField(max_length=16, verbose_name='姓名')
    mobile = models.CharField(max_length=11, blank=True, verbose_name='手机电话')
    store = models.ForeignKey(Store, verbose_name='办卡门店', on_delete=models.PROTECT)
    birthday = models.DateField(verbose_name='出生日期')
    weight = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='现在体重', help_text='单位:KG')
    height = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='身高', help_text='单位:CM')
    allergic = models.CharField(max_length=64, blank=True, verbose_name='过敏史')
    address = models.CharField(max_length=32, blank=True, verbose_name='家庭地址')
    depart_address = models.CharField(max_length=32, blank=True, verbose_name='工作地址')
    depart_name = models.CharField(max_length=16, blank=True, verbose_name='单位名称')
    entry_date = models.DateField(verbose_name='到店日期')
    birth_period = models.DecimalField(max_digits=8, decimal_places=1, default=0, verbose_name='产后', help_text='月')
    notes = models.CharField(max_length=64, blank=True, verbose_name='其他说明')
    created = models.DateTimeField(auto_now_add=True, verbose_name='建立时间')
    create_user = models.ForeignKey('auth.User', verbose_name='建立人员', on_delete=models.PROTECT,
                                    related_name='customer_create_user')
    updated = models.DateTimeField(verbose_name='异动时间', null=True)
    update_user = models.ForeignKey('auth.User', verbose_name='异动人员', on_delete=models.PROTECT,
                                    related_name='customer_update_user', null=True)

    def __str__(self):
        return '{}-{}'.format(self.pk, self.title)

    class Meta:
        verbose_name = '顾客'
        verbose_name_plural = verbose_name

1.1.5.宝宝

顾客的宝宝胎次,目前尚未使用。

DELIVERY_CHOICES = (
    (1, '顺产'),
    (2, '剖宫产'),
)


class Baby(models.Model):
    customer = models.ForeignKey(Customer, verbose_name='母亲', on_delete=models.PROTECT)
    serial = models.PositiveSmallIntegerField(verbose_name='胎次')
    birthday = models.DateField(verbose_name='出生日期')
    delivery = models.PositiveSmallIntegerField(verbose_name='出生方式', choices=DELIVERY_CHOICES)
    gest_week = models.PositiveIntegerField(verbose_name='孕周(周)')
    weight = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='宝宝出生体重(KG)')
    bef_weight = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='妈妈孕前体重(KG)')
    birth_weight = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='妈妈临盆体重(KG)')
    care = models.CharField(max_length=64, blank=True, verbose_name='42天产检情况')

    def __str__(self):
        return '{}的第{}个宝宝'.format(self.customer.title, self.pk)

    class Meta:
        verbose_name = '宝宝'
        verbose_name_plural = verbose_name

1.1.6.商品

如先前所述,分产品/论次服务/有效期间服务/套盒共四类商品,[产品类]商品出售后交易即完成,[论次服务类]与[有效期间类]服务在完成交易后,自动生成论次服务记录有效期间服务记录。

TYPE_CHOICES = (
    ('1', '产品'),
    ('2', '论次服务'),
    ('3', '有效期间服务'),
    ('4', '套盒'),
)


STATUS_CHOICES = (
    ('0', '停止使用'),
    ('1', '正常'),
)


class Good(models.Model):
    title = models.CharField(max_length=32, verbose_name='名称')
    type = models.CharField(max_length=1, verbose_name='类型', choices=TYPE_CHOICES,
                                 help_text='当商品类型为时[论次服务/有效期间服务]时请添加理疗人员手工费'
                                           ',商品新增后不得修改[类型]')
    period = models.PositiveIntegerField(verbose_name='有效期限', default=0,
                                         help_text='单位:月;当商品类型为[有效期间服务]时才需要添加')
    price = models.DecimalField(max_digits=16, decimal_places=2, verbose_name='建议售价')
    unit = models.ForeignKey(Unit, verbose_name='单位', on_delete=models.PROTECT)
    sale = models.BooleanField(verbose_name='是否直接销售', default=True)
    status = models.CharField(max_length=1, verbose_name='状态', choices=STATUS_CHOICES, default='1')
    notes = models.CharField(max_length=64, blank=True, verbose_name='其他说明')
    created = models.DateTimeField(auto_now_add=True, verbose_name='建立时间')
    create_user = models.ForeignKey('auth.User', verbose_name='建立人员', on_delete=models.PROTECT,
                                    related_name='good_create_user')
    updated = models.DateTimeField(verbose_name='异动时间', null=True)
    update_user = models.ForeignKey('auth.User', verbose_name='异动人员', on_delete=models.PROTECT,
                                    related_name='good_update_user', null=True)

    def __str__(self):
        return '{}-{}'.format(self.pk, self.title)

    class Meta:
        verbose_name = '商品'
        verbose_name_plural = verbose_name

1.1.7.套盒内容商品

套盒类商品跟产品类商品一样,在门店要有库存(商品库存分布)才能贩售,而套盒内容商品记录套盒类商品有哪些商品。

class Compose(models.Model):
    main = models.ForeignKey(Good, verbose_name='套盒商品', on_delete=models.PROTECT,
                                    related_name='compose_main')
    serial = models.PositiveIntegerField(verbose_name='序号', default=1)
    content = models.ForeignKey(Good, verbose_name='套盒内容', on_delete=models.PROTECT,
                                    related_name='compose_content')
    quantity = models.PositiveIntegerField(verbose_name='数量')

    def __str__(self):
        return '{}-{}-{}'.format(self.main.title, self.serial, self.content.title)

    class Meta:
        verbose_name = '套盒内容商品'
        verbose_name_plural = verbose_name
        unique_together = ("main", "serial")

1.1.8.手工费

客户购买论次服务记录或有效期间服务商品后,可以来门店享受对应的服务内容,替客户服务的员工在当月工资中就可以增加对应的手工费金额。

class Fee(models.Model):
    good = models.ForeignKey(Good, verbose_name='商品', on_delete=models.PROTECT)
    employee = models.ForeignKey(Employee, verbose_name='员工', on_delete=models.PROTECT)
    price = models.DecimalField(max_digits=16, decimal_places=2, verbose_name='费用')

    def __str__(self):
        return '{}'.format(self.id)

    class Meta:
        verbose_name = '手工费'
        verbose_name_plural = verbose_name

1.1.9.仓库

每个合作门店可以有多个仓库存放商品类与套盒类商品,在本版次系统中尚无实际作用。

class Storage(models.Model):
    title = models.CharField(max_length=4, verbose_name='仓库名称', help_text='最多四码')
    store = models.ForeignKey(Store, verbose_name='所属门店', on_delete=models.PROTECT, help_text='新增后则不可异动')
    notes = models.CharField(max_length=64, verbose_name='描述', blank=True)

    def __str__(self):
        return '{}-{}'.format(self.id, self.title)

    class Meta:
        verbose_name = '仓库'
        verbose_name_plural = verbose_name

1.2.admin.py 设定

1.2.1.UnitAdmin呈现画面

@admin.register(Unit)
class UnitAdmin(admin.ModelAdmin):
    list_display = ['id', 'title']
    view_on_site = False

    def has_delete_permission(self, request, obj=None):
        return False

在这里插入图片描述

1.2.2.StoreAdmin呈现画面

@admin.register(Store)
class StoreAdmin(admin.ModelAdmin):
    list_display = ['id', 'title']
    view_on_site = False

    def has_delete_permission(self, request, obj=None):
        return False

在这里插入图片描述

1.2.3.CustomerAdmin呈现画面

顾客画面下方可以编辑宝宝胎次,并且能看到该顾客已来门店享受过的论次服务记录

class CerviceInline(admin.TabularInline):
    model = Cervice
    fields = ['updated', 'good', 'store', 'employee', 'notes']
    extra = 0

    def get_queryset(self, request):
        qs = super().get_queryset(request)

        return qs.filter(updated__isnull=False).order_by('-updated')

    def has_add_permission(self, request, obj=None):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

class BabyInline(admin.TabularInline):
    model = Baby
    fields = ['customer', 'serial', 'birthday', 'delivery', 'gest_week', 'weight',
              'bef_weight', 'birth_weight', 'care']
    extra = 0

    def has_delete_permission(self, request, obj=None):
        return False


@admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
    list_display = ['id', 'title', 'mobile', 'store', 'birthday', 'weight', 'height', 'allergic',
                    'address', 'depart_address', 'depart_name', 'entry_date', 'birth_period', 'notes']
    fields = ['title', 'mobile', 'store', 'birthday', 'weight', 'height', 'allergic',
              'address', 'depart_address', 'depart_name', 'entry_date', 'birth_period', 'notes',
              'created', 'create_user', 'updated', 'update_user']
    readonly_fields = ['created', 'create_user', 'updated', 'update_user']
    inlines = [BabyInline, CerviceInline]
    view_on_site = False

    def save_model(self, request, obj, form, change):
        if not change:
            obj.create_user = request.user
        else:
            obj.update_user = request.user
            obj.updated = datetime.now()

        super().save_model(request, obj, form, change)

    def has_delete_permission(self, request, obj=None):
        return False

在这里插入图片描述
在这里插入图片描述

1.2.4.GoodAdmin呈现画面

员工手工费可以在商品处设定,也可以在员工处设定,套盒类商品可以设定套盒内的商品与数量。

"""
手工费检查
1.商品类型为2(论次服务)与3(有效期间服务)时才需要设定手工费
"""
class FeeCheckInlineFormset(forms.models.BaseInlineFormSet):
    def clean(self):
        for form in self.forms:
            if form.cleaned_data:
                good = form.cleaned_data.get('good')

                if good.type not in ('2', '3'):
                    raise forms.ValidationError("商品类型为[论次服务]与3[有效期间服务]时才需要设定手工费。")


class FeeInline(admin.TabularInline):
    model = Fee
    formset = FeeCheckInlineFormset
    fields = ['good', 'employee', 'price']
    extra = 0

    def has_delete_permission(self, request, obj=None):
        return False


"""
套盒内容商品
1.main的type必须是4[套盒]
2.content的type不能是4[套盒]
3.content的type是3[有效期间服务]时,数量只能是1
4.内容的[序号]不可重复
"""
class ComposeCheckInlineFormset(forms.models.BaseInlineFormSet):
    def clean(self):
        serial_list = []
        for form in self.forms:
            if form.cleaned_data:
                main = form.cleaned_data.get('main')
                serial = form.cleaned_data.get('serial')
                content = form.cleaned_data.get('content')
                quantity = form.cleaned_data.get('quantity')

                if main.type != '4':
                    raise forms.ValidationError("套盒商品的类型必须为4[套盒]。")

                if content.type == '4':
                    raise forms.ValidationError("套盒内容的类型必须不得为4[套盒]。")

                if content.type == '3':
                    if quantity != 1:
                        raise forms.ValidationError("套盒内容的类型为3[有效期间服务]时,数量只能是1。")

                if not serial in serial_list:
                    serial_list.append(serial)
                else:
                    raise forms.ValidationError("套盒内容的[序号]不可重复。")


class ComposeInline(admin.TabularInline):
    model = Compose
    fk_name = "main"
    formset = ComposeCheckInlineFormset
    fields = ['main', 'serial', 'content', 'quantity']
    extra = 0

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "content":
            kwargs["queryset"] = Good.objects.filter(~Q(type=4), status='1')

        return super().formfield_for_foreignkey(db_field, request, **kwargs)

    def has_delete_permission(self, request, obj=None):
        return False


"""
商品检查
1.类型是[3有效期间服务]时period(有效期限)必须大于0
2.商品新增后不可修改[类型]
3.[套盒]类型产品必须直接销售
"""
class GoodCheckForm(forms.ModelForm):
    def clean(self):
        super(GoodCheckForm, self).clean()
        type = self.cleaned_data.get('type')
        period = self.cleaned_data.get('period')
        sale = self.cleaned_data.get('sale')

        if type == '3':
            if period <= 0:
                raise forms.ValidationError('类型是[有效期间服务]时[有效期限]必须大于0。')
        elif type == '4':
            if sale != True:
                raise forms.ValidationError('[套盒]类型产品必须直接销售。')

        if self.instance.type != '' and self.instance.type != type:
            raise forms.ValidationError('商品新增后不可修改[类型]。')


@admin.register(Good)
class GoodAdmin(admin.ModelAdmin):
    list_display = ['id', 'title', 'type', 'period', 'price', 'unit', 'sale', 'status']
    fields = ['title', 'type', 'period', 'price', 'unit', 'sale', 'status', 'notes',
              'created', 'create_user', 'updated', 'update_user']
    readonly_fields = ['status', 'created', 'create_user', 'updated', 'update_user']
    form = GoodCheckForm
    inlines = [FeeInline, ComposeInline]
    view_on_site = False

    def save_model(self, request, obj, form, change):
        if not change:
            obj.create_user = request.user
        else:
            obj.update_user = request.user
            obj.updated = datetime.now()

        #当商品类型为[3/有效期间服务]时才需要添加
        if obj.type != '3':
            obj.period = 0

        super().save_model(request, obj, form, change)

    def has_delete_permission(self, request, obj=None):
        return False

在这里插入图片描述
在这里插入图片描述

1.2.5.EmployeeAdmin呈现画面

@admin.register(Employee)
class EmployeeAdmin(admin.ModelAdmin):
    list_display = ['id', 'title', 'mobile', 'store', 'entry_date', 'departure_date']
    fields = ['title', 'mobile', 'store', 'entry_date', 'departure_date', 'basic_wage',
              'created', 'create_user', 'updated', 'update_user']
    readonly_fields = ['created', 'create_user', 'updated', 'update_user']
    inlines = [FeeInline]
    view_on_site = False

    def save_model(self, request, obj, form, change):
        if not change:
            obj.create_user = request.user
        else:
            obj.update_user = request.user
            obj.updated = datetime.now()

        super().save_model(request, obj, form, change)

    def has_delete_permission(self, request, obj=None):
        return False

在这里插入图片描述
在这里插入图片描述

1.2.6.StorageAdmin呈现画面


"""
储位检查
1.所属门店不可异动(save_model检查)
"""
@admin.register(Storage)
class StorageAdmin(admin.ModelAdmin):
    list_display = ['id', 'title', 'store', 'notes']
    fields = ['title', 'store', 'notes']
    view_on_site = False

    def save_model(self, request, obj, form, change):
        if not change:
            super().save_model(request, obj, form, change)
        else:
            if 'store' in form.changed_data:
                messages.error(request, '储位新增后[所属门店]不可异动。')
                messages.set_level(request, messages.ERROR)
            else:
                super().save_model(request, obj, form, change)

    def has_delete_permission(self, request, obj=None):
        return False

在这里插入图片描述

标签:产康,verbose,进销存,self,admin,models,class,def,name
来源: https://blog.csdn.net/weixin_45222104/article/details/115140543

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有