Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop

This commit is contained in:
shijing 2022-02-25 13:04:00 +08:00
commit fc8c552a56
23 changed files with 446 additions and 255 deletions

View File

@ -2,6 +2,6 @@
ENV = 'production' ENV = 'production'
# base api # base api
VUE_APP_BASE_API = 'http://47.95.0.242:2222/api' VUE_APP_BASE_API = 'http://49.232.14.174:2222/api'
#VUE_APP_BASE_API = 'http://127.0.0.1:8000/api' #VUE_APP_BASE_API = 'http://127.0.0.1:8000/api'

View File

@ -203,3 +203,11 @@ export function notPackremark(id, data) {
data data
}) })
} }
//物流图片上传
export function ship(id, data) {
return request({
url: `/sam/sale/${id}/up_ship/`,
method: 'POST',
data
})
}

View File

@ -36,7 +36,7 @@
}}</template> }}</template>
</el-table-column> </el-table-column>
<el-table-column label="入库数量"> <el-table-column label="入库数量">
<template slot-scope="scope">{{ scope.row.count }}</template> <template slot-scope="scope">{{ scope.row.count }}</template>
</el-table-column> </el-table-column>
<el-table-column label="是否需要复验" v-if="this.$route.params.pu_order!=null"> <el-table-column label="是否需要复验" v-if="this.$route.params.pu_order!=null">

View File

@ -69,6 +69,13 @@
<span v-else></span> <span v-else></span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="销售状态">
<template slot-scope="scope">{{state_[scope.row.state]}}</template>
</el-table-column>
<!-- <el-table-column align="center" label="操作" width="220px"> <!-- <el-table-column align="center" label="操作" width="220px">
<template slot-scope="scope"> <template slot-scope="scope">
<el-link <el-link
@ -181,6 +188,12 @@
mtestform: { mtestform: {
is_mtestok: false, is_mtestok: false,
}, },
state_: {
10: "可出售",
20: "销售锁定",
30: "已售出",
},
form1: {}, form1: {},
dialogFormVisibleorder: false, dialogFormVisibleorder: false,
orderList: [], orderList: [],

View File

