Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
512549173b
|
@ -46,7 +46,7 @@
|
||||||
<template slot-scope="scope">{{ scope.row.order_.number }}</template>
|
<template slot-scope="scope">{{ scope.row.order_.number }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="合同编号" width="110">
|
<el-table-column label="合同编号" width="110">
|
||||||
<template slot-scope="scope" v-if="scope.row.contract">{{
|
<template slot-scope="scope" v-if="scope.row.order_">{{
|
||||||
scope.row.order_.contract_.number
|
scope.row.order_.contract_.number
|
||||||
}}</template>
|
}}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
|
@ -49,12 +49,12 @@
|
||||||
}}</template>
|
}}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="合同编号" show-overflow-tooltip width="150">
|
<el-table-column label="合同编号" show-overflow-tooltip width="150">
|
||||||
<template slot-scope="scope">{{
|
<template slot-scope="scope" v-if=" scope.row.contract_">{{
|
||||||
scope.row.contract_.number
|
scope.row.contract_.number
|
||||||
}}</template>
|
}}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="合同名称" show-overflow-tooltip width="150">
|
<el-table-column label="合同名称" show-overflow-tooltip width="150">
|
||||||
<template slot-scope="scope">{{
|
<template slot-scope="scope" v-if=" scope.row.contract_">{{
|
||||||
scope.row.contract_.name
|
scope.row.contract_.name
|
||||||
}}</template>
|
}}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
|
@ -1,24 +1,39 @@
|
||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
from distutils import command
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def backup_database():
|
def backup_database():
|
||||||
"""
|
"""
|
||||||
备份数据库
|
备份数据库
|
||||||
"""
|
"""
|
||||||
ret = os.popen('sudo pg_dump -U postgres -d hberp -f /home/lighthouse/hberp_backup.sql')
|
import datetime
|
||||||
return Response()
|
name = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
||||||
|
command = '''pg_dump "user=postgres password=zcDsj2021 dbname=hberp" >
|
||||||
|
/home/lighthouse/backup/hberp_{}.sql'''.format(name)
|
||||||
|
completed = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
return completed
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def reload_server():
|
def reload_server():
|
||||||
os.chdir('/home/lighthouse/hberp')
|
os.chdir('/home/lighthouse/hberp')
|
||||||
ret = subprocess.run('sudo git pull && sudo service supervisor reload')
|
command = 'sudo git pull && sudo service supervisor reload'
|
||||||
return Response(ret.read())
|
completed = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
return completed
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def reload_server_only():
|
||||||
|
command = 'sudo service supervisor reload'
|
||||||
|
completed = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
return completed
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def backup_media():
|
||||||
|
command = 'rsync -avu /home/lighthouse/hberp/hb_server/media/ /home/lighthouse/backup/media/'
|
||||||
|
completed = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
return completed
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.db.models import base
|
||||||
from rest_framework import urlpatterns
|
from rest_framework import urlpatterns
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
from apps.develop.views import BackupDatabase, CleanDataView, ReloadServer, UpdateCuttingView, UpdateEquipState, UpdateFIFOItem, UpdateFIFONumber, UpdateLastTestResult, UpdateNeedToOrder, UpdateSpg
|
from apps.develop.views import BackupDatabase, BackupMedia, CleanDataView, ReloadServer, ReloadServerOnly, UpdateCuttingView, UpdateEquipState, UpdateFIFOItem, UpdateFIFONumber, UpdateLastTestResult, UpdateNeedToOrder, UpdateSpg
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('cleandata/', CleanDataView.as_view()),
|
path('cleandata/', CleanDataView.as_view()),
|
||||||
|
@ -15,6 +15,8 @@ urlpatterns = [
|
||||||
path('update_need_to_order/', UpdateNeedToOrder.as_view()),
|
path('update_need_to_order/', UpdateNeedToOrder.as_view()),
|
||||||
path('update_fifo_number/', UpdateFIFONumber.as_view()),
|
path('update_fifo_number/', UpdateFIFONumber.as_view()),
|
||||||
path('reload_server/', ReloadServer.as_view()),
|
path('reload_server/', ReloadServer.as_view()),
|
||||||
path('backup_database/', BackupDatabase.as_view())
|
path('reload_server_only/', ReloadServerOnly.as_view()),
|
||||||
|
path('backup_database/', BackupDatabase.as_view()),
|
||||||
|
path('backup_media/', BackupMedia.as_view())
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ from rest_framework.decorators import permission_classes
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.permissions import IsAdminUser
|
from rest_framework.permissions import IsAdminUser
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from apps.develop.tasks import backup_database, reload_server
|
from apps.develop.tasks import backup_database, backup_media, reload_server, reload_server_only
|
||||||
from apps.inm.models import FIFO, FIFOItem, Inventory, MaterialBatch
|
from apps.inm.models import FIFO, FIFOItem, Inventory, MaterialBatch
|
||||||
from apps.mtm.models import Material
|
from apps.mtm.models import Material
|
||||||
from apps.pm.models import ProductionPlan, SubProductionPlan
|
from apps.pm.models import ProductionPlan, SubProductionPlan
|
||||||
|
@ -13,6 +13,7 @@ from apps.wf.models import Ticket
|
||||||
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow
|
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow
|
||||||
from apps.wpm.services import WpmService
|
from apps.wpm.services import WpmService
|
||||||
from apps.em.tasks import update_equip_state_by_next_check_date
|
from apps.em.tasks import update_equip_state_by_next_check_date
|
||||||
|
from rest_framework.exceptions import APIException
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
class CleanDataView(APIView):
|
class CleanDataView(APIView):
|
||||||
|
@ -123,10 +124,47 @@ class UpdateFIFONumber(APIView):
|
||||||
class ReloadServer(APIView):
|
class ReloadServer(APIView):
|
||||||
permission_classes = [IsAdminUser]
|
permission_classes = [IsAdminUser]
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
reload_server()
|
"""
|
||||||
|
拉取代码并重启服务
|
||||||
|
"""
|
||||||
|
completed = reload_server()
|
||||||
|
if completed.returncode == 0:
|
||||||
|
return Response()
|
||||||
|
else:
|
||||||
|
raise APIException(completed.stdout)
|
||||||
|
|
||||||
|
class ReloadServerOnly(APIView):
|
||||||
|
permission_classes = [IsAdminUser]
|
||||||
|
def post(self, request):
|
||||||
|
"""
|
||||||
|
仅重启服务
|
||||||
|
"""
|
||||||
|
completed = reload_server_only()
|
||||||
|
if completed.returncode == 0:
|
||||||
|
return Response()
|
||||||
|
else:
|
||||||
|
raise APIException(completed.stdout)
|
||||||
|
|
||||||
class BackupDatabase(APIView):
|
class BackupDatabase(APIView):
|
||||||
permission_classes = [IsAdminUser]
|
permission_classes = [IsAdminUser]
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
backup_database()
|
"""
|
||||||
|
备份数据库到指定位置
|
||||||
|
"""
|
||||||
|
completed = backup_database()
|
||||||
|
if completed.returncode == 0:
|
||||||
|
return Response()
|
||||||
|
else:
|
||||||
|
raise APIException(completed.stdout)
|
||||||
|
|
||||||
|
class BackupMedia(APIView):
|
||||||
|
permission_classes = [IsAdminUser]
|
||||||
|
def post(self, request):
|
||||||
|
"""
|
||||||
|
备份资源到指定位置
|
||||||
|
"""
|
||||||
|
completed = backup_media()
|
||||||
|
if completed.returncode == 0:
|
||||||
|
return Response()
|
||||||
|
else:
|
||||||
|
raise APIException(completed.stdout)
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-28 06:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inm', '0032_auto_20220222_0941'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='fifoitem',
|
||||||
|
name='expiration_date',
|
||||||
|
field=models.DateField(blank=True, null=True, verbose_name='有效期'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -105,6 +105,7 @@ class FIFOItem(BaseModel):
|
||||||
batch = models.CharField('批次号', max_length=100, default='')
|
batch = models.CharField('批次号', max_length=100, default='')
|
||||||
fifo = models.ForeignKey(FIFO, verbose_name='关联出入库',
|
fifo = models.ForeignKey(FIFO, verbose_name='关联出入库',
|
||||||
on_delete=models.CASCADE)
|
on_delete=models.CASCADE)
|
||||||
|
expiration_date = models.DateField('有效期', null=True, blank=True)
|
||||||
subproduction_plan = models.ForeignKey(
|
subproduction_plan = models.ForeignKey(
|
||||||
SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True)
|
SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
files = models.ManyToManyField(File, verbose_name='上传材料', blank=True)
|
files = models.ManyToManyField(File, verbose_name='上传材料', blank=True)
|
||||||
|
|
|
@ -80,7 +80,7 @@ class FIFOItemCreateSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FIFOItem
|
model = FIFOItem
|
||||||
fields = ['warehouse',
|
fields = ['warehouse',
|
||||||
'material', 'batch', 'fifo', 'files', 'pu_order_item', 'count']
|
'material', 'batch', 'fifo', 'files', 'pu_order_item', 'count', 'expiration_date']
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
fifo = validated_data['fifo']
|
fifo = validated_data['fifo']
|
||||||
|
@ -106,7 +106,7 @@ class FIFOItemCreateSerializer(serializers.ModelSerializer):
|
||||||
class FIFOItemUpdateSerializer(serializers.ModelSerializer):
|
class FIFOItemUpdateSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FIFOItem
|
model = FIFOItem
|
||||||
fields = ['warehouse', 'batch', 'files', 'count']
|
fields = ['warehouse', 'batch', 'files', 'count', 'expiration_date']
|
||||||
|
|
||||||
class FIFOItemSerializer(serializers.ModelSerializer):
|
class FIFOItemSerializer(serializers.ModelSerializer):
|
||||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||||
|
@ -128,7 +128,7 @@ class FIFODetailInPurSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FIFOItem
|
model = FIFOItem
|
||||||
fields = ['material', 'count', 'batch', 'details', 'warehouse']
|
fields = ['material', 'count', 'batch', 'details', 'warehouse', 'expiration_date']
|
||||||
|
|
||||||
def validate_batch(self, value):
|
def validate_batch(self, value):
|
||||||
if value == '':
|
if value == '':
|
||||||
|
|
|
@ -5,6 +5,8 @@ from apps.mtm.models import Material
|
||||||
from apps.sam.models import SalePack, SaleProduct
|
from apps.sam.models import SalePack, SaleProduct
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.db.models.aggregates import Sum
|
from django.db.models.aggregates import Sum
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger('log')
|
||||||
|
|
||||||
class InmService:
|
class InmService:
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -12,7 +14,8 @@ class InmService:
|
||||||
"""
|
"""
|
||||||
更新库存(正反)
|
更新库存(正反)
|
||||||
"""
|
"""
|
||||||
if instance.type in [FIFO.FIFO_TYPE_PUR_IN, FIFO.FIFO_TYPE_DO_IN]: # 采购入库, 生产入库
|
if instance.type in [FIFO.FIFO_TYPE_PUR_IN,
|
||||||
|
FIFO.FIFO_TYPE_DO_IN, FIFO.FIFO_TYPE_OTHER_IN]: # 采购入库, 生产入库, 其他入库
|
||||||
# 更新相关表
|
# 更新相关表
|
||||||
for i in FIFOItem.objects.filter(fifo=instance):
|
for i in FIFOItem.objects.filter(fifo=instance):
|
||||||
material = i.material
|
material = i.material
|
||||||
|
@ -21,6 +24,8 @@ class InmService:
|
||||||
o2, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=i.batch,\
|
o2, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=i.batch,\
|
||||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':i.batch})
|
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':i.batch})
|
||||||
o2.count = o2.count + i.count
|
o2.count = o2.count + i.count
|
||||||
|
if o2.expiration_date is None:
|
||||||
|
o2.expiration_date = i.expiration_date
|
||||||
o2.save()
|
o2.save()
|
||||||
|
|
||||||
iv, _= Inventory.objects.get_or_create(material=material, warehouse=warehouse, \
|
iv, _= Inventory.objects.get_or_create(material=material, warehouse=warehouse, \
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-26 00:35
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inm', '0032_auto_20220222_0941'),
|
||||||
|
('sam', '0015_sale_ship_pic'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sale',
|
||||||
|
name='iproducts',
|
||||||
|
field=models.ManyToManyField(through='sam.SaleProduct', to='inm.IProduct'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -94,6 +94,7 @@ class Sale(CommonADModel):
|
||||||
receiver_address = models.CharField('收获地址', null=True, blank=True, max_length=200)
|
receiver_address = models.CharField('收获地址', null=True, blank=True, max_length=200)
|
||||||
remark = models.CharField('备注', null=True, blank=True, max_length=200)
|
remark = models.CharField('备注', null=True, blank=True, max_length=200)
|
||||||
ship_pic = models.CharField('物流图片', max_length=200, null=True, blank=True)
|
ship_pic = models.CharField('物流图片', max_length=200, null=True, blank=True)
|
||||||
|
iproducts = models.ManyToManyField('inm.iproduct', through='sam.saleproduct')
|
||||||
|
|
||||||
class SaleProduct(BaseModel):
|
class SaleProduct(BaseModel):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -37,6 +37,7 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
||||||
return SaleListSerializer
|
return SaleListSerializer
|
||||||
return super().get_serializer_class()
|
return super().get_serializer_class()
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
def destroy(self, request, *args, **kwargs):
|
def destroy(self, request, *args, **kwargs):
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
if obj.is_audited:
|
if obj.is_audited:
|
||||||
|
@ -161,6 +162,8 @@ class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, Ge
|
||||||
})
|
})
|
||||||
return Response(SaleProductPackDetailSerializer(instance=obj).data)
|
return Response(SaleProductPackDetailSerializer(instance=obj).data)
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
|
if obj.sale.is_audited:
|
||||||
|
raise exceptions.APIException('该销售记录已审核,不可装箱')
|
||||||
serializer = SaleProductPackSerializer(data=request.data)
|
serializer = SaleProductPackSerializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
vdata = serializer.validated_data
|
vdata = serializer.validated_data
|
||||||
|
@ -180,6 +183,8 @@ class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, Ge
|
||||||
不装箱备注
|
不装箱备注
|
||||||
"""
|
"""
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
|
if obj.sale.is_audited:
|
||||||
|
raise exceptions.APIException('该销售记录已审核,不可填写备注')
|
||||||
serializer = self.get_serializer(data=request.data)
|
serializer = self.get_serializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
vdata = serializer.validated_data
|
vdata = serializer.validated_data
|
||||||
|
|
|
@ -8,6 +8,7 @@ def get_permission_list(user):
|
||||||
"""
|
"""
|
||||||
获取权限列表,可用redis存取
|
获取权限列表,可用redis存取
|
||||||
"""
|
"""
|
||||||
|
perms_list = ['visitor']
|
||||||
if user.is_superuser:
|
if user.is_superuser:
|
||||||
perms_list = ['admin']
|
perms_list = ['admin']
|
||||||
else:
|
else:
|
||||||
|
@ -43,21 +44,19 @@ class RbacPermission(BasePermission):
|
||||||
perms = cache.get(request.user.username + '__perms')
|
perms = cache.get(request.user.username + '__perms')
|
||||||
if not perms:
|
if not perms:
|
||||||
perms = get_permission_list(request.user)
|
perms = get_permission_list(request.user)
|
||||||
if perms:
|
|
||||||
if 'admin' in perms:
|
if 'admin' in perms:
|
||||||
return True
|
return True
|
||||||
elif not hasattr(view, 'perms_map'):
|
elif not hasattr(view, 'perms_map'):
|
||||||
return True
|
return True
|
||||||
else:
|
|
||||||
perms_map = view.perms_map
|
|
||||||
_method = request._request.method.lower()
|
|
||||||
if perms_map:
|
|
||||||
for key in perms_map:
|
|
||||||
if key == _method or key == '*':
|
|
||||||
if perms_map[key] in perms or perms_map[key] == '*':
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
else:
|
else:
|
||||||
|
perms_map = view.perms_map
|
||||||
|
_method = request._request.method.lower()
|
||||||
|
if perms_map:
|
||||||
|
for key in perms_map:
|
||||||
|
if key == _method or key == '*':
|
||||||
|
if perms_map[key] in perms or perms_map[key] == '*':
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_object_permission(self, request, view, obj):
|
def has_object_permission(self, request, view, obj):
|
||||||
|
|
Loading…
Reference in New Issue