mirror of
https://github.com/himool/HimoolERP.git
synced 2024-09-20 06:46:00 +08:00
feat: 项目文档
This commit is contained in:
parent
453c9de0d8
commit
91ef89f18b
|
@ -2,5 +2,5 @@ from django.contrib import admin
|
|||
from apps.data.models import *
|
||||
|
||||
|
||||
admin.site.register([Warehouse, Client, Supplier, Account,
|
||||
ChargeItem, ClientCategory, SupplierCategory, GoodsCategory, GoodsUnit])
|
||||
admin.site.register([Warehouse, ClientCategory, Client, SupplierCategory, Supplier,
|
||||
Account, ChargeItem])
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.models import *
|
||||
|
||||
|
||||
|
@ -32,6 +33,17 @@ class Warehouse(Model):
|
|||
return number
|
||||
|
||||
|
||||
class ClientCategory(Model):
|
||||
"""客户分类"""
|
||||
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='client_categories')
|
||||
|
||||
class Meta:
|
||||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
class Client(Model):
|
||||
"""客户"""
|
||||
|
||||
|
@ -75,11 +87,16 @@ class Client(Model):
|
|||
|
||||
return number
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
self.has_arrears = self.arrears_amount > 0
|
||||
if update_fields:
|
||||
update_fields.append('has_arrears')
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
class SupplierCategory(Model):
|
||||
"""供应商分类"""
|
||||
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='supplier_categories')
|
||||
|
||||
class Meta:
|
||||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
class Supplier(Model):
|
||||
|
@ -118,12 +135,6 @@ class Supplier(Model):
|
|||
|
||||
return number
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
self.has_arrears = self.arrears_amount > 0
|
||||
if update_fields:
|
||||
update_fields.append('has_arrears')
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
|
||||
class Account(Model):
|
||||
"""结算账户"""
|
||||
|
@ -164,12 +175,6 @@ class Account(Model):
|
|||
|
||||
return number
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
self.has_balance = self.balance_amount > 0
|
||||
if update_fields:
|
||||
update_fields.append('has_balance')
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
|
||||
class ChargeItem(Model):
|
||||
"""收支项目"""
|
||||
|
@ -189,52 +194,7 @@ class ChargeItem(Model):
|
|||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
class ClientCategory(Model):
|
||||
"""客户分类"""
|
||||
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='client_categories')
|
||||
|
||||
class Meta:
|
||||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
class SupplierCategory(Model):
|
||||
"""供应商分类"""
|
||||
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='supplier_categories')
|
||||
|
||||
class Meta:
|
||||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
class GoodsCategory(Model):
|
||||
"""商品分类"""
|
||||
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='goods_categories')
|
||||
|
||||
class Meta:
|
||||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
class GoodsUnit(Model):
|
||||
"""商品单位"""
|
||||
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='goods_units')
|
||||
|
||||
class Meta:
|
||||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Warehouse', 'Client', 'Supplier', 'Account',
|
||||
'ChargeItem', 'ClientCategory', 'SupplierCategory',
|
||||
'GoodsCategory', 'GoodsUnit',
|
||||
'Warehouse', 'ClientCategory', 'Client', 'SupplierCategory', 'Supplier',
|
||||
'Account', 'ChargeItem',
|
||||
]
|
||||
|
|
|
@ -1,44 +1,37 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
class WarehousePermission(InterfacePermission):
|
||||
class WarehousePermission(ModelPermission):
|
||||
code = 'warehouse'
|
||||
|
||||
|
||||
class ClientPermission(InterfacePermission):
|
||||
class ClientPermission(ModelPermission):
|
||||
code = 'client'
|
||||
|
||||
|
||||
class SupplierPermission(InterfacePermission):
|
||||
class SupplierPermission(ModelPermission):
|
||||
code = 'supplier'
|
||||
|
||||
|
||||
class AccountPermission(InterfacePermission):
|
||||
class AccountPermission(ModelPermission):
|
||||
code = 'account'
|
||||
|
||||
|
||||
class ChargeItemPermission(InterfacePermission):
|
||||
class ChargeItemPermission(ModelPermission):
|
||||
code = 'charge_item'
|
||||
|
||||
|
||||
class ClientCategoryPermission(InterfacePermission):
|
||||
class ClientCategoryPermission(ModelPermission):
|
||||
code = 'client_category'
|
||||
|
||||
|
||||
class SupplierCategoryPermission(InterfacePermission):
|
||||
class SupplierCategoryPermission(ModelPermission):
|
||||
code = 'supplier_category'
|
||||
|
||||
|
||||
class GoodsCategoryPermission(InterfacePermission):
|
||||
code = 'goods_category'
|
||||
|
||||
|
||||
class GoodsUnitPermission(InterfacePermission):
|
||||
code = 'goods_unit'
|
||||
|
||||
|
||||
__all__ = [
|
||||
'WarehousePermission', 'ClientPermission', 'SupplierPermission', 'AccountPermission',
|
||||
'ChargeItemPermission', 'ClientCategoryPermission', 'SupplierCategoryPermission',
|
||||
'GoodsCategoryPermission', 'GoodsUnitPermission',
|
||||
]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.data.models import *
|
||||
|
@ -28,6 +29,17 @@ class WarehouseSerializer(BaseSerializer):
|
|||
return instance
|
||||
|
||||
|
||||
class ClientCategorySerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ClientCategory
|
||||
read_only_fields = ['id']
|
||||
fields = ['name', 'remark', *read_only_fields]
|
||||
|
||||
def validate_name(self, value):
|
||||
self.validate_unique({'name': value}, message=f'名称[{value}]已存在')
|
||||
return value
|
||||
|
||||
class ClientSerializer(BaseSerializer):
|
||||
level_display = CharField(source='get_level_display', read_only=True, label='等级')
|
||||
category_name = CharField(source='category.name', read_only=True, label='分类名称')
|
||||
|
@ -62,6 +74,17 @@ class ClientSerializer(BaseSerializer):
|
|||
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
class SupplierCategorySerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = SupplierCategory
|
||||
read_only_fields = ['id']
|
||||
fields = ['name', 'remark', *read_only_fields]
|
||||
|
||||
def validate_name(self, value):
|
||||
self.validate_unique({'name': value}, message=f'名称[{value}]已存在')
|
||||
return value
|
||||
|
||||
|
||||
class SupplierSerializer(BaseSerializer):
|
||||
category_name = CharField(source='category.name', read_only=True, label='分类名称')
|
||||
|
@ -140,56 +163,12 @@ class ChargeItemSerializer(BaseSerializer):
|
|||
return value
|
||||
|
||||
|
||||
class ClientCategorySerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ClientCategory
|
||||
read_only_fields = ['id']
|
||||
fields = ['name', 'remark', *read_only_fields]
|
||||
|
||||
def validate_name(self, value):
|
||||
self.validate_unique({'name': value}, message=f'名称[{value}]已存在')
|
||||
return value
|
||||
|
||||
|
||||
class SupplierCategorySerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = SupplierCategory
|
||||
read_only_fields = ['id']
|
||||
fields = ['name', 'remark', *read_only_fields]
|
||||
|
||||
def validate_name(self, value):
|
||||
self.validate_unique({'name': value}, message=f'名称[{value}]已存在')
|
||||
return value
|
||||
|
||||
|
||||
class GoodsCategorySerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GoodsCategory
|
||||
read_only_fields = ['id']
|
||||
fields = ['name', 'remark', *read_only_fields]
|
||||
|
||||
def validate_name(self, value):
|
||||
self.validate_unique({'name': value}, message=f'名称[{value}]已存在')
|
||||
return value
|
||||
|
||||
|
||||
class GoodsUnitSerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GoodsUnit
|
||||
read_only_fields = ['id']
|
||||
fields = ['name', 'remark', *read_only_fields]
|
||||
|
||||
def validate_name(self, value):
|
||||
self.validate_unique({'name': value}, message=f'名称[{value}]已存在')
|
||||
return value
|
||||
|
||||
|
||||
__all__ = [
|
||||
'WarehouseSerializer', 'ClientSerializer', 'SupplierSerializer', 'AccountSerializer',
|
||||
'ChargeItemSerializer', 'ClientCategorySerializer', 'SupplierCategorySerializer',
|
||||
'GoodsCategorySerializer', 'GoodsUnitSerializer',
|
||||
'WarehouseSerializer',
|
||||
'ClientCategorySerializer', 'ClientSerializer',
|
||||
'SupplierCategorySerializer','SupplierSerializer',
|
||||
'AccountSerializer', 'ChargeItemSerializer',
|
||||
]
|
||||
|
|
|
@ -4,12 +4,10 @@ from apps.data.views import *
|
|||
|
||||
router = BaseRouter()
|
||||
router.register('warehouses', WarehouseViewSet, 'warehouse')
|
||||
router.register('client_categories', ClientCategoryViewSet, 'client_category')
|
||||
router.register('clients', ClientViewSet, 'client')
|
||||
router.register('supplier_categories', SupplierCategoryViewSet, 'supplier_category')
|
||||
router.register('suppliers', SupplierViewSet, 'supplier')
|
||||
router.register('accounts', AccountViewSet, 'account')
|
||||
router.register('charge_items', ChargeItemViewSet, 'charge_item')
|
||||
router.register('client_categories', ClientCategoryViewSet, 'client_category')
|
||||
router.register('supplier_categories', SupplierCategoryViewSet, 'supplier_category')
|
||||
router.register('goods_categories', GoodsCategoryViewSet, 'goods_category')
|
||||
router.register('goods_units', GoodsUnitViewSet, 'goods_unit')
|
||||
urlpatterns = router.urls
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
@ -9,7 +11,7 @@ from apps.data.models import *
|
|||
from apps.goods.models import *
|
||||
|
||||
|
||||
class WarehouseViewSet(ModelViewSet):
|
||||
class WarehouseViewSet(ModelViewSet, DataProtectMixin):
|
||||
"""仓库"""
|
||||
|
||||
serializer_class = WarehouseSerializer
|
||||
|
@ -29,12 +31,6 @@ class WarehouseViewSet(ModelViewSet):
|
|||
Inventory.objects.bulk_create([Inventory(warehouse=warehouse, goods=goods, team=self.team)
|
||||
for goods in Goods.objects.filter(team=self.team)])
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
try:
|
||||
instance.delete()
|
||||
except ProtectedError:
|
||||
raise ValidationError(f'仓库[{instance.name}]已被引用, 无法删除')
|
||||
|
||||
@extend_schema(responses={200: NumberResponse})
|
||||
@action(detail=False, methods=['get'])
|
||||
def number(self, request, *args, **kwargs):
|
||||
|
@ -68,7 +64,17 @@ class WarehouseViewSet(ModelViewSet):
|
|||
return Response(data=serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class ClientViewSet(ModelViewSet):
|
||||
class ClientCategoryViewSet(ModelViewSet):
|
||||
"""客户分类"""
|
||||
|
||||
serializer_class = ClientCategorySerializer
|
||||
permission_classes = [IsAuthenticated, ClientCategoryPermission]
|
||||
search_fields = ['name', 'remark']
|
||||
ordering_fields = ['id', 'name']
|
||||
queryset = ClientCategory.objects.all()
|
||||
|
||||
|
||||
class ClientViewSet(ModelViewSet, DataProtectMixin):
|
||||
"""客户"""
|
||||
|
||||
serializer_class = ClientSerializer
|
||||
|
@ -80,12 +86,6 @@ class ClientViewSet(ModelViewSet):
|
|||
select_related_fields = ['category']
|
||||
queryset = Client.objects.all()
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
try:
|
||||
instance.delete()
|
||||
except ProtectedError:
|
||||
raise ValidationError(f'客户[{instance.name}]已被引用, 无法删除')
|
||||
|
||||
@extend_schema(responses={200: NumberResponse})
|
||||
@action(detail=False, methods=['get'])
|
||||
def number(self, request, *args, **kwargs):
|
||||
|
@ -95,7 +95,17 @@ class ClientViewSet(ModelViewSet):
|
|||
return Response(data={'number': number}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class SupplierViewSet(ModelViewSet):
|
||||
class SupplierCategoryViewSet(ModelViewSet):
|
||||
"""供应商分类"""
|
||||
|
||||
serializer_class = SupplierCategorySerializer
|
||||
permission_classes = [IsAuthenticated, SupplierCategoryPermission]
|
||||
search_fields = ['name', 'remark']
|
||||
ordering_fields = ['id', 'name']
|
||||
queryset = SupplierCategory.objects.all()
|
||||
|
||||
|
||||
class SupplierViewSet(ModelViewSet, DataProtectMixin):
|
||||
"""供应商"""
|
||||
|
||||
serializer_class = SupplierSerializer
|
||||
|
@ -107,12 +117,6 @@ class SupplierViewSet(ModelViewSet):
|
|||
select_related_fields = ['category']
|
||||
queryset = Supplier.objects.all()
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
try:
|
||||
instance.delete()
|
||||
except ProtectedError:
|
||||
raise ValidationError(f'供应商[{instance.name}]已被引用, 无法删除')
|
||||
|
||||
@extend_schema(responses={200: NumberResponse})
|
||||
@action(detail=False, methods=['get'])
|
||||
def number(self, request, *args, **kwargs):
|
||||
|
@ -122,7 +126,7 @@ class SupplierViewSet(ModelViewSet):
|
|||
return Response(data={'number': number}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class AccountViewSet(ModelViewSet):
|
||||
class AccountViewSet(ModelViewSet, DataProtectMixin):
|
||||
"""结算账户"""
|
||||
|
||||
serializer_class = AccountSerializer
|
||||
|
@ -133,12 +137,6 @@ class AccountViewSet(ModelViewSet):
|
|||
ordering = ['order', 'id']
|
||||
queryset = Account.objects.all()
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
try:
|
||||
instance.delete()
|
||||
except ProtectedError:
|
||||
raise ValidationError(f'结算账户[{instance.name}]已被引用, 无法删除')
|
||||
|
||||
@extend_schema(responses={200: NumberResponse})
|
||||
@action(detail=False, methods=['get'])
|
||||
def number(self, request, *args, **kwargs):
|
||||
|
@ -159,48 +157,9 @@ class ChargeItemViewSet(ModelViewSet):
|
|||
queryset = ChargeItem.objects.all()
|
||||
|
||||
|
||||
class ClientCategoryViewSet(ModelViewSet):
|
||||
"""客户分类"""
|
||||
|
||||
serializer_class = ClientCategorySerializer
|
||||
permission_classes = [IsAuthenticated, ClientCategoryPermission]
|
||||
search_fields = ['name', 'remark']
|
||||
ordering_fields = ['id', 'name']
|
||||
queryset = ClientCategory.objects.all()
|
||||
|
||||
|
||||
class SupplierCategoryViewSet(ModelViewSet):
|
||||
"""供应商分类"""
|
||||
|
||||
serializer_class = SupplierCategorySerializer
|
||||
permission_classes = [IsAuthenticated, SupplierCategoryPermission]
|
||||
search_fields = ['name', 'remark']
|
||||
ordering_fields = ['id', 'name']
|
||||
queryset = SupplierCategory.objects.all()
|
||||
|
||||
|
||||
class GoodsCategoryViewSet(ModelViewSet):
|
||||
"""商品分类"""
|
||||
|
||||
serializer_class = GoodsCategorySerializer
|
||||
permission_classes = [IsAuthenticated, GoodsCategoryPermission]
|
||||
search_fields = ['name', 'remark']
|
||||
ordering_fields = ['id', 'name']
|
||||
queryset = GoodsCategory.objects.all()
|
||||
|
||||
|
||||
class GoodsUnitViewSet(ModelViewSet):
|
||||
"""商品单位"""
|
||||
|
||||
serializer_class = GoodsUnitSerializer
|
||||
permission_classes = [IsAuthenticated, GoodsUnitPermission]
|
||||
search_fields = ['name', 'remark']
|
||||
ordering_fields = ['id', 'name']
|
||||
queryset = GoodsUnit.objects.all()
|
||||
|
||||
|
||||
__all__ = [
|
||||
'WarehouseViewSet', 'ClientViewSet', 'SupplierViewSet', 'AccountViewSet',
|
||||
'ChargeItemViewSet', 'ClientCategoryViewSet', 'SupplierCategoryViewSet',
|
||||
'GoodsCategoryViewSet', 'GoodsUnitViewSet',
|
||||
'WarehouseViewSet',
|
||||
'ClientCategoryViewSet', 'ClientViewSet',
|
||||
'SupplierCategoryViewSet', 'SupplierViewSet',
|
||||
'AccountViewSet', 'ChargeItemViewSet',
|
||||
]
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
class PaymentOrderPermission(InterfacePermission):
|
||||
class PaymentOrderPermission(ModelPermission):
|
||||
code = 'payment_order'
|
||||
|
||||
|
||||
class CollectionOrderPermission(InterfacePermission):
|
||||
class CollectionOrderPermission(ModelPermission):
|
||||
code = 'collection_order'
|
||||
|
||||
|
||||
class ChargeOrderPermission(InterfacePermission):
|
||||
class ChargeOrderPermission(ModelPermission):
|
||||
code = 'charge_order'
|
||||
|
||||
|
||||
class AccountTransferRecordPermission(InterfacePermission):
|
||||
class AccountTransferRecordPermission(ModelPermission):
|
||||
code = 'account_transfer_record'
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.finance.models import *
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.contrib import admin
|
|||
from apps.goods.models import *
|
||||
|
||||
|
||||
admin.site.register([Goods, Batch, Inventory])
|
||||
admin.site.register([GoodsCategory, GoodsUnit, Goods, GoodsImage, Batch, Inventory])
|
||||
|
|
|
@ -1,15 +1,38 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.models import *
|
||||
|
||||
|
||||
class GoodsCategory(Model):
|
||||
"""商品分类"""
|
||||
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='goods_categories')
|
||||
|
||||
class Meta:
|
||||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
class GoodsUnit(Model):
|
||||
"""商品单位"""
|
||||
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
remark = CharField(max_length=256, null=True, blank=True, verbose_name='备注')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='goods_units')
|
||||
|
||||
class Meta:
|
||||
unique_together = [('name', 'team')]
|
||||
|
||||
|
||||
class Goods(Model):
|
||||
"""商品"""
|
||||
|
||||
number = CharField(max_length=32, verbose_name='编号')
|
||||
name = CharField(max_length=64, verbose_name='名称')
|
||||
barcode = CharField(max_length=32, null=True, blank=True, verbose_name='条码')
|
||||
category = ForeignKey('data.GoodsCategory', on_delete=SET_NULL, null=True,
|
||||
category = ForeignKey('goods.GoodsCategory', on_delete=SET_NULL, null=True,
|
||||
related_name='goods_set', verbose_name='商品分类')
|
||||
unit = ForeignKey('data.GoodsUnit', on_delete=SET_NULL, null=True,
|
||||
unit = ForeignKey('goods.GoodsUnit', on_delete=SET_NULL, null=True,
|
||||
related_name='goods_set', verbose_name='商品单位')
|
||||
spec = CharField(max_length=64, null=True, blank=True, verbose_name='商品规格')
|
||||
enable_batch_control = BooleanField(default=False, verbose_name='启用批次控制')
|
||||
|
@ -45,6 +68,16 @@ class Goods(Model):
|
|||
return number
|
||||
|
||||
|
||||
class GoodsImage(Model):
|
||||
"""商品图片"""
|
||||
|
||||
goods = ForeignKey('goods.Goods', on_delete=SET_NULL, null=True,
|
||||
related_name='goods_images', verbose_name='商品')
|
||||
file = ImageField(verbose_name='文件')
|
||||
name = CharField(max_length=256, verbose_name='文件名称')
|
||||
team = ForeignKey('system.Team', on_delete=CASCADE, related_name='goods_images')
|
||||
|
||||
|
||||
class Batch(Model):
|
||||
"""批次"""
|
||||
|
||||
|
@ -65,12 +98,6 @@ class Batch(Model):
|
|||
class Meta:
|
||||
unique_together = [('number', 'warehouse', 'goods', 'team')]
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
self.has_stock = self.remain_quantity > 0
|
||||
if update_fields:
|
||||
update_fields.append('has_stock')
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
|
||||
class Inventory(Model):
|
||||
"""库存"""
|
||||
|
@ -85,13 +112,8 @@ class Inventory(Model):
|
|||
class Meta:
|
||||
unique_together = [('warehouse', 'goods', 'team')]
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
self.has_stock = self.total_quantity > 0
|
||||
if update_fields:
|
||||
update_fields.append('has_stock')
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Goods', 'Batch', 'Inventory',
|
||||
'GoodsCategory', 'GoodsUnit', 'Goods', 'GoodsImage',
|
||||
'Batch', 'Inventory',
|
||||
]
|
||||
|
|
|
@ -1,18 +1,27 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
class GoodsPermission(InterfacePermission):
|
||||
class GoodsCategoryPermission(ModelPermission):
|
||||
code = 'goods_category'
|
||||
|
||||
|
||||
class GoodsUnitPermission(ModelPermission):
|
||||
code = 'goods_unit'
|
||||
|
||||
|
||||
class GoodsPermission(ModelPermission):
|
||||
code = 'goods'
|
||||
|
||||
|
||||
class BatchPermission(InterfacePermission):
|
||||
class BatchPermission(ModelPermission):
|
||||
code = 'batch'
|
||||
|
||||
|
||||
class InventoryPermission(InterfacePermission):
|
||||
class InventoryPermission(ModelPermission):
|
||||
code = 'inventory'
|
||||
|
||||
|
||||
__all__ = [
|
||||
'GoodsPermission', 'BatchPermission', 'InventoryPermission',
|
||||
'GoodsCategoryPermission', 'GoodsUnitPermission', 'GoodsPermission',
|
||||
'BatchPermission', 'InventoryPermission',
|
||||
]
|
||||
|
|
|
@ -1,15 +1,40 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.goods.models import *
|
||||
from apps.data.models import *
|
||||
|
||||
|
||||
class GoodsCategorySerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GoodsCategory
|
||||
read_only_fields = ['id']
|
||||
fields = ['name', 'remark', *read_only_fields]
|
||||
|
||||
def validate_name(self, value):
|
||||
self.validate_unique({'name': value}, message=f'名称[{value}]已存在')
|
||||
return value
|
||||
|
||||
|
||||
class GoodsUnitSerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GoodsUnit
|
||||
read_only_fields = ['id']
|
||||
fields = ['name', 'remark', *read_only_fields]
|
||||
|
||||
def validate_name(self, value):
|
||||
self.validate_unique({'name': value}, message=f'名称[{value}]已存在')
|
||||
return value
|
||||
|
||||
|
||||
class GoodsSerializer(BaseSerializer):
|
||||
|
||||
class InventorySerializer(BaseSerializer):
|
||||
class InventoryItemSerializer(BaseSerializer):
|
||||
|
||||
class BatchItemSerializer(BaseSerializer):
|
||||
|
||||
class BatchSerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Batch
|
||||
read_only_fields = ['id']
|
||||
|
@ -26,7 +51,7 @@ class GoodsSerializer(BaseSerializer):
|
|||
|
||||
warehouse_number = CharField(source='warehouse.number', read_only=True, label='仓库编号')
|
||||
warehouse_name = CharField(source='warehouse.name', read_only=True, label='仓库名称')
|
||||
batch_items = BatchSerializer(source='batchs', required=False, many=True, label='批次')
|
||||
batch_items = BatchItemSerializer(source='batchs', required=False, many=True, label='批次Item')
|
||||
|
||||
class Meta:
|
||||
model = Inventory
|
||||
|
@ -42,18 +67,28 @@ class GoodsSerializer(BaseSerializer):
|
|||
raise ValidationError('库存数量小于零')
|
||||
return value
|
||||
|
||||
class GoodsImageItemSerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GoodsImage
|
||||
fields = ['id', 'name', 'file']
|
||||
|
||||
category_name = CharField(source='category.name', read_only=True, label='分类名称')
|
||||
unit_name = CharField(source='unit.name', read_only=True, label='单位名称')
|
||||
inventory_items = InventorySerializer(source='inventories', required=False, many=True, label='库存')
|
||||
inventory_items = InventoryItemSerializer(source='inventories', required=False,
|
||||
many=True, label='库存Item')
|
||||
goods_image_items = GoodsImageItemSerializer(source='goods_images', many=True,
|
||||
read_only=True, label='商品图片Item')
|
||||
|
||||
class Meta:
|
||||
model = Goods
|
||||
read_only_fields = ['id', 'category_name', 'unit_name']
|
||||
read_only_fields = ['id', 'category_name', 'unit_name', 'goods_image_items']
|
||||
fields = ['number', 'name', 'barcode', 'category', 'unit', 'spec', 'enable_batch_control',
|
||||
'shelf_life_days', 'shelf_life_warning_days', 'enable_inventory_warning',
|
||||
'inventory_upper', 'inventory_lower', 'purchase_price', 'retail_price',
|
||||
'level_price1', 'level_price2', 'level_price3', 'remark', 'order',
|
||||
'is_active', 'inventory_items', *read_only_fields]
|
||||
'is_active', 'inventory_items', 'goods_images', *read_only_fields]
|
||||
extra_kwargs = {'goods_images': {'required': False}}
|
||||
|
||||
def validate_number(self, value):
|
||||
self.validate_unique({'number': value}, message=f'编号[{value}]已存在')
|
||||
|
@ -67,6 +102,10 @@ class GoodsSerializer(BaseSerializer):
|
|||
instance = self.validate_foreign_key(GoodsUnit, instance, message='商品单位不存在')
|
||||
return instance
|
||||
|
||||
def validate_goods_images(self, instances):
|
||||
instances = self.validate_foreign_key_set(GoodsImage, instances, message='商品图片不存在')
|
||||
return instances
|
||||
|
||||
@transaction.atomic
|
||||
def create(self, validated_data):
|
||||
inventory_items = validated_data.pop('inventories', [])
|
||||
|
@ -101,7 +140,7 @@ class GoodsSerializer(BaseSerializer):
|
|||
production_date=production_date, shelf_life_days=goods.shelf_life_days,
|
||||
expiration_date=expiration_date, initial_inventory=inventory, team=self.team,
|
||||
))
|
||||
|
||||
|
||||
total_inventory_quantity = NP.plus(total_inventory_quantity, total_quantity)
|
||||
break
|
||||
else:
|
||||
|
@ -146,6 +185,18 @@ class GoodsSerializer(BaseSerializer):
|
|||
return goods
|
||||
|
||||
|
||||
class GoodsImageSerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GoodsImage
|
||||
read_only_fields = ['id', 'name']
|
||||
fields = ['file', *read_only_fields]
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['name'] = validated_data['file'].name
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
class BatchSerializer(BaseSerializer):
|
||||
warehouse_number = CharField(source='warehouse.number', read_only=True, label='仓库编号')
|
||||
warehouse_name = CharField(source='warehouse.name', read_only=True, label='仓库名称')
|
||||
|
@ -176,5 +227,6 @@ class InventorySerializer(BaseSerializer):
|
|||
|
||||
|
||||
__all__ = [
|
||||
'GoodsSerializer', 'BatchSerializer', 'InventorySerializer',
|
||||
'GoodsCategorySerializer', 'GoodsUnitSerializer', 'GoodsSerializer', 'GoodsImageSerializer',
|
||||
'BatchSerializer', 'InventorySerializer',
|
||||
]
|
||||
|
|
|
@ -3,7 +3,10 @@ from apps.goods.views import *
|
|||
|
||||
|
||||
router = BaseRouter()
|
||||
router.register('goods_categories', GoodsCategoryViewSet, 'goods_category')
|
||||
router.register('goods_units', GoodsUnitViewSet, 'goods_unit')
|
||||
router.register('goods', GoodsViewSet, 'goods')
|
||||
router.register('goods_images', GoodsViewSet, 'goods_image')
|
||||
router.register('batchs', BatchViewSet, 'batch')
|
||||
router.register('inventories', InventoryViewSet, 'inventory')
|
||||
urlpatterns = router.urls
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
@ -9,7 +11,27 @@ from apps.goods.models import *
|
|||
from apps.data.models import *
|
||||
|
||||
|
||||
class GoodsViewSet(ModelViewSet):
|
||||
class GoodsCategoryViewSet(ModelViewSet):
|
||||
"""商品分类"""
|
||||
|
||||
serializer_class = GoodsCategorySerializer
|
||||
permission_classes = [IsAuthenticated, GoodsCategoryPermission]
|
||||
search_fields = ['name', 'remark']
|
||||
ordering_fields = ['id', 'name']
|
||||
queryset = GoodsCategory.objects.all()
|
||||
|
||||
|
||||
class GoodsUnitViewSet(ModelViewSet):
|
||||
"""商品单位"""
|
||||
|
||||
serializer_class = GoodsUnitSerializer
|
||||
permission_classes = [IsAuthenticated, GoodsUnitPermission]
|
||||
search_fields = ['name', 'remark']
|
||||
ordering_fields = ['id', 'name']
|
||||
queryset = GoodsUnit.objects.all()
|
||||
|
||||
|
||||
class GoodsViewSet(ModelViewSet, DataProtectMixin):
|
||||
"""商品"""
|
||||
|
||||
serializer_class = GoodsSerializer
|
||||
|
@ -22,12 +44,6 @@ class GoodsViewSet(ModelViewSet):
|
|||
prefetch_related_fields = ['inventories', 'inventories__batchs']
|
||||
queryset = Goods.objects.all()
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
try:
|
||||
instance.delete()
|
||||
except ProtectedError:
|
||||
raise ValidationError(f'商品[{instance.name}]已被引用, 无法删除')
|
||||
|
||||
@extend_schema(responses={200: NumberResponse})
|
||||
@action(detail=False, methods=['get'])
|
||||
def number(self, request, *args, **kwargs):
|
||||
|
@ -37,6 +53,15 @@ class GoodsViewSet(ModelViewSet):
|
|||
return Response(data={'number': number}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class GoodsImageViewSet(ModelViewSet):
|
||||
"""商品图片"""
|
||||
|
||||
serializer_class = GoodsImageSerializer
|
||||
permission_classes = [IsAuthenticated, GoodsPermission]
|
||||
search_fields = ['name']
|
||||
queryset = GoodsImage.objects.all()
|
||||
|
||||
|
||||
class BatchViewSet(BaseViewSet, ReadOnlyMixin):
|
||||
"""批次"""
|
||||
|
||||
|
@ -63,5 +88,6 @@ class InventoryViewSet(BaseViewSet, ReadOnlyMixin):
|
|||
|
||||
|
||||
__all__ = [
|
||||
'GoodsViewSet', 'BatchViewSet', 'InventoryViewSet',
|
||||
'GoodsCategoryViewSet', 'GoodsUnitViewSet', 'GoodsViewSet', 'GoodsImageViewSet',
|
||||
'BatchViewSet', 'InventoryViewSet',
|
||||
]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.system.models import *
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
class PurchaseOrderPermission(InterfacePermission):
|
||||
class PurchaseOrderPermission(ModelPermission):
|
||||
code = 'purchase_order'
|
||||
|
||||
|
||||
class PurchaseReturnOrderPermission(InterfacePermission):
|
||||
class PurchaseReturnOrderPermission(ModelPermission):
|
||||
code = 'purchase_return_order'
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.purchase.models import *
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
class SalesOrderPermission(InterfacePermission):
|
||||
class SalesOrderPermission(ModelPermission):
|
||||
code = 'sales_order'
|
||||
|
||||
|
||||
class SalesReturnOrderPermission(InterfacePermission):
|
||||
class SalesReturnOrderPermission(ModelPermission):
|
||||
code = 'sales_return_order'
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.sales.models import *
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
class StockInPermission(InterfacePermission):
|
||||
class StockInPermission(ModelPermission):
|
||||
code = 'stock_in'
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from apps.goods.models import Batch
|
||||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.stock_in.models import *
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
class StockOutPermission(InterfacePermission):
|
||||
class StockOutPermission(ModelPermission):
|
||||
code = 'stock_out'
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.stock_out.models import *
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
class StockTransferPermission(InterfacePermission):
|
||||
class StockTransferPermission(ModelPermission):
|
||||
code = 'stock_transfer'
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.stock_transfer.models import *
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.contrib.auth.hashers import make_password
|
||||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
from apps.system.models import *
|
||||
|
|
|
@ -3,6 +3,8 @@ from rest_framework_simplejwt.exceptions import TokenError
|
|||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
from extensions.common.base import *
|
||||
from extensions.common.schema import *
|
||||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# 常用命令
|
||||
|
||||
## 接口文档
|
||||
|
||||
## 接口文档
|
||||
```
|
||||
http://127.0.0.1:8000/api/schema/swagger-ui/
|
||||
http://127.0.0.1:8000/api/schema/redoc/
|
||||
|
@ -10,7 +10,6 @@ http://127.0.0.1:8000/admin/
|
|||
```
|
||||
|
||||
## 构建
|
||||
|
||||
```
|
||||
python manage.py makemigrations
|
||||
python manage.py migrate
|
||||
|
@ -18,7 +17,6 @@ python manage.py shell_plus
|
|||
```
|
||||
|
||||
## 启动
|
||||
|
||||
```
|
||||
python tools/create_configs.py
|
||||
python tools/rebuild_database.py
|
||||
|
|
25
documents/项目文档/商品管理/商品信息.md
Normal file
25
documents/项目文档/商品管理/商品信息.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# 商品信息
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建商品:
|
||||
[/api/goods/]
|
||||
|
||||
- 编辑/删除商品:
|
||||
[/api/goods/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
||||
|
||||
- 商品分类选项:
|
||||
[/api/goods_categories/options/]
|
||||
|
||||
- 商品单位选项:
|
||||
[/api/goods_units/options/]
|
||||
|
||||
- 上传商品图片:
|
||||
[/api/goods_images/]
|
||||
|
||||
- 仓库选项:
|
||||
[/api/warehouses/options/]
|
13
documents/项目文档/商品管理/商品分类.md
Normal file
13
documents/项目文档/商品管理/商品分类.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# 商品分类
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建商品分类:
|
||||
[/api/goods_categories/]
|
||||
|
||||
- 编辑/删除商品分类:
|
||||
[/api/goods_categories/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
13
documents/项目文档/商品管理/商品单位.md
Normal file
13
documents/项目文档/商品管理/商品单位.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# 商品单位
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建商品单位:
|
||||
[/api/goods_units/]
|
||||
|
||||
- 编辑/删除商品单位:
|
||||
[/api/goods_units/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
16
documents/项目文档/基础数据/仓库.md
Normal file
16
documents/项目文档/基础数据/仓库.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# 仓库
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建仓库:
|
||||
[/api/warehouses/]
|
||||
|
||||
- 编辑/删除仓库:
|
||||
[/api/warehouses/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
||||
|
||||
- 管理员选项:
|
||||
[/api/users/options/]
|
16
documents/项目文档/基础数据/供应商.md
Normal file
16
documents/项目文档/基础数据/供应商.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# 供应商
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建供应商:
|
||||
[/api/suppliers/]
|
||||
|
||||
- 编辑/删除供应商:
|
||||
[/api/suppliers/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
||||
|
||||
- 供应商分类选项:
|
||||
[/api/supplier_categories/options/]
|
13
documents/项目文档/基础数据/供应商分类.md
Normal file
13
documents/项目文档/基础数据/供应商分类.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# 供应商分类
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建供应商分类:
|
||||
[/api/supplier_categories/]
|
||||
|
||||
- 编辑/删除供应商分类:
|
||||
[/api/supplier_categories/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
16
documents/项目文档/基础数据/客户.md
Normal file
16
documents/项目文档/基础数据/客户.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# 客户
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建客户:
|
||||
[/api/suppliers/]
|
||||
|
||||
- 编辑/删除客户:
|
||||
[/api/suppliers/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
||||
|
||||
- 客户分类选项:
|
||||
[/api/client_categories/options/]
|
13
documents/项目文档/基础数据/客户分类.md
Normal file
13
documents/项目文档/基础数据/客户分类.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# 客户分类
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建客户分类:
|
||||
[/api/client_categories/]
|
||||
|
||||
- 编辑/删除客户分类:
|
||||
[/api/client_categories/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
13
documents/项目文档/基础数据/收支项目.md
Normal file
13
documents/项目文档/基础数据/收支项目.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# 收支项目
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建收支项目:
|
||||
[/api/charge_items/]
|
||||
|
||||
- 编辑/删除收支项目:
|
||||
[/api/charge_items/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
13
documents/项目文档/基础数据/结算账户.md
Normal file
13
documents/项目文档/基础数据/结算账户.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# 结算账户
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询/创建结算账户:
|
||||
[/api/accounts/]
|
||||
|
||||
- 编辑/删除结算账户:
|
||||
[/api/accounts/{id}/]
|
||||
|
||||
|
||||
## 其他接口
|
13
documents/项目文档/报表统计/库存报表.md
Normal file
13
documents/项目文档/报表统计/库存报表.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# 库存报表
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询库存
|
||||
[/api/inventories/]
|
||||
|
||||
|
||||
## 其他接口
|
||||
|
||||
- 仓库选项:
|
||||
[/api/warehouses/options/]
|
13
documents/项目文档/报表统计/批次报表.md
Normal file
13
documents/项目文档/报表统计/批次报表.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# 批次报表
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
- 查询批次
|
||||
[/api/batchs/]
|
||||
|
||||
|
||||
## 其他接口
|
||||
|
||||
- 仓库选项:
|
||||
[/api/warehouses/options/]
|
|
@ -1,7 +1,7 @@
|
|||
# 员工账号
|
||||
|
||||
|
||||
# 功能
|
||||
## 功能
|
||||
|
||||
- 查询/创建账号:
|
||||
[/api/users/]
|
||||
|
@ -25,7 +25,7 @@
|
|||
[/api/user/set_password/]
|
||||
|
||||
|
||||
# 其他接口
|
||||
## 其他接口
|
||||
|
||||
- 角色选项:
|
||||
[/api/roles/options/]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# 系统配置
|
||||
|
||||
|
||||
# 功能
|
||||
## 功能
|
||||
|
||||
- 查询系统配置:
|
||||
[/api/system/configs/]
|
||||
|
@ -10,4 +10,4 @@
|
|||
[/api/system/set_configs/]
|
||||
|
||||
|
||||
# 其他接口
|
||||
## 其他接口
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# 角色权限
|
||||
|
||||
|
||||
# 功能
|
||||
## 功能
|
||||
|
||||
- 查询/创建角色:
|
||||
[/api/roles/]
|
||||
|
@ -10,7 +10,7 @@
|
|||
[/api/roles/{id}/]
|
||||
|
||||
|
||||
# 其他接口
|
||||
## 其他接口
|
||||
|
||||
- 权限列表:
|
||||
[/api/permission_groups]
|
||||
|
|
|
@ -40,8 +40,8 @@ INSTALLED_APPS = [
|
|||
'debug_toolbar',
|
||||
|
||||
'apps.system',
|
||||
# 'apps.data',
|
||||
# 'apps.goods',
|
||||
'apps.data',
|
||||
'apps.goods',
|
||||
# 'apps.purchase',
|
||||
# 'apps.sales',
|
||||
# 'apps.stock_in',
|
||||
|
|
|
@ -32,8 +32,8 @@ urlpatterns = [
|
|||
*static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT),
|
||||
|
||||
path('api/', include('apps.system.urls')),
|
||||
# path('api/', include('apps.data.urls')),
|
||||
# path('api/', include('apps.goods.urls')),
|
||||
path('api/', include('apps.data.urls')),
|
||||
path('api/', include('apps.goods.urls')),
|
||||
# path('api/', include('apps.purchase.urls')),
|
||||
# path('api/', include('apps.sales.urls')),
|
||||
# path('api/', include('apps.stock_in.urls')),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from extensions.permissions import InterfacePermission
|
||||
from extensions.permissions import ModelPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from extensions.common.base import *
|
||||
from extensions.serializers import *
|
||||
from extensions.exceptions import *
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from extensions.common.schema import *
|
||||
from extensions.common.base import *
|
||||
from extensions.permissions import *
|
||||
from extensions.exceptions import *
|
||||
from extensions.viewsets import *
|
||||
|
|
Loading…
Reference in a new issue