diff --git a/apps/data/admin.py b/apps/data/admin.py index f0cc8c3..9b09abd 100644 --- a/apps/data/admin.py +++ b/apps/data/admin.py @@ -2,5 +2,5 @@ from django.contrib import admin from apps.data.models import * -admin.register([Warehouse, Client, Supplier, Account, - ChargeItem, ClientCategory, SupplierCategory, GoodsCategory, GoodsUnit]) +admin.site.register([Warehouse, Client, Supplier, Account, + ChargeItem, ClientCategory, SupplierCategory, GoodsCategory, GoodsUnit]) diff --git a/apps/data/serializers.py b/apps/data/serializers.py index 4a97030..fa91e88 100644 --- a/apps/data/serializers.py +++ b/apps/data/serializers.py @@ -22,7 +22,7 @@ class WarehouseSerializer(BaseSerializer): return value def validate_manager(self, instance): - instance = self.validate_foreign_key(User, instance) + instance = self.validate_foreign_key(User, instance, message='管理员不存在') if not instance.is_active: raise ValidationError(f'管理员[{instance.name}]未激活') return instance @@ -47,7 +47,7 @@ class ClientSerializer(BaseSerializer): return value def validate_category(self, instance): - instance = self.validate_foreign_key(ClientCategory, instance) + instance = self.validate_foreign_key(ClientCategory, instance, message='客户分类不存在') return instance def create(self, validated_data): @@ -80,7 +80,7 @@ class SupplierSerializer(BaseSerializer): return value def validate_category(self, instance): - instance = self.validate_foreign_key(SupplierCategory, instance) + instance = self.validate_foreign_key(SupplierCategory, instance, message='供应商分类不存在') return instance def create(self, validated_data): diff --git a/apps/finance/admin.py b/apps/finance/admin.py index 8c38f3f..5067c68 100644 --- a/apps/finance/admin.py +++ b/apps/finance/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from apps.finance.models import * -# Register your models here. + +admin.site.register([]) diff --git a/apps/flow/admin.py b/apps/flow/admin.py index 8c38f3f..a82a984 100644 --- a/apps/flow/admin.py +++ b/apps/flow/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from apps.flow.models import * -# Register your models here. + +admin.site.register([]) diff --git a/apps/goods/admin.py b/apps/goods/admin.py index 4bf0c80..022f30e 100644 --- a/apps/goods/admin.py +++ b/apps/goods/admin.py @@ -2,4 +2,4 @@ from django.contrib import admin from apps.goods.models import * -admin.register([Goods, Batch, Inventory]) +admin.site.register([Goods, Batch, Inventory]) diff --git a/apps/goods/serializers.py b/apps/goods/serializers.py index eef1dd1..11e17e0 100644 --- a/apps/goods/serializers.py +++ b/apps/goods/serializers.py @@ -26,11 +26,11 @@ class GoodsSerializer(BaseSerializer): return value def validate_category(self, instance): - instance = self.validate_foreign_key(GoodsCategory, instance) + instance = self.validate_foreign_key(GoodsCategory, instance, message='商品分类不存在') return instance def validate_unit(self, instance): - instance = self.validate_foreign_key(GoodsUnit, instance) + instance = self.validate_foreign_key(GoodsUnit, instance, message='商品单位不存在') return instance @transaction.atomic diff --git a/apps/purchase/admin.py b/apps/purchase/admin.py index 8c38f3f..8b2731a 100644 --- a/apps/purchase/admin.py +++ b/apps/purchase/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from apps.purchase.models import * -# Register your models here. + +admin.site.register([]) diff --git a/apps/purchase/models.py b/apps/purchase/models.py index 32fd2de..bedc967 100644 --- a/apps/purchase/models.py +++ b/apps/purchase/models.py @@ -10,9 +10,9 @@ class PurchaseOrder(Model): handler = ForeignKey('system.User', on_delete=PROTECT, related_name='purchase_orders', verbose_name='经手人') handle_time = DateTimeField(verbose_name='处理时间') remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注') - total_quantity = FloatField(verbose_name='采购总数量') + total_quantity = FloatField(null=True, verbose_name='采购总数量') other_amount = AmountField(default=0, verbose_name='其他费用') - total_amount = AmountField(verbose_name='采购总金额') + total_amount = AmountField(null=True, verbose_name='采购总金额') payment_amount = AmountField(default=0, verbose_name='付款金额') arrears_amount = AmountField(default=0, verbose_name='欠款金额') payment_order = OneToOneField('finance.PaymentOrder', on_delete=PROTECT, null=True, @@ -29,7 +29,16 @@ class PurchaseOrder(Model): @classmethod def get_number(cls, team): - return + start_date, end_date = pendulum.now(), pendulum.tomorrow() + instance = cls.objects.filter(team=team, create_time__gte=start_date, create_time__lt=end_date).last() + + try: + result = re.match('^(.*?)([1-9]+)$', instance.number) + number = result.group(1) + str(int(result.group(2)) + 1) + except AttributeError: + number = 'CG' + start_date.format('YYYYMMDD') + '0001' + + return number class PurchaseGoods(Model): diff --git a/apps/purchase/schemas.py b/apps/purchase/schemas.py index 8d7cdfd..1dffa8c 100644 --- a/apps/purchase/schemas.py +++ b/apps/purchase/schemas.py @@ -1,6 +1,10 @@ from extensions.serializers import * -__all__ = [ +class NumberResponse(Serializer): + number = CharField(label='编号') + +__all__ = [ + 'NumberResponse', ] diff --git a/apps/purchase/serializers.py b/apps/purchase/serializers.py index add84b3..60ce489 100644 --- a/apps/purchase/serializers.py +++ b/apps/purchase/serializers.py @@ -25,7 +25,7 @@ class PurchaseOrderSerializer(BaseSerializer): fields = ['goods', 'purchase_quantity', 'purchase_price', *read_only_fields] def validate_goods(self, instance): - instance = self.validate_foreign_key(Goods, instance) + instance = self.validate_foreign_key(Goods, instance, message='商品不存在') if not instance.is_active: raise ValidationError(f'商品[{instance.name}]未激活') return instance @@ -52,9 +52,9 @@ class PurchaseOrderSerializer(BaseSerializer): fields = ['account', 'payment_amount', *read_only_fields] def validate_account(self, instance): - instance = self.validate_foreign_key(Account, instance) + instance = self.validate_foreign_key(Account, instance, message='账户不存在') if not instance.is_active: - raise ValidationError(f'结算账户[{instance.name}]未激活') + raise ValidationError(f'账户[{instance.name}]未激活') return instance def validate_payment_amount(self, value): @@ -85,7 +85,7 @@ class PurchaseOrderSerializer(BaseSerializer): return value def validate_warehouse(self, instance): - instance = self.validate_foreign_key(Warehouse, instance) + instance = self.validate_foreign_key(Warehouse, instance, message='仓库不存在') if not instance.is_active: raise ValidationError(f'仓库[{instance.name}]未激活') @@ -94,13 +94,13 @@ class PurchaseOrderSerializer(BaseSerializer): return instance def validate_supplier(self, instance): - instance = self.validate_foreign_key(Supplier, instance) + instance = self.validate_foreign_key(Supplier, instance, message='供应商不存在') if not instance.is_active: raise ValidationError(f'供应商[{instance.name}]未激活') return instance def validate_handler(self, instance): - instance = self.validate_foreign_key(User, instance) + instance = self.validate_foreign_key(User, instance, message='经手人不存在') if not instance.is_active: raise ValidationError(f'经手人[{instance.name}]未激活') return instance @@ -112,11 +112,10 @@ class PurchaseOrderSerializer(BaseSerializer): @transaction.atomic def create(self, validated_data): - purchase_goods_items = validated_data.pop('purchase_goods_items') - payment_account_items = validated_data.pop('payment_account_items', None) - print(purchase_goods_items) - print(payment_account_items) - + purchase_goods_items = validated_data.pop('purchase_goods_set') + payment_order_item = validated_data.pop('payment_order', {}) + payment_account_items = payment_order_item.pop('payment_accounts', []) + validated_data['enable_auto_stock_in'] = self.team.enable_auto_stock_in validated_data['creator'] = self.user purchase_order = super().create(validated_data) @@ -144,6 +143,8 @@ class PurchaseOrderSerializer(BaseSerializer): purchase_order.total_quantity = total_purchase_quantity purchase_order.total_amount = total_purchase_amount + total_payment_amount = 0 + # 创建付款单据 if payment_account_items: payment_order_number = PaymentOrder.get_number(team=self.team) @@ -154,8 +155,6 @@ class PurchaseOrderSerializer(BaseSerializer): remark=payment_order_remark, creator=self.user, team=self.team ) - total_payment_amount = 0 - # 创建付款账户 payment_accounts = [] for payment_account_item in payment_account_items: @@ -170,12 +169,12 @@ class PurchaseOrderSerializer(BaseSerializer): PaymentAccount.objects.bulk_create(payment_accounts) payment_order.total_amount = total_payment_amount payment_order.save(update_fields=['total_amount']) - purchase_order.payment_amount = total_payment_amount - purchase_order.arrears_amount = NP.minus(total_purchase_amount, total_payment_amount) purchase_order.payment_order = payment_order - purchase_order = purchase_order.save(update_fields=['total_quantity', 'total_amount', 'payment_amount', - 'arrears_amount', 'payment_order']) + purchase_order.payment_amount = total_payment_amount + purchase_order.arrears_amount = NP.minus(total_purchase_amount, total_payment_amount) + purchase_order.save(update_fields=['total_quantity', 'total_amount', 'payment_amount', + 'arrears_amount', 'payment_order']) return purchase_order diff --git a/apps/purchase/views.py b/apps/purchase/views.py index f08b3b8..c2afea8 100644 --- a/apps/purchase/views.py +++ b/apps/purchase/views.py @@ -17,11 +17,19 @@ class PurchaseOrderViewSet(BaseViewSet, ListModelMixin, RetrieveModelMixin, Crea search_fields = ['number', 'supplier__number', 'supplier__name', 'remark'] ordering_fields = ['id', 'number', 'total_quantity', 'total_amount', 'create_time'] ordering = ['-number', 'id'] - select_related_fields = ['warehouse', 'supplier', 'handler', 'creator', - 'purchase_goods_set__goods__unit'] - prefetch_related_fields = ['purchase_goods_set', 'payment_order__payment_accounts'] + select_related_fields = ['warehouse', 'supplier', 'handler', 'creator'] + prefetch_related_fields = ['purchase_goods_set', 'purchase_goods_set__goods__unit', + 'payment_order__payment_accounts'] queryset = PurchaseOrder.objects.all() + @extend_schema(responses={200: NumberResponse}) + @action(detail=False, methods=['get']) + def number(self, request, *args, **kwargs): + """获取编号""" + + number = PurchaseOrder.get_number(self.team) + return Response(data={'number': number}, status=status.HTTP_200_OK) + __all__ = [ 'PurchaseOrderViewSet', diff --git a/apps/sales/admin.py b/apps/sales/admin.py index 8c38f3f..22467dd 100644 --- a/apps/sales/admin.py +++ b/apps/sales/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from apps.sales.models import * -# Register your models here. + +admin.site.register([]) diff --git a/apps/stock_check/admin.py b/apps/stock_check/admin.py index 8c38f3f..826bf31 100644 --- a/apps/stock_check/admin.py +++ b/apps/stock_check/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from apps.stock_check.models import * -# Register your models here. + +admin.site.register([]) diff --git a/apps/stock_in/admin.py b/apps/stock_in/admin.py index 8c38f3f..309229d 100644 --- a/apps/stock_in/admin.py +++ b/apps/stock_in/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from apps.stock_in.models import * -# Register your models here. + +admin.site.register([]) diff --git a/apps/stock_out/admin.py b/apps/stock_out/admin.py index 8c38f3f..33095b5 100644 --- a/apps/stock_out/admin.py +++ b/apps/stock_out/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from apps.stock_out.models import * -# Register your models here. + +admin.site.register([]) diff --git a/apps/stock_transfer/admin.py b/apps/stock_transfer/admin.py index 8c38f3f..33095b5 100644 --- a/apps/stock_transfer/admin.py +++ b/apps/stock_transfer/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from apps.stock_out.models import * -# Register your models here. + +admin.site.register([]) diff --git a/apps/system/admin.py b/apps/system/admin.py index f435a03..e30779a 100644 --- a/apps/system/admin.py +++ b/apps/system/admin.py @@ -2,4 +2,4 @@ from django.contrib import admin from apps.system.models import * -admin.register([Team, PermissionType, Permission, Role, User]) +admin.site.register([Team, PermissionType, Permission, Role, User]) diff --git a/apps/system/serializers.py b/apps/system/serializers.py index 5c5434f..f4e8e41 100644 --- a/apps/system/serializers.py +++ b/apps/system/serializers.py @@ -40,7 +40,7 @@ class UserSerializer(BaseSerializer): return value def validate_roles(self, instances): - instances = self.validate_foreign_key_set(Role, instances) + instances = self.validate_foreign_key_set(Role, instances, message='角色不存在') return instances def create(self, validated_data): diff --git a/documents/常用命令.md b/documents/常用命令.md index ca63ecf..a7aa471 100644 --- a/documents/常用命令.md +++ b/documents/常用命令.md @@ -6,6 +6,7 @@ http://127.0.0.1:8000/api/schema/swagger-ui/ http://127.0.0.1:8000/api/schema/redoc/ http://127.0.0.1:8000/api/ +http://127.0.0.1:8000/admin/ ``` ## 构建 @@ -21,6 +22,8 @@ python manage.py shell_plus ``` python tools/create_configs.py python tools/rebuild_database.py +python manage.py createsuperuser python manage.py runscript init_permission python manage.py runscript create_user +python manage.py runscript create_test_data ``` diff --git a/extensions/serializers.py b/extensions/serializers.py index 4d9af9a..687cb86 100644 --- a/extensions/serializers.py +++ b/extensions/serializers.py @@ -28,8 +28,6 @@ class BaseSerializer(ModelSerializer): if instance: if not (instance := model.objects.filter(id=instance.id, team=self.team).first()): raise ValidationError(message) - instance.validate() - return instance def validate_foreign_key_set(self, model, instances, message): @@ -39,10 +37,6 @@ class BaseSerializer(ModelSerializer): if len(instance_ids) != len(instances): raise ValidationError(message) - - for instance in instances: - instance.validate() - return instances def validate_unique(self, fields, message): diff --git a/scripts/create_test_data.py b/scripts/create_test_data.py new file mode 100644 index 0000000..7d25d16 --- /dev/null +++ b/scripts/create_test_data.py @@ -0,0 +1,15 @@ +from django.db import transaction +from apps.data.models import * +from apps.goods.models import * +from apps.system.models import * + + +def run(*args): + team = Team.objects.all().first() + with transaction.atomic(): + Account.objects.create(number='A001', name='默认账户', team=team) + Supplier.objects.create(number='S001', name='默认供应商', team=team) + warehouse = Warehouse.objects.create(number='W001', name='默认仓库', team=team) + goods = Goods.objects.create(number='G001', name='商品A', purchase_price=10, retail_price=20, + level_price1=20, level_price2=20, level_price3=20, team=team) + Inventory.objects.create(warehouse=warehouse, goods=goods, team=team) diff --git a/scripts/create_user.py b/scripts/create_user.py new file mode 100644 index 0000000..1d2a8c8 --- /dev/null +++ b/scripts/create_user.py @@ -0,0 +1,19 @@ +from django.contrib.auth.hashers import make_password +from django.db import transaction +from apps.system.models import * +from apps.data.models import * +import pendulum + + +def run(*args): + number = input('编号: ') + username = input('用户名: ') + password = input('密码: ') + name = input('名称: ') + activation_days = input('激活天数: ') + expiry_time = pendulum.now().add(days=float(activation_days)) + + with transaction.atomic(): + team = Team.objects.create(number=number, expiry_time=expiry_time) + User.objects.create(team=team, username=username, password=make_password(password), + name=name, is_manager=True)