更新生产计划、销售订单、工作订单和仓库发料功能
This commit is contained in:
@@ -140,3 +140,20 @@ export function revokeIssue(mbomId: number): Promise<void> {
|
||||
export function calcBom(planId: number): Promise<void> {
|
||||
return request.put(`/erp/mp/plan/bom-calculate/${planId}`)
|
||||
}
|
||||
|
||||
// 齐套检查:查询物料清单的子件库存情况
|
||||
export interface StockCheckItem {
|
||||
itemCode: string
|
||||
itemName: string
|
||||
unitName?: string
|
||||
requiredQty: number
|
||||
availableQty: number
|
||||
shortage: number
|
||||
isShortage: boolean
|
||||
}
|
||||
|
||||
export function checkMbomStock(mbomId: number): Promise<StockCheckItem[]> {
|
||||
return request.get(`/erp/mp/mbom/stock-check/${mbomId}`).then((res: any) => {
|
||||
return res.data ?? res.rows ?? res ?? []
|
||||
})
|
||||
}
|
||||
|
||||
@@ -57,6 +57,12 @@ export interface ProductionPlan {
|
||||
slaveList?: PlanLine[]
|
||||
/** 部门名称(单据视图) */
|
||||
deptName?: string
|
||||
/** 客户ID(从关联销售订单带入) */
|
||||
clientId?: number
|
||||
/** 客户编码(从关联销售订单带入) */
|
||||
clientCode?: string
|
||||
/** 客户名称(从关联销售订单带入) */
|
||||
clientName?: string
|
||||
/** 物料清单(BOM运算结果,详情页只读) */
|
||||
mbomList?: MbomLine[]
|
||||
/** 补料清单(详情页只读) */
|
||||
@@ -187,6 +193,7 @@ export const PLAN_STATUS_MAP: Record<string, { label: string; type: string }> =
|
||||
|
||||
export const BUSINESS_STATUS_OPTIONS = [
|
||||
{ value: 'NORMAL', label: '正常' },
|
||||
{ value: 'BOM_CALCULATED', label: '已运算' },
|
||||
{ value: 'PAUSE', label: '暂停' },
|
||||
{ value: 'CANCEL', label: '取消' }
|
||||
]
|
||||
@@ -295,7 +302,7 @@ export function getImportOrderList(params?: {
|
||||
return request.get('/erp/sl/order/list', {
|
||||
params: {
|
||||
...params,
|
||||
orderStatus: '审核',
|
||||
status: 'APPROVED',
|
||||
pageNum: 1,
|
||||
pageSize: 100
|
||||
}
|
||||
@@ -306,9 +313,9 @@ export function getImportOrderList(params?: {
|
||||
orderId: row.orderId,
|
||||
orderCode: row.orderCode,
|
||||
orderDate: row.orderDate,
|
||||
userId: row.salesmanId,
|
||||
userName: row.salesmanName,
|
||||
salesmanName: row.salesmanName,
|
||||
userId: row.salesUserId ?? row.salesmanId,
|
||||
userName: row.salesUserName ?? row.salesmanName,
|
||||
salesmanName: row.salesUserName ?? row.salesmanName,
|
||||
clientName: row.clientName,
|
||||
deliveryDate: row.deliveryDate,
|
||||
deliveryStatus: row.deliveryDate && new Date(row.deliveryDate) < new Date() ? '超期' : '预计',
|
||||
|
||||
@@ -123,10 +123,11 @@ export interface SalesOrderDetailListResponse {
|
||||
|
||||
export const ORDER_STATUS_MAP: Record<string, { label: string; type: string }> = {
|
||||
'DRAFT': { label: '草稿', type: 'info' },
|
||||
'开立': { label: '开立', type: '' },
|
||||
'审核': { label: '审核', type: 'success' },
|
||||
'退回': { label: '退回', type: 'warning' },
|
||||
'关闭': { label: '关闭', type: 'danger' }
|
||||
'PREPARE': { label: '开立', type: '' },
|
||||
'APPROVED': { label: '已审核', type: 'success' },
|
||||
'REJECTED': { label: '退回', type: 'warning' },
|
||||
'FINISHED': { label: '已完成', type: 'info' },
|
||||
'CANCELED': { label: '关闭', type: 'danger' },
|
||||
}
|
||||
|
||||
export const SALES_TYPE_OPTIONS = [
|
||||
@@ -162,9 +163,10 @@ const BASE = '/erp/sl/order'
|
||||
function normalizeOrderRow(row: any): any {
|
||||
return {
|
||||
...row,
|
||||
orderStatus: row.orderStatus ?? row.status ?? '',
|
||||
salesmanId: row.salesmanId ?? row.salesUserId,
|
||||
salesmanName: row.salesmanName ?? row.salesUserName ?? '',
|
||||
salesType: row.salesType ?? row.saleType ?? '',
|
||||
salesType: row.salesType ?? row.orderType ?? row.saleType ?? '',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,11 +199,13 @@ export function getSalesOrderDetail(orderId: number): Promise<SalesOrder> {
|
||||
// 后端返回 salesUserId/salesUserName,前端表单使用 salesmanId/salesmanName,便于下拉回显
|
||||
if (data.salesUserId !== undefined) data.salesmanId = data.salesUserId
|
||||
if (data.salesUserName !== undefined) data.salesmanName = data.salesUserName
|
||||
// 审核信息字段别名映射(后端可能使用 checkBy/checkDate 等命名)
|
||||
// 审核信息字段别名映射
|
||||
// 使用 == null 而非 ! 判断,避免 auditorId=0 或 auditorName='' 被误判为缺失
|
||||
if (data.auditorId == null) data.auditorId = data.checkUserId ?? data.checkById ?? data.auditById
|
||||
if (data.auditorName == null) data.auditorName = data.checkUserName ?? data.checkByName ?? data.auditByName ?? data.auditUser
|
||||
if (data.auditDate == null) data.auditDate = data.checkDate ?? data.auditTime ?? data.checkTime
|
||||
if (data.auditorId == null) data.auditorId = data.approverId ?? data.checkUserId ?? data.checkById ?? data.auditById
|
||||
if (data.auditorName == null) data.auditorName = data.approverName ?? data.checkUserName ?? data.checkByName ?? data.auditByName ?? data.auditUser
|
||||
if (data.auditDate == null) data.auditDate = data.approveDate ?? data.checkDate ?? data.auditTime ?? data.checkTime
|
||||
// 统一状态字段
|
||||
if (data.orderStatus == null) data.orderStatus = data.status ?? ''
|
||||
return data
|
||||
})
|
||||
}
|
||||
@@ -216,6 +220,10 @@ function buildOrderPayload(data: Partial<SalesOrder>): Record<string, unknown> {
|
||||
// 后端实体为 salesUserId / salesUserName,前端表单为 salesmanId / salesmanName,此处统一发给后端
|
||||
if (payload.salesmanId !== undefined) payload.salesUserId = payload.salesmanId
|
||||
if (payload.salesmanName !== undefined) payload.salesUserName = payload.salesmanName
|
||||
// 后端实体用 orderType 存储销售类型,前端表单用 salesType
|
||||
if (payload.salesType !== undefined) payload.orderType = payload.salesType
|
||||
// 前端用 orderStatus,后端实体字段为 status
|
||||
if (payload.orderStatus !== undefined) payload.status = payload.orderStatus
|
||||
return payload
|
||||
}
|
||||
|
||||
|
||||
@@ -208,6 +208,7 @@
|
||||
|
||||
<el-table
|
||||
:data="formData.lines"
|
||||
class="order-lines-table"
|
||||
stripe
|
||||
border
|
||||
style="width: 100%"
|
||||
@@ -225,7 +226,6 @@
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<span v-else>{{ formatNumber(row.quantity) }}</span>
|
||||
@@ -236,7 +236,6 @@
|
||||
<el-input
|
||||
v-if="!isView"
|
||||
v-model="row.qualityReq"
|
||||
size="small"
|
||||
placeholder="质量要求"
|
||||
/>
|
||||
<span v-else>{{ row.qualityReq || '-' }}</span>
|
||||
@@ -247,7 +246,6 @@
|
||||
<el-input
|
||||
v-if="!isView"
|
||||
v-model="row.remark"
|
||||
size="small"
|
||||
placeholder="备注"
|
||||
/>
|
||||
<span v-else>{{ row.remark || '-' }}</span>
|
||||
@@ -291,17 +289,14 @@
|
||||
<span v-else>{{ row.mbomCode || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mbomStatus" label="单据状态" width="80" />
|
||||
<el-table-column prop="businessType" label="业务类型" width="100" />
|
||||
<el-table-column prop="issueStatus" label="状态" width="90">
|
||||
<el-table-column prop="mbomStatus" label="单据状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-if="canEditMbom"
|
||||
:model-value="row.issueStatus === 'ISSUED'"
|
||||
:loading="mbomSaveLoading[row.mbomId!]"
|
||||
@change="(val: boolean) => handleMbomIssueToggle(row, val)"
|
||||
/>
|
||||
<span v-else>{{ row.issueStatus === 'ISSUED' ? '已下发' : (row.issueStatus || '—') }}</span>
|
||||
{{ getMbomStatusLabel(row.mbomStatus) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="businessType" label="业务类型" width="100">
|
||||
<template #default="{ row }">
|
||||
{{ getBusinessTypeLabel(row.businessType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="itemCode" label="物料编码" width="140" show-overflow-tooltip />
|
||||
@@ -334,9 +329,9 @@
|
||||
{{ formatNumber(row.productionQty) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="workshopName" label="下发车间" width="160">
|
||||
<el-table-column label="下发车间" width="230">
|
||||
<template #default="{ row }">
|
||||
<template v-if="canEditMbom">
|
||||
<div v-if="canEditMbom" style="display: flex; flex-direction: column; gap: 4px;">
|
||||
<el-select
|
||||
v-model="row.workshopId"
|
||||
placeholder="下发车间"
|
||||
@@ -353,24 +348,29 @@
|
||||
:value="w.workshopId!"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<span v-else>{{ row.workshopName || '—' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="issueDate" label="下发时间" width="130">
|
||||
<template #default="{ row }">
|
||||
<div style="display: flex; gap: 4px; align-items: center;">
|
||||
<el-date-picker
|
||||
v-if="canEditMbom"
|
||||
v-model="row.issueDate"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
placeholder="下发日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
style="flex: 1"
|
||||
:disabled="row.issueStatus === 'ISSUED'"
|
||||
@change="(val: string) => handleMbomIssueDateChange(row, val)"
|
||||
/>
|
||||
<span v-else>{{ row.issueDate || '—' }}</span>
|
||||
<el-switch
|
||||
:model-value="row.issueStatus === 'ISSUED'"
|
||||
:loading="mbomSaveLoading[row.mbomId!]"
|
||||
size="small"
|
||||
@change="(val: boolean) => handleMbomIssueToggle(row, val)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>{{ row.workshopName || '—' }}</div>
|
||||
<div style="font-size: 12px; color: #909399;">{{ row.issueDate || '—' }} / {{ row.issueStatus === 'ISSUED' ? '已下发' : '未下发' }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="220" align="center" fixed="right">
|
||||
@@ -400,7 +400,7 @@
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="supCode" label="单据编码" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="supStatus" label="单据状态" width="80" />
|
||||
<el-table-column prop="supStatus" label="单据状态" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="businessType" label="业务类型" width="100" />
|
||||
<el-table-column prop="issueStatus" label="状态" width="80" />
|
||||
<el-table-column prop="itemCode" label="物料编码" width="140" show-overflow-tooltip />
|
||||
@@ -645,6 +645,46 @@
|
||||
<el-button @click="showEbomViewDialog = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 齐套检查弹窗 -->
|
||||
<el-dialog
|
||||
v-model="showStockCheckDialog"
|
||||
title="齐套检查"
|
||||
width="800px"
|
||||
destroy-on-close
|
||||
>
|
||||
<div v-loading="stockCheckLoading">
|
||||
<el-table :data="stockCheckData" border size="small" max-height="400">
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="itemCode" label="物料编码" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="itemName" label="物料名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="unitName" label="主计量" width="80" />
|
||||
<el-table-column prop="requiredQty" label="需求量" width="100" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ formatNumber(row.requiredQty) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="availableQty" label="可用量" width="100" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ formatNumber(row.availableQty) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="shortage" label="缺料量" width="100" align="right">
|
||||
<template #default="{ row }">
|
||||
<span :style="{ color: row.isShortage ? '#f56c6c' : '#67c23a' }">
|
||||
{{ formatNumber(row.shortage) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="stockCheckData.length === 0 && !stockCheckLoading" style="text-align: center; padding: 40px; color: #909399;">
|
||||
暂无数据
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="showStockCheckDialog = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -669,7 +709,7 @@ import {
|
||||
type MbomLine,
|
||||
type ImportOrder
|
||||
} from '@/api/productionPlan'
|
||||
import { calcBom, updateMbom, issueToWorkshop, revokeIssue, getMbomLines, type MbomLine as ApiMbomLine } from '@/api/mbom'
|
||||
import { calcBom, updateMbom, issueToWorkshop, revokeIssue, getMbomLines, checkMbomStock, type MbomLine as ApiMbomLine, type StockCheckItem } from '@/api/mbom'
|
||||
import { listEbom, getEbom, type EbomHeader, type EbomLine } from '@/api/rd/ebom'
|
||||
import { listWorkshop, type Workshop } from '@/api/masterdata/workshop'
|
||||
|
||||
@@ -767,6 +807,11 @@ const ebomViewData = ref<EbomHeader | null>(null)
|
||||
const ebomViewLines = ref<EbomLine[]>([])
|
||||
const ebomViewLoading = ref(false)
|
||||
|
||||
/** 齐套检查弹窗 */
|
||||
const showStockCheckDialog = ref(false)
|
||||
const stockCheckData = ref<StockCheckItem[]>([])
|
||||
const stockCheckLoading = ref(false)
|
||||
|
||||
/** 供应方式选项(生产/加工/装配/采购/委外) */
|
||||
const SUPPLY_TYPE_OPTIONS = [
|
||||
{ value: 'SELF_MADE', label: '生产' },
|
||||
@@ -877,8 +922,24 @@ async function handleBomCalculate() {
|
||||
}
|
||||
|
||||
/** 物料清单 - 齐套检查(占位,后续对接接口) */
|
||||
function handleMbomStockCheck(_row: any) {
|
||||
ElMessage.info('齐套检查功能待对接后端接口')
|
||||
async function handleMbomStockCheck(row: any) {
|
||||
if (!row.mbomId) {
|
||||
ElMessage.warning('物料清单ID不存在')
|
||||
return
|
||||
}
|
||||
|
||||
stockCheckLoading.value = true
|
||||
showStockCheckDialog.value = true
|
||||
stockCheckData.value = []
|
||||
|
||||
try {
|
||||
const data = await checkMbomStock(row.mbomId)
|
||||
stockCheckData.value = data
|
||||
} catch (error: any) {
|
||||
ElMessage.error('齐套检查失败:' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
stockCheckLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 物料清单 - BOM补料(占位,后续对接接口) */
|
||||
@@ -900,6 +961,29 @@ function getSupplyTypeLabel(supplyType?: string): string {
|
||||
return labelMap[supplyType] ?? supplyType
|
||||
}
|
||||
|
||||
/** MBOM 单据状态映射 */
|
||||
function getMbomStatusLabel(status?: string): string {
|
||||
if (!status) return '—'
|
||||
const labelMap: Record<string, string> = {
|
||||
'PREPARE': '开立',
|
||||
'DRAFT': '开立',
|
||||
'APPROVED': '审核',
|
||||
'CLOSED': '关闭'
|
||||
}
|
||||
return labelMap[status] ?? status
|
||||
}
|
||||
|
||||
/** MBOM 业务类型映射 */
|
||||
function getBusinessTypeLabel(businessType?: string): string {
|
||||
if (!businessType) return '—'
|
||||
const labelMap: Record<string, string> = {
|
||||
'BOM_CALC': 'BOM运算',
|
||||
'BOM_SUPPLEMENT': 'BOM补料',
|
||||
'PRODUCTION_SUPPLEMENT': '生产补料'
|
||||
}
|
||||
return labelMap[businessType] ?? businessType
|
||||
}
|
||||
|
||||
/** 打开物料清单汇总弹窗(PRD 6.3.10:标题「计划单号-产品编码-产品名称-数量」- 物料清单,表格为MBOM明细) */
|
||||
function openMbomSummaryDialog() {
|
||||
const planCode = formData.planCode || '计划单'
|
||||
@@ -1554,4 +1638,13 @@ onMounted(async () => {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.order-lines-table :deep(.el-table__body .el-table__cell) {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.order-lines-table :deep(.el-input__wrapper),
|
||||
.order-lines-table :deep(.el-input-number .el-input__wrapper) {
|
||||
min-height: 36px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -214,6 +214,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="planDate" label="单据日期" width="110" />
|
||||
<el-table-column label="操作" width="120" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="handleView(row)">
|
||||
查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 单据视图表格:无序号,复选框,单据编码、单据日期、单据状态、业务类型、业务部门、业务人员、业务状态、审核日期、操作 -->
|
||||
@@ -241,9 +248,9 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="businessType" label="业务类型" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="deptName" label="业务部门" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="operatorName" label="业务人员" width="100" show-overflow-tooltip>
|
||||
<el-table-column prop="businessType" label="业务类型" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="deptName" label="业务部门" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="operatorName" label="业务人员" min-width="100" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.operatorName || row.salesUserName || '-' }}
|
||||
</template>
|
||||
@@ -253,8 +260,12 @@
|
||||
{{ getBusinessStatusLabel(row.businessStatus) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="approveDate" label="审核日期" width="120" />
|
||||
<el-table-column label="操作" width="160" fixed="right">
|
||||
<el-table-column prop="approveDate" label="审核日期" width="120">
|
||||
<template #default="{ row }">
|
||||
{{ row.approveDate ? row.approveDate.slice(0, 10) : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button type="success" link @click="handleView(row)">查看</el-button>
|
||||
<el-button
|
||||
@@ -387,11 +398,11 @@ const queryParams = reactive<PlanQuery>({
|
||||
const quickFilter = ref('')
|
||||
const quickFilterTags = [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '胶带', value: '胶带' },
|
||||
{ label: '机柜', value: '机柜' },
|
||||
{ label: '电脑', value: '电脑' },
|
||||
{ label: '纸杯机', value: '纸杯机' },
|
||||
{ label: '配套机', value: '配套机' }
|
||||
{ label: '模具', value: '模具' },
|
||||
{ label: '注塑件', value: '注塑件' },
|
||||
{ label: '塑料件', value: '塑料件' },
|
||||
{ label: '橡胶件', value: '橡胶件' },
|
||||
{ label: '五金件', value: '五金件' }
|
||||
]
|
||||
|
||||
/** 单据视图数据 */
|
||||
|
||||
@@ -81,42 +81,17 @@
|
||||
:disabled="isView"
|
||||
label-width="90px"
|
||||
>
|
||||
<!-- 表头表单区:5列布局 -->
|
||||
<!-- 表头表单区:4列布局 -->
|
||||
<el-collapse v-model="activeCollapse">
|
||||
<el-collapse-item title="生产订单" name="basic">
|
||||
<el-row :gutter="12">
|
||||
<!-- 第1列 -->
|
||||
<el-col :span="5">
|
||||
<!-- Row 1 -->
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="单据编码">
|
||||
<el-input v-model="formData.workorderCode" disabled placeholder="系统自动生成" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单据日期">
|
||||
<el-date-picker
|
||||
v-model="formData.orderDate"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="单据状态">
|
||||
<el-tag :type="getStatusType(formData.status)">
|
||||
{{ getStatusLabel(formData.status) }}
|
||||
</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="业务状态">
|
||||
<el-select v-model="formData.businessStatus" placeholder="请选择" style="width: 100%">
|
||||
<el-option
|
||||
v-for="opt in BUSINESS_STATUS_OPTIONS"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 第2列 -->
|
||||
<el-col :span="5">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="业务类型">
|
||||
<el-select v-model="formData.businessType" placeholder="请选择" style="width: 100%">
|
||||
<el-option
|
||||
@@ -127,18 +102,8 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作员">
|
||||
<el-input v-model="formData.operatorName" disabled placeholder="当前用户" />
|
||||
</el-form-item>
|
||||
<el-form-item label="审核员">
|
||||
<el-input v-model="formData.approverName" disabled placeholder="-" />
|
||||
</el-form-item>
|
||||
<el-form-item label="审核日期">
|
||||
<el-input v-model="formData.approveDate" disabled placeholder="-" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 第3列 -->
|
||||
<el-col :span="5">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="计划单号" prop="sourceCode">
|
||||
<el-input
|
||||
:model-value="formData.sourceCode || ''"
|
||||
@@ -151,15 +116,19 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="跟单编号">
|
||||
<el-input v-model="formData.salesOrderCode" disabled placeholder="-" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="物料编码">
|
||||
<el-input v-model="formData.productCode" disabled placeholder="选择计划单后带入" />
|
||||
</el-form-item>
|
||||
<el-form-item label="订单交期">
|
||||
<el-input v-model="formData.deliveryDate" disabled placeholder="-" />
|
||||
</el-form-item>
|
||||
<el-form-item label="需求日期">
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- Row 2 -->
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="单据日期">
|
||||
<el-date-picker
|
||||
v-model="formData.requestDate"
|
||||
v-model="formData.orderDate"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
@@ -167,14 +136,42 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 第4列 -->
|
||||
<el-col :span="5">
|
||||
<el-form-item label="物料编码">
|
||||
<el-input v-model="formData.productCode" disabled placeholder="选择计划单后带入" />
|
||||
<el-col :span="6">
|
||||
<el-form-item label="操作员">
|
||||
<el-input v-model="formData.operatorName" disabled placeholder="当前用户" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="跟单编号">
|
||||
<el-input v-model="formData.salesOrderCode" disabled placeholder="-" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="物料名称">
|
||||
<el-input v-model="formData.productName" disabled placeholder="选择计划单后带入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- Row 3 -->
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="单据状态">
|
||||
<el-tag :type="getStatusType(formData.status)">
|
||||
{{ getStatusLabel(formData.status) }}
|
||||
</el-tag>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="审核员">
|
||||
<el-input v-model="formData.approverName" disabled placeholder="-" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="订单交期">
|
||||
<el-input v-model="formData.deliveryDate" disabled placeholder="-" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="生产总数" prop="quantity">
|
||||
<div style="display: flex; align-items: center; gap: 4px; width: 100%">
|
||||
<el-input-number
|
||||
@@ -187,15 +184,39 @@
|
||||
<span style="white-space: nowrap; color: #909399;">{{ formData.unitOfMeasure || '台' }}</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注信息">
|
||||
<el-input v-model="formData.remark" placeholder="备注" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- Row 4 -->
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="业务状态">
|
||||
<el-select v-model="formData.businessStatus" placeholder="请选择" style="width: 100%">
|
||||
<el-option
|
||||
v-for="opt in BUSINESS_STATUS_OPTIONS"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 第5列 -->
|
||||
<el-col :span="4">
|
||||
<el-form-item label="图纸号">
|
||||
<el-input v-model="formData.drawingNo" placeholder="图纸号" />
|
||||
<el-col :span="6">
|
||||
<el-form-item label="审核日期">
|
||||
<el-input v-model="formData.approveDate" disabled placeholder="-" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="需求日期">
|
||||
<el-date-picker
|
||||
v-model="formData.requestDate"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="工艺路线">
|
||||
<el-input
|
||||
:model-value="formData.routeName || ''"
|
||||
@@ -208,9 +229,21 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- Row 5 -->
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="图纸号">
|
||||
<el-input v-model="formData.drawingNo" placeholder="图纸号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="生产线">
|
||||
<el-input v-model="formData.productionLine" placeholder="生产线" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="生产日期" prop="productionDate">
|
||||
<el-date-picker
|
||||
v-model="formData.productionDate"
|
||||
@@ -220,6 +253,8 @@
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="加工时长">
|
||||
<div style="display: flex; align-items: center; gap: 4px; width: 100%">
|
||||
<el-input-number
|
||||
@@ -233,6 +268,14 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- Row 6 -->
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="备注信息">
|
||||
<el-input v-model="formData.remark" placeholder="备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</el-form>
|
||||
@@ -588,6 +631,9 @@ function confirmPlanSelect() {
|
||||
formData.orderSource = 'PLAN'
|
||||
formData.salesOrderCode = plan.salesOrderCode || ''
|
||||
formData.deliveryDate = plan.deliveryDate || ''
|
||||
if (plan.clientId) formData.clientId = plan.clientId
|
||||
if (plan.clientCode) formData.clientCode = plan.clientCode
|
||||
if (plan.clientName) formData.clientName = plan.clientName
|
||||
const firstLine = plan.lines?.[0]
|
||||
if (firstLine) {
|
||||
formData.productId = firstLine.itemId
|
||||
@@ -858,4 +904,8 @@ onMounted(() => {
|
||||
|
||||
.dialog-search { margin-bottom: 16px; display: flex; align-items: center; }
|
||||
.empty-hint { padding: 24px 0; text-align: center; color: #909399; font-size: 13px; }
|
||||
|
||||
.material-section :deep(.el-table__header th .cell) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="workorderName" label="工单名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="workorderType" label="工单类型" width="80" align="center">
|
||||
<el-table-column prop="workorderType" label="工单类型" width="80" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ getWorkorderTypeLabel(row.workorderType) }}
|
||||
</template>
|
||||
@@ -156,18 +156,18 @@
|
||||
<el-table-column prop="productCode" label="产品编号" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="productName" label="产品名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="productSpc" label="规格型号" width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="unitOfMeasure" label="单位" width="60" align="center" />
|
||||
<el-table-column prop="quantity" label="生产数量" width="100" align="right">
|
||||
<el-table-column prop="unitOfMeasure" label="单位" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="quantity" label="生产数量" width="100" align="right" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ formatQuantity(row.quantity) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="quantityProduced" label="已生产" width="100" align="right">
|
||||
<el-table-column prop="quantityProduced" label="已生产" width="100" align="right" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ formatQuantity(row.quantityProduced) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="quantityScheduled" label="已排产" width="100" align="right">
|
||||
<el-table-column prop="quantityScheduled" label="已排产" width="100" align="right" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ formatQuantity(row.quantityScheduled) }}
|
||||
</template>
|
||||
@@ -178,7 +178,7 @@
|
||||
{{ row.productionDate ? String(row.productionDate).slice(0, 10) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="80" align="center">
|
||||
<el-table-column prop="status" label="状态" width="80" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)">
|
||||
{{ getStatusLabel(row.status) }}
|
||||
@@ -543,4 +543,8 @@ onMounted(() => {
|
||||
font-weight: bold;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.table-card :deep(.el-table__header th .cell) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<el-button type="primary" @click="handleSave" :loading="saveLoading">
|
||||
<el-icon><Check /></el-icon>保存
|
||||
</el-button>
|
||||
<el-button v-if="isEdit && formData.orderStatus === '开立'" @click="handleWithdraw">
|
||||
<el-button v-if="isEdit && formData.orderStatus === 'PREPARE'" @click="handleWithdraw">
|
||||
撤回
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -601,7 +601,7 @@ const formData = reactive<SalesOrder>({
|
||||
orderId: undefined,
|
||||
orderCode: '',
|
||||
orderDate: new Date().toISOString().split('T')[0],
|
||||
orderStatus: '开立',
|
||||
orderStatus: 'PREPARE',
|
||||
bizType: 'sales_order',
|
||||
bizStatus: 'normal',
|
||||
salesType: 'factory',
|
||||
@@ -688,13 +688,13 @@ const totalAmount = computed(() => {
|
||||
/** 是否可审核 */
|
||||
const canAudit = computed(() => {
|
||||
return (isEdit.value || isView.value) &&
|
||||
formData.orderStatus === '开立' &&
|
||||
formData.orderStatus === 'PREPARE' &&
|
||||
(formData.lines?.length || 0) > 0
|
||||
})
|
||||
|
||||
/** 是否可反审核 */
|
||||
const canUnaudit = computed(() => {
|
||||
return (isEdit.value || isView.value) && formData.orderStatus === '审核'
|
||||
return (isEdit.value || isView.value) && formData.orderStatus === 'APPROVED'
|
||||
})
|
||||
|
||||
// ============ 方法 ============
|
||||
@@ -1093,7 +1093,7 @@ async function handleWithdraw() {
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm('确认撤回此订单吗?', '提示', { type: 'warning' })
|
||||
formData.orderStatus = '草稿'
|
||||
formData.orderStatus = 'PREPARE'
|
||||
await updateSalesOrder(formData)
|
||||
ElMessage.success('撤回成功')
|
||||
loadOrderData()
|
||||
|
||||
@@ -235,7 +235,7 @@
|
||||
type="primary"
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
:disabled="row.orderStatus === '审核'"
|
||||
:disabled="row.orderStatus === 'APPROVED'"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
@@ -244,7 +244,7 @@
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
:disabled="row.orderStatus === '审核'"
|
||||
:disabled="row.orderStatus === 'APPROVED'"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
@@ -341,13 +341,13 @@ const salesTypeOptions = SALES_TYPE_OPTIONS
|
||||
/** 是否可以审核(选中了开立状态的订单) */
|
||||
const canAudit = computed(() => {
|
||||
return selectedRows.value.length > 0 &&
|
||||
selectedRows.value.every(row => row.orderStatus === '开立')
|
||||
selectedRows.value.every(row => row.orderStatus === 'PREPARE')
|
||||
})
|
||||
|
||||
/** 是否可以反审核(选中了审核状态的订单) */
|
||||
const canUnaudit = computed(() => {
|
||||
return selectedRows.value.length > 0 &&
|
||||
selectedRows.value.every(row => row.orderStatus === '审核')
|
||||
selectedRows.value.every(row => row.orderStatus === 'APPROVED')
|
||||
})
|
||||
|
||||
// ============ 方法 ============
|
||||
|
||||
@@ -433,7 +433,9 @@
|
||||
<el-table-column prop="quantity" label="生产数量" width="100" align="right" />
|
||||
<el-table-column prop="status" label="状态" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.status || '-' }}
|
||||
<el-tag :type="WORKORDER_STATUS_MAP[row.status]?.type || 'info'" size="small">
|
||||
{{ WORKORDER_STATUS_MAP[row.status]?.label || row.status || '-' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -586,6 +588,7 @@ import {
|
||||
STATUS_MAP,
|
||||
type IssueHeader
|
||||
} from '@/api/warehouse/issue'
|
||||
import { STATUS_MAP as WORKORDER_STATUS_MAP, getWorkOrderBomList } from '@/api/workOrder'
|
||||
import PrintDialog from '@/components/print/PrintDialog.vue'
|
||||
import type { PrintConfig } from '@/components/print/types'
|
||||
import {
|
||||
@@ -656,7 +659,7 @@ const formRules = {
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
issueName: [{ required: true, message: '领料单名称不能为空', trigger: 'blur' }]
|
||||
issueName: [{ required: false }]
|
||||
}
|
||||
|
||||
// ============ 领料行状态 ============
|
||||
@@ -751,11 +754,28 @@ const selectedItem = ref<any>(null)
|
||||
async function loadItems() {
|
||||
itemLoading.value = true
|
||||
try {
|
||||
if (formData.workorderId) {
|
||||
const bomItems = await getWorkOrderBomList(formData.workorderId)
|
||||
const keyword = (itemSearch.itemCode || itemSearch.itemName || '').toLowerCase()
|
||||
const mapped = bomItems.map(b => ({
|
||||
itemId: b.itemId,
|
||||
itemCode: b.itemCode || '',
|
||||
itemName: b.itemName || '',
|
||||
specification: b.itemSpc || '',
|
||||
unitOfMeasure: b.unitOfMeasure || '',
|
||||
unitName: b.unitName || '',
|
||||
itemTypeName: ''
|
||||
}))
|
||||
itemList.value = keyword
|
||||
? mapped.filter(m => m.itemCode.toLowerCase().includes(keyword) || m.itemName.toLowerCase().includes(keyword))
|
||||
: mapped
|
||||
} else {
|
||||
const res = await getItemSelectList({
|
||||
itemCode: itemSearch.itemCode || undefined,
|
||||
itemName: itemSearch.itemName || undefined
|
||||
})
|
||||
itemList.value = res.rows
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载物料失败:', error)
|
||||
} finally {
|
||||
@@ -1188,6 +1208,12 @@ async function handleSave() {
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
|
||||
if (!formData.issueName?.trim()) {
|
||||
const now = new Date()
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
formData.issueName = `领料单-${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`
|
||||
}
|
||||
|
||||
saveLoading.value = true
|
||||
|
||||
// 保存表头
|
||||
|
||||
@@ -127,24 +127,24 @@
|
||||
<el-table-column prop="taskCode" label="任务编码" width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="workstationName" label="工作站" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="clientName" label="客户名称" width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="issueDate" label="领料日期" width="120" align="center">
|
||||
<el-table-column prop="issueDate" label="领料日期" width="120" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.issueDate ? String(row.issueDate).slice(0, 10) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="requiredTime" label="需求时间" width="150" align="center">
|
||||
<el-table-column prop="requiredTime" label="需求时间" width="150" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.requiredTime ? String(row.requiredTime).slice(0, 16) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="80" align="center">
|
||||
<el-table-column prop="status" label="状态" width="80" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)">
|
||||
{{ getStatusLabel(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||
<el-table-column label="操作" width="280" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<!-- 所有状态:查看 -->
|
||||
<el-button type="success" link @click="handleView(row)">查看</el-button>
|
||||
@@ -457,4 +457,8 @@ onMounted(() => {
|
||||
font-weight: bold;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.table-card :deep(.el-table__header th .cell) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
package com.ktg.mes.mp.controller;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.ktg.common.constant.UserConstants;
|
||||
import com.ktg.mes.mp.domain.MpMbomLine;
|
||||
import com.ktg.mes.mp.service.IMpMbomLineService;
|
||||
import com.ktg.mes.wm.domain.WmMaterialStock;
|
||||
import com.ktg.mes.wm.service.IWmMaterialStockService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -42,6 +48,9 @@ public class MpMbomController extends BaseController
|
||||
@Autowired
|
||||
private IMpMbomLineService mpMbomLineService;
|
||||
|
||||
@Autowired
|
||||
private IWmMaterialStockService wmMaterialStockService;
|
||||
|
||||
/**
|
||||
* 查询物料清单列表
|
||||
*/
|
||||
@@ -200,4 +209,70 @@ public class MpMbomController extends BaseController
|
||||
}
|
||||
return toAjax(mpMbomService.revokeIssue(mbomId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 齐套检查:查询物料清单的子件库存情况
|
||||
*/
|
||||
@GetMapping("/stock-check/{mbomId}")
|
||||
public AjaxResult stockCheck(@PathVariable Long mbomId)
|
||||
{
|
||||
MpMbom mbom = mpMbomService.selectMpMbomByMbomId(mbomId);
|
||||
if (mbom == null) {
|
||||
return AjaxResult.error("物料清单不存在!");
|
||||
}
|
||||
|
||||
// 查询物料清单明细(子件列表)
|
||||
MpMbomLine query = new MpMbomLine();
|
||||
query.setMbomId(mbomId);
|
||||
List<MpMbomLine> lines = mpMbomLineService.selectMpMbomLineList(query);
|
||||
|
||||
if (lines == null || lines.isEmpty()) {
|
||||
return AjaxResult.success(new ArrayList<>());
|
||||
}
|
||||
|
||||
// 查询每个子件的库存并计算缺料情况
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (MpMbomLine line : lines) {
|
||||
if (line.getItemId() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 查询物料库存
|
||||
WmMaterialStock stockQuery = new WmMaterialStock();
|
||||
stockQuery.setItemId(line.getItemId());
|
||||
List<WmMaterialStock> stocks = wmMaterialStockService.selectWmMaterialStockList(stockQuery);
|
||||
|
||||
// 汇总可用库存(未冻结的库存)
|
||||
BigDecimal availableQty = BigDecimal.ZERO;
|
||||
if (stocks != null) {
|
||||
for (WmMaterialStock stock : stocks) {
|
||||
if (stock.getQuantityOnhand() != null && !"Y".equals(stock.getFrozenFlag())) {
|
||||
availableQty = availableQty.add(stock.getQuantityOnhand());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 需求量
|
||||
BigDecimal requiredQty = line.getQuantity() != null ? line.getQuantity() : BigDecimal.ZERO;
|
||||
|
||||
// 缺料量(需求量 - 可用量,如果 < 0 则为 0)
|
||||
BigDecimal shortage = requiredQty.subtract(availableQty);
|
||||
if (shortage.compareTo(BigDecimal.ZERO) < 0) {
|
||||
shortage = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("itemCode", line.getItemCode());
|
||||
item.put("itemName", line.getItemName());
|
||||
item.put("unitName", line.getUnitName());
|
||||
item.put("requiredQty", requiredQty);
|
||||
item.put("availableQty", availableQty);
|
||||
item.put("shortage", shortage);
|
||||
item.put("isShortage", shortage.compareTo(BigDecimal.ZERO) > 0);
|
||||
|
||||
result.add(item);
|
||||
}
|
||||
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,18 @@ public class MpPlan extends BaseEntity
|
||||
@Excel(name = "销售员")
|
||||
private String salesUserName;
|
||||
|
||||
/** 部门名称(从关联销售订单带入,不持久化) */
|
||||
private String deptName;
|
||||
|
||||
/** 客户ID(从关联销售订单带入,不持久化) */
|
||||
private Long clientId;
|
||||
|
||||
/** 客户编码(从关联销售订单带入,不持久化) */
|
||||
private String clientCode;
|
||||
|
||||
/** 客户名称(从关联销售订单带入,不持久化) */
|
||||
private String clientName;
|
||||
|
||||
/** 订单交期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "订单交期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@@ -70,6 +82,9 @@ public class MpPlan extends BaseEntity
|
||||
/** BOM ID */
|
||||
private Long bomId;
|
||||
|
||||
/** BOM编码(从关联BOM带入,不持久化) */
|
||||
private String bomCode;
|
||||
|
||||
/** BOM版本号 */
|
||||
@Excel(name = "BOM版本号")
|
||||
private String bomVersion;
|
||||
@@ -94,7 +109,7 @@ public class MpPlan extends BaseEntity
|
||||
private String approverName;
|
||||
|
||||
/** 审核日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date approveDate;
|
||||
|
||||
/** 删除标志 */
|
||||
@@ -249,6 +264,25 @@ public class MpPlan extends BaseEntity
|
||||
return salesUserName;
|
||||
}
|
||||
|
||||
public void setDeptName(String deptName)
|
||||
{
|
||||
this.deptName = deptName;
|
||||
}
|
||||
|
||||
public String getDeptName()
|
||||
{
|
||||
return deptName;
|
||||
}
|
||||
|
||||
public void setClientId(Long clientId) { this.clientId = clientId; }
|
||||
public Long getClientId() { return clientId; }
|
||||
|
||||
public void setClientCode(String clientCode) { this.clientCode = clientCode; }
|
||||
public String getClientCode() { return clientCode; }
|
||||
|
||||
public void setClientName(String clientName) { this.clientName = clientName; }
|
||||
public String getClientName() { return clientName; }
|
||||
|
||||
public void setDeliveryDate(Date deliveryDate)
|
||||
{
|
||||
this.deliveryDate = deliveryDate;
|
||||
@@ -269,6 +303,16 @@ public class MpPlan extends BaseEntity
|
||||
return bomId;
|
||||
}
|
||||
|
||||
public void setBomCode(String bomCode)
|
||||
{
|
||||
this.bomCode = bomCode;
|
||||
}
|
||||
|
||||
public String getBomCode()
|
||||
{
|
||||
return bomCode;
|
||||
}
|
||||
|
||||
public void setBomVersion(String bomVersion)
|
||||
{
|
||||
this.bomVersion = bomVersion;
|
||||
@@ -400,6 +444,7 @@ public class MpPlan extends BaseEntity
|
||||
.append("salesUserName", getSalesUserName())
|
||||
.append("deliveryDate", getDeliveryDate())
|
||||
.append("bomId", getBomId())
|
||||
.append("bomCode", getBomCode())
|
||||
.append("bomVersion", getBomVersion())
|
||||
.append("bomDesc", getBomDesc())
|
||||
.append("totalQuantity", getTotalQuantity())
|
||||
|
||||
@@ -77,6 +77,10 @@ public class MpPlanLine extends BaseEntity
|
||||
private String salesUserName;
|
||||
/** 订单交期(关联表头,明细视图展示) */
|
||||
private String deliveryDate;
|
||||
/** 单据状态(关联表头,明细视图展示) */
|
||||
private String status;
|
||||
/** 单据日期(关联表头,明细视图展示) */
|
||||
private String planDate;
|
||||
|
||||
public void setLineId(Long lineId)
|
||||
{
|
||||
@@ -256,6 +260,18 @@ public class MpPlanLine extends BaseEntity
|
||||
public String getDeliveryDate() {
|
||||
return deliveryDate;
|
||||
}
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
public void setPlanDate(String planDate) {
|
||||
this.planDate = planDate;
|
||||
}
|
||||
public String getPlanDate() {
|
||||
return planDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -342,7 +342,13 @@ public class MpPlanServiceImpl implements IMpPlanService
|
||||
// 生成物料清单编码(通过通用编码引擎)
|
||||
mbom.setMbomCode(autoCodeUtil.genSerialCode(UserConstants.MBOM_CODE, ""));
|
||||
mbom.setMbomDate(new Date());
|
||||
// 当计划已审核时,自动审核物料清单
|
||||
if (UserConstants.ORDER_STATUS_APPROVED.equals(plan.getStatus())) {
|
||||
mbom.setStatus(UserConstants.ORDER_STATUS_APPROVED);
|
||||
mbom.setApproveDate(DateUtils.getNowDate());
|
||||
} else {
|
||||
mbom.setStatus(UserConstants.ORDER_STATUS_PREPARE);
|
||||
}
|
||||
mbom.setBusinessType("BOM_CALC");
|
||||
mbom.setPlanId(plan.getPlanId());
|
||||
mbom.setPlanCode(plan.getPlanCode());
|
||||
|
||||
@@ -111,6 +111,7 @@ public class ProWorkorderServiceImpl implements IProWorkorderService
|
||||
}
|
||||
}
|
||||
|
||||
proWorkorder.setWorkorderName(buildWorkorderName(proWorkorder));
|
||||
proWorkorder.setCreateTime(DateUtils.getNowDate());
|
||||
return proWorkorderMapper.insertProWorkorder(proWorkorder);
|
||||
}
|
||||
@@ -124,6 +125,7 @@ public class ProWorkorderServiceImpl implements IProWorkorderService
|
||||
@Override
|
||||
public int updateProWorkorder(ProWorkorder proWorkorder)
|
||||
{
|
||||
proWorkorder.setWorkorderName(buildWorkorderName(proWorkorder));
|
||||
proWorkorder.setUpdateTime(DateUtils.getNowDate());
|
||||
return proWorkorderMapper.updateProWorkorder(proWorkorder);
|
||||
}
|
||||
@@ -242,4 +244,23 @@ public class ProWorkorderServiceImpl implements IProWorkorderService
|
||||
List<ProWorkorderHomeVO> collect = proWorkorders.stream().filter(item -> 0L == item.getParentId()).collect(Collectors.toList());
|
||||
return AjaxResult.success(collect);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生产工单名称规则:JX + 产品名称 + 单据日期(yyyyMMdd)
|
||||
*/
|
||||
private String buildWorkorderName(ProWorkorder proWorkorder) {
|
||||
String productName = StringUtils.trimToEmpty(proWorkorder.getProductName());
|
||||
if (StringUtils.isEmpty(productName)) {
|
||||
productName = StringUtils.trimToEmpty(proWorkorder.getProductCode());
|
||||
}
|
||||
if (StringUtils.isEmpty(productName)) {
|
||||
productName = "未命名产品";
|
||||
}
|
||||
|
||||
String docDate = DateUtils.parseDateToStr(
|
||||
"yyyyMMdd",
|
||||
proWorkorder.getRequestDate() == null ? DateUtils.getNowDate() : proWorkorder.getRequestDate()
|
||||
);
|
||||
return "JX-" + productName + "-" + docDate;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,22 +123,34 @@ public class SlOrderController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核销售订单
|
||||
* 审核销售订单(支持批量,逗号分隔)
|
||||
*/
|
||||
@Log(title = "销售订单", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/audit/{orderId}")
|
||||
public AjaxResult audit(@PathVariable Long orderId)
|
||||
@PostMapping("/audit/{orderIds}")
|
||||
public AjaxResult audit(@PathVariable String orderIds)
|
||||
{
|
||||
return toAjax(slOrderService.auditSlOrder(orderId, getUsername()));
|
||||
String nickName = getLoginUser().getUser().getNickName();
|
||||
Long userId = getUserId();
|
||||
int rows = 0;
|
||||
for (String id : orderIds.split(","))
|
||||
{
|
||||
rows += slOrderService.auditSlOrder(Long.parseLong(id.trim()), nickName, userId);
|
||||
}
|
||||
return toAjax(rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* 反审核销售订单
|
||||
* 反审核销售订单(支持批量,逗号分隔)
|
||||
*/
|
||||
@Log(title = "销售订单", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/unaudit/{orderId}")
|
||||
public AjaxResult unaudit(@PathVariable Long orderId)
|
||||
@PostMapping("/unaudit/{orderIds}")
|
||||
public AjaxResult unaudit(@PathVariable String orderIds)
|
||||
{
|
||||
return toAjax(slOrderService.unauditSlOrder(orderId, getUsername()));
|
||||
int rows = 0;
|
||||
for (String id : orderIds.split(","))
|
||||
{
|
||||
rows += slOrderService.unauditSlOrder(Long.parseLong(id.trim()), getUsername());
|
||||
}
|
||||
return toAjax(rows);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +71,11 @@ public interface ISlOrderService
|
||||
* 审核销售订单
|
||||
*
|
||||
* @param orderId 销售订单ID
|
||||
* @param username 审核人
|
||||
* @param approverName 审核人昵称
|
||||
* @param approverId 审核人ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int auditSlOrder(Long orderId, String username);
|
||||
public int auditSlOrder(Long orderId, String approverName, Long approverId);
|
||||
|
||||
/**
|
||||
* 反审核销售订单
|
||||
|
||||
@@ -221,11 +221,12 @@ public class SlOrderServiceImpl implements ISlOrderService
|
||||
* 审核销售订单
|
||||
*
|
||||
* @param orderId 销售订单ID
|
||||
* @param username 审核人
|
||||
* @param approverName 审核人昵称
|
||||
* @param approverId 审核人ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int auditSlOrder(Long orderId, String username)
|
||||
public int auditSlOrder(Long orderId, String approverName, Long approverId)
|
||||
{
|
||||
SlOrder order = slOrderMapper.selectSlOrderByOrderId(orderId);
|
||||
if (order == null)
|
||||
@@ -233,9 +234,10 @@ public class SlOrderServiceImpl implements ISlOrderService
|
||||
return 0;
|
||||
}
|
||||
order.setStatus(UserConstants.ORDER_STATUS_APPROVED);
|
||||
order.setApproverName(username);
|
||||
order.setApproverId(approverId);
|
||||
order.setApproverName(approverName);
|
||||
order.setApproveDate(DateUtils.getNowDate());
|
||||
order.setUpdateBy(username);
|
||||
order.setUpdateBy(approverName);
|
||||
order.setUpdateTime(DateUtils.getNowDate());
|
||||
return slOrderMapper.updateSlOrder(order);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="salesOrderCode" column="sales_order_code" />
|
||||
<result property="salesUserName" column="sales_user_name" />
|
||||
<result property="deliveryDate" column="delivery_date" />
|
||||
<result property="status" column="status" />
|
||||
<result property="planDate" column="plan_date" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectMpPlanLineVo">
|
||||
@@ -52,8 +54,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
select l.line_id, l.plan_id, l.plan_code, l.line_no, l.pp_number, l.item_id, l.item_code,
|
||||
l.item_name, l.specification, l.unit_name, l.quantity, l.remark,
|
||||
l.del_flag, l.create_time, l.tenant_id,
|
||||
p.sales_order_code, p.sales_user_name,
|
||||
date_format(p.delivery_date, '%Y-%m-%d') as delivery_date
|
||||
p.sales_order_code, p.sales_user_name, p.status,
|
||||
date_format(p.delivery_date, '%Y-%m-%d') as delivery_date,
|
||||
date_format(p.plan_date, '%Y-%m-%d') as plan_date
|
||||
from erp_mp_plan_line l
|
||||
left join erp_mp_plan p on l.plan_id = p.plan_id and p.del_flag = '0'
|
||||
<where>
|
||||
|
||||
@@ -17,8 +17,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="salesOrderCode" column="sales_order_code" />
|
||||
<result property="salesUserId" column="sales_user_id" />
|
||||
<result property="salesUserName" column="sales_user_name" />
|
||||
<result property="deptName" column="dept_name" />
|
||||
<result property="clientId" column="client_id" />
|
||||
<result property="clientCode" column="client_code" />
|
||||
<result property="clientName" column="client_name" />
|
||||
<result property="deliveryDate" column="delivery_date" />
|
||||
<result property="bomId" column="bom_id" />
|
||||
<result property="bomCode" column="bom_code" />
|
||||
<result property="bomVersion" column="bom_version" />
|
||||
<result property="bomDesc" column="bom_desc" />
|
||||
<result property="totalQuantity" column="total_quantity" />
|
||||
@@ -36,48 +41,52 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectMpPlanVo">
|
||||
select plan_id, tenant_id, plan_code, plan_date, status, business_status, business_type,
|
||||
work_type, sales_order_id, sales_order_code, sales_user_name,
|
||||
delivery_date, bom_id, bom_version, bom_desc, total_quantity, remark,
|
||||
del_flag, create_by, create_time, update_by, update_time
|
||||
from erp_mp_plan
|
||||
select p.plan_id, p.tenant_id, p.plan_code, p.plan_date, p.status, p.business_status, p.business_type,
|
||||
p.work_type, p.sales_order_id, p.sales_order_code, p.sales_user_name,
|
||||
p.delivery_date, p.bom_id, p.bom_version, p.bom_desc, p.total_quantity, p.remark,
|
||||
p.operator_id, p.operator_name, p.approver_id, p.approver_name, p.approve_date,
|
||||
p.del_flag, p.create_by, p.create_time, p.update_by, p.update_time,
|
||||
so.dept_name, so.client_id, so.client_code, so.client_name, b.bom_code
|
||||
from erp_mp_plan p
|
||||
left join erp_sl_order so on p.sales_order_id = so.order_id and so.del_flag = '0'
|
||||
left join md_bom b on p.bom_id = b.bom_id and b.del_flag = '0'
|
||||
</sql>
|
||||
|
||||
<select id="selectMpPlanList" parameterType="MpPlan" resultMap="MpPlanResult">
|
||||
<include refid="selectMpPlanVo"/>
|
||||
<where>
|
||||
del_flag = '0'
|
||||
<if test="planCode != null and planCode != ''"> and plan_code like concat('%', #{planCode}, '%')</if>
|
||||
<if test="status != null and status != ''"> and status = #{status}</if>
|
||||
<if test="businessStatus != null and businessStatus != ''"> and business_status = #{businessStatus}</if>
|
||||
<if test="businessType != null and businessType != ''"> and business_type = #{businessType}</if>
|
||||
<if test="workType != null"> and work_type = #{workType}</if>
|
||||
<if test="salesOrderId != null"> and sales_order_id = #{salesOrderId}</if>
|
||||
<if test="salesOrderCode != null and salesOrderCode != ''"> and sales_order_code like concat('%', #{salesOrderCode}, '%')</if>
|
||||
<if test="salesUserName != null and salesUserName != ''"> and sales_user_name like concat('%', #{salesUserName}, '%')</if>
|
||||
p.del_flag = '0'
|
||||
<if test="planCode != null and planCode != ''"> and p.plan_code like concat('%', #{planCode}, '%')</if>
|
||||
<if test="status != null and status != ''"> and p.status = #{status}</if>
|
||||
<if test="businessStatus != null and businessStatus != ''"> and p.business_status = #{businessStatus}</if>
|
||||
<if test="businessType != null and businessType != ''"> and p.business_type = #{businessType}</if>
|
||||
<if test="workType != null"> and p.work_type = #{workType}</if>
|
||||
<if test="salesOrderId != null"> and p.sales_order_id = #{salesOrderId}</if>
|
||||
<if test="salesOrderCode != null and salesOrderCode != ''"> and p.sales_order_code like concat('%', #{salesOrderCode}, '%')</if>
|
||||
<if test="salesUserName != null and salesUserName != ''"> and p.sales_user_name like concat('%', #{salesUserName}, '%')</if>
|
||||
<if test="params.beginPlanDate != null and params.beginPlanDate != '' and params.endPlanDate != null and params.endPlanDate != ''">
|
||||
and plan_date between #{params.beginPlanDate} and #{params.endPlanDate}
|
||||
and p.plan_date between #{params.beginPlanDate} and #{params.endPlanDate}
|
||||
</if>
|
||||
<if test="params.beginDeliveryDate != null and params.beginDeliveryDate != '' and params.endDeliveryDate != null and params.endDeliveryDate != ''">
|
||||
and delivery_date between #{params.beginDeliveryDate} and #{params.endDeliveryDate}
|
||||
and p.delivery_date between #{params.beginDeliveryDate} and #{params.endDeliveryDate}
|
||||
</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
order by p.create_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectMpPlanByPlanId" parameterType="Long" resultMap="MpPlanResult">
|
||||
<include refid="selectMpPlanVo"/>
|
||||
where plan_id = #{planId} and del_flag = '0'
|
||||
where p.plan_id = #{planId} and p.del_flag = '0'
|
||||
</select>
|
||||
|
||||
<select id="selectMpPlanByPlanCode" parameterType="String" resultMap="MpPlanResult">
|
||||
<include refid="selectMpPlanVo"/>
|
||||
where plan_code = #{planCode} and del_flag = '0'
|
||||
where p.plan_code = #{planCode} and p.del_flag = '0'
|
||||
</select>
|
||||
|
||||
<select id="checkPlanCodeUnique" parameterType="MpPlan" resultMap="MpPlanResult">
|
||||
<include refid="selectMpPlanVo"/>
|
||||
where plan_code = #{planCode} and del_flag = '0' limit 1
|
||||
where p.plan_code = #{planCode} and p.del_flag = '0' limit 1
|
||||
</select>
|
||||
|
||||
<select id="selectMaxPlanCode" parameterType="String" resultType="String">
|
||||
@@ -109,6 +118,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="bomDesc != null">bom_desc,</if>
|
||||
<if test="totalQuantity != null">total_quantity,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="operatorId != null">operator_id,</if>
|
||||
<if test="operatorName != null">operator_name,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
</trim>
|
||||
@@ -130,6 +141,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="bomDesc != null">#{bomDesc},</if>
|
||||
<if test="totalQuantity != null">#{totalQuantity},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="operatorId != null">#{operatorId},</if>
|
||||
<if test="operatorName != null">#{operatorName},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
</trim>
|
||||
@@ -153,6 +166,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="bomDesc != null">bom_desc = #{bomDesc},</if>
|
||||
<if test="totalQuantity != null">total_quantity = #{totalQuantity},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="operatorId != null">operator_id = #{operatorId},</if>
|
||||
<if test="operatorName != null">operator_name = #{operatorName},</if>
|
||||
<if test="approverId != null">approver_id = #{approverId},</if>
|
||||
<if test="approverName != null">approver_name = #{approverName},</if>
|
||||
<if test="approveDate != null">approve_date = #{approveDate},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
</trim>
|
||||
|
||||
@@ -46,7 +46,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectProWorkorderVo">
|
||||
select workorder_id, workorder_code, workorder_name, workorder_type, order_source, source_code, product_id, product_code, product_name, product_spc, unit_of_measure, unit_name, batch_code, quantity,quantity_produced, client_id, client_code, client_name, vendor_id, vendor_code, vendor_name, request_date, parent_id, ancestors, finish_date, cancel_date, status, remark, attr1, attr2, attr3, attr4, create_by, create_time, update_by, update_time from pro_workorder
|
||||
select workorder_id, workorder_code, workorder_name, workorder_type, order_source, source_code, product_id, product_code, product_name, product_spc, unit_of_measure, unit_name, batch_code, quantity, quantity_produced, quantity_changed, quantity_scheduled, client_id, client_code, client_name, vendor_id, vendor_code, vendor_name, request_date, parent_id, ancestors, finish_date, cancel_date, status, remark, attr1, attr2, attr3, attr4, create_by, create_time, update_by, update_time from pro_workorder
|
||||
</sql>
|
||||
|
||||
<select id="selectProWorkorderList" parameterType="ProWorkorder" resultMap="ProWorkorderResult">
|
||||
|
||||
@@ -86,7 +86,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
inner join erp_sl_order o on ol.order_id = o.order_id
|
||||
<where>
|
||||
ol.del_flag = '0' and o.del_flag = '0'
|
||||
and o.status = '审核'
|
||||
and o.status = 'APPROVED'
|
||||
and (ol.quantity - ifnull(ol.delivered_qty, 0)) > 0
|
||||
<if test="orderCode != null and orderCode != ''"> and ol.order_code like concat('%', #{orderCode}, '%')</if>
|
||||
<if test="trackCode != null and trackCode != ''"> and ol.track_code like concat('%', #{trackCode}, '%')</if>
|
||||
|
||||
BIN
prd/.DS_Store
vendored
BIN
prd/.DS_Store
vendored
Binary file not shown.
10
prd/issues-0311-3.md
Normal file
10
prd/issues-0311-3.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# 销售订单
|
||||
|
||||
## 新增销售订单(编辑销售订单)
|
||||
1.点击审核按钮后,审核信息提交含审核人员,审核日期,单据状态等,使用当前登录用户作为审核人员,当前日期为审核日期,单据状态变成已审核。
|
||||
|
||||
## 销售订单
|
||||
1.单据视图状态下列表中单据状态没有显示,
|
||||
2.单据视图状态下列表中审核,反审核按钮不可操作,
|
||||
3.明细视图下单据状态显示成中文,销售员显示用户昵称,不是用户名,
|
||||
4.明细视图状态下列表中销售类型没有正确显示。
|
||||
17
prd/issues-0311-4.md
Normal file
17
prd/issues-0311-4.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# 生产计划单
|
||||
|
||||
## 生产计划单列表页
|
||||
1.审核日期没有显示,
|
||||
2.业务部门没有显示,
|
||||
3.明细视图状态下列表中销售员显示用户昵称,不是用户名,
|
||||
4.明细视图状态下列表中物料清单、单据日期没有正确显示,
|
||||
5.快捷筛选的tag改成和注塑行业相关的产品,
|
||||
6.明细视图状态下列表中操作栏居右显示,
|
||||
|
||||
## 新增生产计划单表单页(编辑生产计划单)
|
||||
1.点击引入后的弹窗页中业务人员没有显示出名称来,
|
||||
2.订单信息列表中数量、质量要求、备注字段的输入框高度增加,
|
||||
3.物料清单列表中单据状态、业务类型显示的不是中文
|
||||
4.物料清单列表下发车间列中合并生产车间、生产日期、状态3个列到下发车间列,
|
||||
5.已经审核了,开关状态按钮下发车间操作时,还是显示“只有已审核状态的单据才能下发!”,
|
||||
6.实现物料清单列表中的齐套检查功能
|
||||
11
prd/issues-0311-5.md
Normal file
11
prd/issues-0311-5.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# 生产计划单
|
||||
|
||||
## 生产计划单列表页
|
||||
1.单据视图状态下列表中操作栏居右显示,
|
||||
2.业务状态应该显示中文
|
||||
3.审核日期不需要时间,只显示日期就行
|
||||
|
||||
## 新增生产计划单表单页(编辑生产计划单)
|
||||
1.订单信息列表中数量、质量要求、备注字段的输入框高度一致,
|
||||
2.查看编辑生产计划单-》基础信息-》订单BOM应该显示订单BOM的单号
|
||||
3.物料清单列表中单据状态、业务类型显示的不是中文
|
||||
12
prd/issues-0311-6.md
Normal file
12
prd/issues-0311-6.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# 生产计划单
|
||||
|
||||
### 新增生产计划单表单页(编辑生产计划单)
|
||||
1.补料清单列表中单据状态列宽度增加,
|
||||
|
||||
## 产品BOM列表页
|
||||
1. 表格中“单据编码”,“单据状态”列宽度增加,不要出现换行,内容过长采用"..."截断显示,
|
||||
2. 单据视图状态下表格宽度100%显示,“操作”列居右对齐(参考生产计划单列表页),
|
||||
|
||||
## 新增/编辑产品BOM表单页
|
||||
1. 物料编码-》选择后显示的“选择物料”弹窗左侧分类树使用物料/产品名称作为分类名称,
|
||||
2. 物料信息表格行高度增加,输入框高度增加。
|
||||
27
prd/issues-0311-7.md
Normal file
27
prd/issues-0311-7.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# 生产订单
|
||||
|
||||
## 生产订单列表页
|
||||
1. 表格表头内容不允许换行,
|
||||
2. 表格每行的内容不要换行显示,内容过长采用"..."截断显示,
|
||||
3. 检查表格中工艺路线,客户名称没有显示的原因,如不是数据为空导致的请修复bug,
|
||||
|
||||
## 新增/编辑生产订单表单页
|
||||
1. 表头表单区的工艺路线和生产日期所在列的宽度太小了,加大宽度,改成4列布局
|
||||
2. 领料明细和完工明细表格的表头内容不允许换行,
|
||||
|
||||
# 产品BOM
|
||||
|
||||
## 新增/编辑EBOM表单页
|
||||
1. “选择物料”弹窗左侧分类树应该显示的是物料/产品名称,参考满足要求的物料管理(masterdata/item)页的左侧物料分类树的实现方法,
|
||||
|
||||
|
||||
# 生产领料单
|
||||
|
||||
## 生产领料单列表页
|
||||
1. 表格每行的内容不要换行显示,增加表头“操作”列的宽度,使一行能显示4个以上的按钮,
|
||||
|
||||
|
||||
## 新增生产领料单表单页
|
||||
1. 生产工单选择弹窗中的表格,表格的“状态“列显示的不是中文,
|
||||
2. 领料单名称未非必填项,如果没有写名称,请自动生成领料单名称,格式为:领料单-yyyyMMddHHmmss,
|
||||
3. 添加领料物料行时候,选择物料弹窗中只显示在所属生产工单的BOM物料清单中物料,
|
||||
Reference in New Issue
Block a user