@ -153,12 +153,14 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="关联客户" prop="customer"> <el-form-item label="关联客户" prop="customer" >
<el-select <el-select
style="width: 100%" style="width: 100%"
v-model="sale.customer" v-model="sale.customer"
@change="selectcustomer" @change="selectcustomer"
placeholder="请选择" placeholder="请选择"
:disabled="show"
> >
<el-option <el-option
v-for="item in customeroptions" v-for="item in customeroptions"
@ -170,15 +172,17 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="关联合同" prop="contract"> <el-form-item label="关联合同" prop="contract">
<el-input v-model="sale.contract" placeholder="关联合同" /> <el-input v-model="sale.contract" placeholder="关联合同" :disabled="edit"/>
</el-form-item> </el-form-item>
<el-form-item label="所需产品" prop="product"> <el-form-item label="所需产品" prop="product">
<el-select <el-select
:disabled="show"
style="width: 100%" style="width: 100%"
v-model="sale.product" v-model="sale.product"
@change="selectproduct" @change="selectproduct"
placeholder="请选择" placeholder="请选择"
ref="btn"
> >
<el-option <el-option
v-for="item in materialoptions" v-for="item in materialoptions"
@ -328,6 +332,8 @@ export default {
materialoptions: [], materialoptions: [],
iproductoptions: [], iproductoptions: [],
dialogVisible: false, dialogVisible: false,
show:false,
edit:true,
dialogType: "new", dialogType: "new",
options: [ options: [
{ {
@ -375,9 +381,12 @@ export default {
//选择订单变化 //选择订单变化
selectorder(selval) { selectorder(selval) {
getOrder(selval).then((response) => { getOrder(selval).then((response) => {
if (response.data) { if (response.data) {
this.show=true;
this.sale.customer = response.data.customer; this.sale.customer = response.data.customer;
this.sale.product = response.data.product; this.sale.product = response.data.product;
this.sale.contract = response.data.contract_.name; this.sale.contract = response.data.contract_.name;
this.sale.receiver = response.data.customer_.contact; this.sale.receiver = response.data.customer_.contact;
@ -540,13 +549,25 @@ export default {
//审核 //审核
handleAudit(scope) { handleAudit(scope) {
saleAudit(scope.row.id).then((res) => {
if (res.code >= 200) { this.$confirm("确认审核?", "提示", {
this.$message.success("审核成功成功"); confirmButtonText: "确认",
cancelButtonText: "取消",
type: "success",
})
.then(async () => {
await saleAudit(scope.row.id);
this.getList(); this.getList();
} this.$message.success("审核成功!");
}); })
.catch((err) => {
console.error(err);
});
}, },
}, },
}; };
</script> </script>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-card style="margin-top: 2px"> <el-card style="margin-top: 2px">
<el-descriptions title="基本信息" direction="vertical" :column="8" border> <el-descriptions title="基本信息" direction="vertical" :column="6" border>
<el-descriptions-item label="客户名称" v-if="salesdetail.customer"> <el-descriptions-item label="客户名称" v-if="salesdetail.customer">
{{ salesdetail.customer_.name }}</el-descriptions-item {{ salesdetail.customer_.name }}</el-descriptions-item
> >
@ -15,180 +15,216 @@
> >
{{ salesdetail.product_.specification }}</el-descriptions-item {{ salesdetail.product_.specification }}</el-descriptions-item
> >
<el-descriptions-item label="订单编号" v-if="salesdetail.order">
{{ salesdetail.order_.number }}
</el-descriptions-item>
<el-descriptions-item label="合同名称" v-if="salesdetail.order"> <el-descriptions-item label="合同名称" v-if="salesdetail.order">
{{ salesdetail.order_.contract_.name }}</el-descriptions-item {{ salesdetail.order_.contract_.name }}</el-descriptions-item
> >
<el-descriptions-item label="合同编号" v-if="salesdetail.order">
{{ salesdetail.order_.contract_.number }}</el-descriptions-item
>
<el-descriptions-item label="订单编号" v-if="salesdetail.order">
{{ salesdetail.order_.number }}
</el-descriptions-item>
<el-descriptions-item label="物流详情" v-if="ship_pic!=''">
<el-link :href="salesdetail.ship_pic">物流单</el-link></el-descriptions-item>
</el-descriptions> </el-descriptions>
<el-card class="box-card"> <el-button type="primary" style="margin-top:10px" @click="upload">上传物流信息</el-button>
<div slot="header" class="clearfix"> </el-card>
<span>关联产品信息</span> <el-card class="box-card">
<div slot="header" class="clearfix">
<span>关联产品信息</span>
</div>
<el-table
ref="singleTable"
:data="saleproduct"
highlight-current-row
style="width: 100%"
>
<el-table-column type="index" width="50" />
<el-table-column label="产品编号" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.number }}</template>
</el-table-column>
<el-table-column label="产品名称" show-overflow-tooltip>
<template slot-scope="scope">{{
scope.row.iproduct_.material_.name
}}</template>
</el-table-column>
<el-table-column label="批次">
<template slot-scope="scope">{{
scope.row.iproduct_.batch
}}</template>
</el-table-column>
<el-table-column label="仓库">
<template slot-scope="scope">{{
scope.row.iproduct_.warehouse_.name
}}</template>
</el-table-column>
<el-table-column label="是否已军检">
<template slot-scope="scope">
<el-tag v-if="scope.row.is_mtested == false">未军检</el-tag>
<el-tag v-else>已军检</el-tag></template
>
</el-table-column>
<el-table-column label="军检">
<template slot-scope="scope">
<el-tag v-if="scope.row.is_mtestok == false">不合格</el-tag>
<el-tag v-else>合格</el-tag></template
>
</el-table-column>
<el-table-column label="装箱单号" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.packnum }}</template>
</el-table-column>
<el-table-column label="未装箱说明" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.remark }}</template>
</el-table-column>
<el-table-column align="center" label="操作" width="220px">
<template slot-scope="scope">
<el-link
v-if="checkPermission(['warehouse_delete'])"
type="primary"
@click="handlePack(scope)"
>装箱</el-link
>
<el-link
v-if="checkPermission(['warehouse_delete'])"
type="primary"
@click="handleNotPack(scope)"
>备注</el-link
>
<el-link
v-if="checkPermission(['warehouse_delete'])"
type="danger"
@click="handleDelete(scope)"
>删除</el-link
>
</template>
</el-table-column>
</el-table>
<el-dialog
:close-on-click-modal="false"
:visible.sync="dialogVisibless"
title="上传物流文件"
>
<el-form
ref="Forms"
:model="ship"
label-width="100px"
label-position="right"
:rules="rule1"
>
<el-form-item label="文件" prop="template" >
<el-upload
ref="upload"
:action="upUrl"
:on-preview="handlePreview"
:on-success="handleUpSuccess"
:on-remove="handleRemove"
:headers="upHeaders"
:file-list="fileList"
:limit="1"
accept="webp,bmp,jpg,png,tif,gif,apng"
>
<el-button size="small" type="primary">上传文件</el-button>
</el-upload>
</el-form-item>
</el-form>
<div style="text-align: right">
<el-button type="danger" @click="dialogVisibless = false">取消</el-button>
<el-button type="primary" @click="uploadship">确认</el-button>
</div>
</el-dialog>
<el-dialog
:visible.sync="dialogVisible"
:close-on-click-modal="false"
width="60%"
:title="dialogType === 'edit' ? '编辑装箱单' : '新增装箱单'"
>
<el-form
ref="Form"
:model="packData"
label-width="100px"
label-position="right"
>
<el-form-item label="装箱单号" prop="packnum">
<el-input v-model="packData.packnum" placeholder="装箱单号" />
</el-form-item>
<el-form-item label="装箱文件确认" prop="iproducts">
<el-table
:data="packlist"
border
fit
stripe
highlight-current-row
ref="multipleTable"
height="300"
>
<el-table-column type="index" width="50" label="序号" />
<el-table-column label="名称">
<template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column>
<el-table-column label="单位">
<template slot-scope="scope">{{ scope.row.unit }}</template>
</el-table-column>
<el-table-column label="数量" width="150">
<template slot-scope="scope">
<el-form :model="scope.row">
<el-form-item size="mini">
<el-input-number
v-model="scope.row.count"
:min="0"
:value="0"
></el-input-number>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column label="库存数量">
<template slot-scope="scope" v-if="scope.row.material_">{{
scope.row.material_.count
}}</template>
</el-table-column>
<el-table-column label="安全库存数量">
<template slot-scope="scope" v-if="scope.row.material_">{{
scope.row.material_.count_safe
}}</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<div style="text-align: right">
<el-button type="danger" @click="dialogVisible = false"
>取消</el-button
>
<el-button type="primary" @click="submitPack">确认</el-button>
</div> </div>
<el-table </el-dialog>
ref="singleTable" <el-dialog
:data="saleproduct" :visible.sync="dialogVisibles"
highlight-current-row :close-on-click-modal="false"
style="width: 100%" width="60%"
title="未装箱备注"
>
<el-form
ref="Form"
:model="notpackData"
label-width="100px"
label-position="right"
> >
<el-table-column type="index" width="50" /> <el-form-item label="备注" prop="remark">
<el-table-column label="产品编号" show-overflow-tooltip> <el-input v-model="notpackData.remark" placeholder="未装箱备注" />
<template slot-scope="scope">{{ scope.row.number }}</template> </el-form-item>
</el-table-column> </el-form>
<div style="text-align: right">
<el-table-column label="产品名称" show-overflow-tooltip> <el-button type="danger" @click="dialogVisibles = false"
<template slot-scope="scope">{{ >取消</el-button
scope.row.iproduct_.material_.name
}}</template>
</el-table-column>
<el-table-column label="批次">
<template slot-scope="scope">{{
scope.row.iproduct_.batch
}}</template>
</el-table-column>
<el-table-column label="仓库">
<template slot-scope="scope">{{
scope.row.iproduct_.warehouse_.name
}}</template>
</el-table-column>
<el-table-column label="是否已军检">
<template slot-scope="scope">
<el-tag v-if="scope.row.is_mtested == false">未军检</el-tag>
<el-tag v-else>已军检</el-tag></template
>
</el-table-column>
<el-table-column label="军检">
<template slot-scope="scope">
<el-tag v-if="scope.row.is_mtestok == false">不合格</el-tag>
<el-tag v-else>合格</el-tag></template
>
</el-table-column>
<el-table-column label="装箱单号" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.packnum }}</template>
</el-table-column>
<el-table-column label="未装箱说明" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.remark }}</template>
</el-table-column>
<el-table-column align="center" label="操作" width="220px">
<template slot-scope="scope">
<el-link
v-if="checkPermission(['warehouse_delete'])"
type="primary"
@click="handlePack(scope)"
>装箱</el-link
>
<el-link
v-if="checkPermission(['warehouse_delete'])"
type="primary"
@click="handleNotPack(scope)"
>备注</el-link
>
<el-link
v-if="checkPermission(['warehouse_delete'])"
type="danger"
@click="handleDelete(scope)"
>删除</el-link
>
</template>
</el-table-column>
</el-table>
<el-dialog
:visible.sync="dialogVisible"
:close-on-click-modal="false"
width="60%"
:title="dialogType === 'edit' ? '编辑装箱单' : '新增装箱单'"
>
<el-form
ref="Form"
:model="packData"
label-width="100px"
label-position="right"
> >
<el-form-item label="装箱单号" prop="packnum"> <el-button type="primary" @click="submitnotPack">确认</el-button>
<el-input v-model="packData.packnum" placeholder="装箱单号" /> </div>
</el-form-item> </el-dialog>
<el-form-item label="装箱文件确认" prop="iproducts">
<el-table
:data="packlist"
border
fit
stripe
highlight-current-row
ref="multipleTable"
height="300"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column type="index" width="50" label="序号" />
<el-table-column label="名称">
<template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column>
<el-table-column label="单位">
<template slot-scope="scope">{{ scope.row.unit }}</template>
</el-table-column>
<el-table-column label="数量">
<template slot-scope="scope">
<el-form :model="scope.row">
<el-form-item size="mini">
<el-input-number
v-model="scope.row.count"
:min="0"
:value="0"
></el-input-number>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column label="库存数量">
<template slot-scope="scope" v-if="scope.row.material_">{{
scope.row.material_.count
}}</template>
</el-table-column>
<el-table-column label="安全库存数量">
<template slot-scope="scope" v-if="scope.row.material_">{{
scope.row.material_.count_safe
}}</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<div style="text-align: right">
<el-button type="danger" @click="dialogVisible = false"
>取消</el-button
>
<el-button type="primary" @click="submitPack">确认</el-button>
</div>
</el-dialog>
<el-dialog
:visible.sync="dialogVisibles"
:close-on-click-modal="false"
width="60%"
title="未装箱备注"
>
<el-form
ref="Form"
:model="notpackData"
label-width="100px"
label-position="right"
>
<el-form-item label="备注" prop="remark">
<el-input v-model="notpackData.remark" placeholder="未装箱备注" />
</el-form-item>
</el-form>
<div style="text-align: right">
<el-button type="danger" @click="dialogVisibles = false"
>取消</el-button
>
<el-button type="primary" @click="submitnotPack">确认</el-button>
</div>
</el-dialog>
</el-card>
</el-card> </el-card>
</div> </div>
</template> </template>
@ -200,14 +236,15 @@ import {
gePack, gePack,
subPack, subPack,
notPackremark, notPackremark,
ship
} from "@/api/sam"; } from "@/api/sam";
import checkPermission from "@/utils/permission"; import checkPermission from "@/utils/permission";
import { upUrl, upHeaders } from "@/api/file";
import { genTree } from "@/utils"; import { genTree } from "@/utils";
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
const defaultepackData = { const defaultepackData = {
packnum: "" packnum: "",
} };
export default { export default {
components: { Pagination }, components: { Pagination },
data() { data() {
@ -215,17 +252,22 @@ export default {
salesdetail: "", salesdetail: "",
saleproduct: "", saleproduct: "",
packlist: [], packlist: [],
upHeaders: upHeaders(),
upUrl: upUrl(),
dialogVisible: false, dialogVisible: false,
dialogVisibles:false, dialogVisibles: false,
packData:defaultepackData, dialogVisibless: false,
notpackData:{remark:""}, ship:{},
packData: defaultepackData,
notpackData: { remark: "" },
detail: [], detail: [],
fileList:[],
saleproductId: null, saleproductId: null,
saleProductid:null, saleProductid: null,
dialogType: "new", dialogType: "new",
}; };
}, },
computed: {}, computed: {},
watch: {}, watch: {},
created() { created() {
@ -243,6 +285,39 @@ export default {
} }
}); });
}, },
//上传物流文件
handlePreview(file) {
if ("url" in file) {
window.open(file.url);
} else {
window.open(file.response.data.path);
}
},
handleUpSuccess(res, file, filelist) {
this.ship.path = res.data.path;
console.log(this.ship.path)
},
handleRemove(file, filelist){
this.ship.path = null;
},
upload() {
this.dialogVisibless=true;
},
uploadship()
{
console.log(this.ship);
ship(this.id, this.ship).then((res) => {
if (res.code >= 200) {
this.dialogVisibless = false;
this.$message.success("物流文件上传成功!");
}
});
},
getSaleproductLists() { getSaleproductLists() {
getSaleproductList({ sale: this.id, page: 0 }).then((response) => { getSaleproductList({ sale: this.id, page: 0 }).then((response) => {
@ -268,31 +343,24 @@ export default {
}, },
//装箱操作 //装箱操作
handlePack(scope) { handlePack(scope) {
this.packData = Object.assign({}, scope.row); this.packData = Object.assign({}, scope.row);
this.dialogType = "new"; this.dialogType = "new";
this.dialogVisible = true; this.dialogVisible = true;
this.$nextTick(() => { this.$nextTick(() => {
this.$refs["Form"].clearValidate(); this.$refs["Form"].clearValidate();
}); });
gePack(scope.row.id).then((response) => { gePack(scope.row.id).then((response) => {
if (response.data) { if (response.data) {
this.packlist = response.data.detail; this.packlist = response.data.detail;
} }
}); });
this.saleproductId = scope.row.id; this.saleproductId = scope.row.id;
}, },
submitPack() { submitPack() {
this.$refs.multipleTable.selection.forEach((item) => { this.packData.detail = this.packlist;
this.detail.push({ console.log(this.packData);
id: item.id,
count: item.count,
});
});
console.log( this.detail);
this.packData.detail = this.detail;
subPack(this.saleproductId, this.packData).then((res) => { subPack(this.saleproductId, this.packData).then((res) => {
if (res.code >= 200) { if (res.code >= 200) {
this.getSaleproductLists(); this.getSaleproductLists();
@ -302,14 +370,11 @@ export default {
}); });
}, },
//未装箱备注 //未装箱备注
handleNotPack(scope) handleNotPack(scope) {
{ this.dialogVisibles = true;
this.dialogVisibles=true; this.saleProductid = scope.row.id;
this.saleProductid=scope.row.id; },
} submitnotPack() {
,
submitnotPack()
{
notPackremark(this.saleProductid, this.notpackData).then((res) => { notPackremark(this.saleProductid, this.notpackData).then((res) => {
if (res.code >= 200) { if (res.code >= 200) {
this.getSaleproductLists(); this.getSaleproductLists();
@ -317,7 +382,7 @@ export default {
this.$message.success("成功"); this.$message.success("成功");
} }
}); });
} },
}, },
}; };
</script> </script>

View File

@ -0,0 +1,25 @@
from __future__ import absolute_import, unicode_literals
from rest_framework.response import Response
from celery import shared_task
@shared_task
def backup_database():
"""
备份数据库
"""
import os
ret = os.popen('sudo pg_dump -U postgres -d hberp -f /home/lighthouse/hberp_backup.sql')
return Response(ret.read())
@shared_task
def reload_server():
import os # 更新后端
os.chdir('/home/lighthouse/hberp')
ret = os.popen('sudo git pull && sudo service supervisor reload')
return Response(ret.read())

View File

@ -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 CleanDataView, UpdateCuttingView, UpdateEquipState, UpdateFIFOItem, UpdateFIFONumber, UpdateLastTestResult, UpdateNeedToOrder, UpdateSpg from apps.develop.views import BackupDatabase, CleanDataView, ReloadServer, UpdateCuttingView, UpdateEquipState, UpdateFIFOItem, UpdateFIFONumber, UpdateLastTestResult, UpdateNeedToOrder, UpdateSpg
urlpatterns = [ urlpatterns = [
path('cleandata/', CleanDataView.as_view()), path('cleandata/', CleanDataView.as_view()),
@ -13,6 +13,8 @@ urlpatterns = [
path('update_spg/', UpdateSpg.as_view()), path('update_spg/', UpdateSpg.as_view()),
path('update_equip_state/', UpdateEquipState.as_view()), path('update_equip_state/', UpdateEquipState.as_view()),
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('backup_database/', BackupDatabase.as_view())
] ]

View File

@ -4,6 +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.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
@ -117,4 +118,15 @@ class UpdateFIFONumber(APIView):
else: else:
i.number = 'CK' + ranstr(7) i.number = 'CK' + ranstr(7)
i.save() i.save()
return Response() return Response()
class ReloadServer(APIView):
permission_classes = [IsAdminUser]
def post(self, request):
reload_server()
class BackupDatabase(APIView):
permission_classes = [IsAdminUser]
def post(self, request):
backup_database()

View File

@ -17,36 +17,34 @@ class HRMService:
f.write(base64_data) f.write(base64_data)
try: try:
unknown_picture = face_recognition.load_image_file(filepath) unknown_picture = face_recognition.load_image_file(filepath)
unknown_face_encoding = face_recognition.face_encodings(unknown_picture)[0] unknown_face_encoding = face_recognition.face_encodings(unknown_picture, num_jitters=2)[0]
os.remove(filepath) os.remove(filepath)
except: except:
os.remove(filepath) os.remove(filepath)
return None, '人脸识别失败' return None, '识别失败,请调整位置'
# 匹配人脸库 # 匹配人脸库
face_datas = cache.get('face_datas') face_datas = cache.get('face_datas')
face_users = cache.get('face_users')
if face_datas is None: if face_datas is None:
update_all_user_facedata_cache() update_all_user_facedata_cache()
try: face_datas = cache.get('face_datas')
results = face_recognition.compare_faces(face_datas, face_users = cache.get('face_users')
unknown_face_encoding, tolerance=0.48) results = face_recognition.compare_faces(face_datas,
except: unknown_face_encoding, tolerance=0.45)
return None, '人脸匹配失败'
for index, value in enumerate(results): for index, value in enumerate(results):
if value: if value:
# 识别成功 # 识别成功
user = User.objects.get(id=face_users[index]) user = User.objects.get(id=face_users[index])
return user, '' return user, ''
return None, '人脸匹配失败' return None, '人脸未匹配,请调整位置'
@classmethod @classmethod
def get_facedata_from_img(cls, img_path): def get_facedata_from_img(cls, img_path):
try: try:
photo_path = settings.BASE_DIR + img_path photo_path = settings.BASE_DIR + img_path
picture_of_me = face_recognition.load_image_file(photo_path) picture_of_me = face_recognition.load_image_file(photo_path)
my_face_encoding = face_recognition.face_encodings(picture_of_me)[0] my_face_encoding = face_recognition.face_encodings(picture_of_me, num_jitters=2)[0]
face_data_list = my_face_encoding.tolist() face_data_list = my_face_encoding.tolist()
return face_data_list, '' return face_data_list, ''
except: except:
return None, '人脸识别失败' return None, '人脸数据获取失败请重新上传图片'

View File

@ -183,6 +183,7 @@ class FaceLogin(CreateAPIView):
return Response({ return Response({
'refresh': str(refresh), 'refresh': str(refresh),
'access': str(refresh.access_token), 'access': str(refresh.access_token),
'username':user.username 'username':user.username,
'name':user.name
}) })
return Response(msg, status=status.HTTP_400_BAD_REQUEST) return Response(msg, status=status.HTTP_400_BAD_REQUEST)

View File

@ -55,23 +55,18 @@ class InmService:
for i in FIFOItem.objects.filter(fifo=instance): for i in FIFOItem.objects.filter(fifo=instance):
material = i.material material = i.material
warehouse = i.warehouse warehouse = i.warehouse
o1 = Inventory.objects.get(material=material, warehouse=warehouse) mb = MaterialBatch.objects.get(material=material, warehouse=warehouse, batch=i.batch)
temp_count = o1.count - i.count temp_count = mb.count - i.count
if temp_count < 0:
raise ValidationError('仓库库存不足,操作失败')
o1.count = temp_count
o1.save()
print(i.batch)
o2 = MaterialBatch.objects.get(material=material, warehouse=warehouse, batch=i.batch)
temp_count = o2.count - i.count
if temp_count < 0: if temp_count < 0:
raise ValidationError('批次库存不足,操作失败') raise ValidationError('批次库存不足,操作失败')
o2.count = temp_count mb.count = temp_count
o2.save() mb.save()
temp_count = material.count - i.count
if temp_count < 0: iv = Inventory.objects.get(material=material, warehouse=warehouse)
raise ValidationError('物料库存不足,操作失败') iv.count = MaterialBatch.objects.filter(material=material, warehouse=warehouse).count()
material.count = temp_count iv.save()
material.count = MaterialBatch.objects.filter(material=material).count()
material.save() material.save()
# 删除IProduct # 删除IProduct

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-02-25 01:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sam', '0014_auto_20220222_1530'),
]
operations = [
migrations.AddField(
model_name='sale',
name='ship_pic',
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='物流图片'),
),
]

View File

@ -93,6 +93,7 @@ class Sale(CommonADModel):
receiver_phone = models.CharField('收货人联系电话', null=True, blank=True, max_length=20) receiver_phone = models.CharField('收货人联系电话', null=True, blank=True, max_length=20)
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)
class SaleProduct(BaseModel): class SaleProduct(BaseModel):
""" """

View File

@ -97,3 +97,6 @@ class SaleProductPackSerializer(serializers.ModelSerializer):
class SRemarkItemCreateSerializer(serializers.Serializer): class SRemarkItemCreateSerializer(serializers.Serializer):
remark = serializers.CharField(min_length=6) remark = serializers.CharField(min_length=6)
class SaleUpShipPicSerializer(serializers.Serializer):
path = serializers.CharField(min_length=4, max_length=200)

View File

@ -6,7 +6,7 @@ from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
from apps.inm.services import InmService from apps.inm.services import InmService
from apps.mtm.models import Material, PackItem from apps.mtm.models import Material, PackItem
from apps.sam.models import Sale, SalePack, SaleProduct from apps.sam.models import Sale, SalePack, SaleProduct
from apps.sam.serializers_sale import SRemarkItemCreateSerializer, SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer, SaleProductPackDetailSerializer, SaleProductPackSerializer from apps.sam.serializers_sale import SRemarkItemCreateSerializer, SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer, SaleProductPackDetailSerializer, SaleProductPackSerializer, SaleUpShipPicSerializer
from rest_framework import exceptions from rest_framework import exceptions
from django.db import transaction from django.db import transaction
from rest_framework.decorators import action from rest_framework.decorators import action
@ -85,8 +85,6 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
fifo.sale = obj fifo.sale = obj
fifo.type = FIFO.FIFO_TYPE_SALE_OUT fifo.type = FIFO.FIFO_TYPE_SALE_OUT
fifo.is_audited = False fifo.is_audited = False
fifo.auditor = request.user
fifo.inout_date = timezone.now()
fifo.create_by = request.user fifo.create_by = request.user
fifo.number = 'CK' + ranstr(7) fifo.number = 'CK' + ranstr(7)
fifo.save() fifo.save()
@ -95,6 +93,20 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
obj.save() obj.save()
return Response() return Response()
@action(methods=['post'], detail=True, perms_map={'post':'sale_up_ship'}, serializer_class=SaleUpShipPicSerializer)
@transaction.atomic
def up_ship(self, request, pk=None):
"""
上传物流信息
"""
serializer = SaleUpShipPicSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
obj = self.get_object()
obj.ship_pic = vdata['path']
obj.save()
return Response()

4
hb_server/cbeat_start.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
cd /home/lighthouse/hberp/hb_server
source venv/bin/activate
exec celery -A server beat -l info

View File

@ -0,0 +1,4 @@
#!/bin/bash
cd /home/lighthouse/hberp/hb_server
source venv/bin/activate
exec celery -A server worker -l info

View File

@ -0,0 +1,4 @@
#!/bin/bash
cd /home/lighthouse/hberp/hb_server
source venv/bin/activate
exec gunicorn -w 5 -b 0.0.0.0:2223 server.wsgi

View File

@ -15,3 +15,4 @@ numpy==1.21.2
workalendar==16.2.0 workalendar==16.2.0
face_recognition==1.3.0 face_recognition==1.3.0
gunicorn==20.1.0 gunicorn==20.1.0
redis==4.1.4

View File

@ -158,7 +158,7 @@ REST_FRAMEWORK = {
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
], ],
'DEFAULT_PERMISSION_CLASSES': [ 'DEFAULT_PERMISSION_CLASSES': [
# 'rest_framework.permissions.IsAuthenticated', 'rest_framework.permissions.AllowAny',
'apps.system.permission.RbacPermission' 'apps.system.permission.RbacPermission'
], ],
'DEFAULT_RENDERER_CLASSES': [ 'DEFAULT_RENDERER_CLASSES': [

View File

@ -25,21 +25,25 @@ from rest_framework import routers
from rest_framework.documentation import include_docs_urls from rest_framework.documentation import include_docs_urls
from django.views.generic import TemplateView from django.views.generic import TemplateView
from utils.view import GenSignature, UpdateDevelop from utils.view import GenSignature, UpdateDevelop
import os
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register('', FileViewSet, basename="file") router.register('', FileViewSet, basename="file")
schema_view = get_schema_view( schema_dict = dict(
openapi.Info( info=openapi.Info(
title="航玻ERP API", title="航玻ERP API",
default_version='v1', default_version='v1',
contact=openapi.Contact(email="caoqianming@foxmail.com"), contact=openapi.Contact(email="caoqianming@foxmail.com"),
license=openapi.License(name="MIT License"), license=openapi.License(name="MIT License"),
), ),
public=True, public=True,
permission_classes=[], permission_classes=[],)
url="http://49.232.14.174:2222/"
) if os.getenv('DJANGO_SETTINGS_MODULE') != 'server.settings_dev':
schema_dict['url'] = "http://49.232.14.174:2222/"
schema_view = get_schema_view(**schema_dict)
urlpatterns = [ urlpatterns = [
path('api/admin/doc/', include('django.contrib.admindocs.urls')), path('api/admin/doc/', include('django.contrib.admindocs.urls')),

View File

@ -78,15 +78,15 @@ class UpdateDevelop(APIView):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
import os import os
# 更新后端 # 更新后端
os.chdir('/home/hberp') os.chdir('/home/lighthouse/hberp')
ret = os.popen('git pull https://caoqianming%40foxmail.com:9093qqww@e.coding.net/ctcdevteam/hberp/hberp.git develop') ret = os.popen('sudo git pull && sudo service supervisor reload')
# 奇怪的处理 # 奇怪的处理
os.chdir('/home/hberp/hb_server/vuedist') # os.chdir('/home/hberp/hb_server/vuedist')
os.popen('cp index.html indexbak') # os.popen('cp index.html indexbak')
time.sleep(1000) # time.sleep(1000)
os.popen('rm -rf index.html') # os.popen('rm -rf index.html')
time.sleep(1000) # time.sleep(1000)
os.popen('mv -f indexbak index.html') # os.popen('mv -f indexbak index.html')
# 打包前端 # 打包前端
# os.chdir('/home/hberp/hb_client') # os.chdir('/home/hberp/hb_client')
# os.system('npm run build:prod') # os.system('npm run build:prod')