zy-asrs-admin/src/components/orderOut/orderOutBatchPreview/index.vue
New file @@ -0,0 +1,237 @@ <script setup> import { ref, watch, reactive } from 'vue'; import { useRouter } from "vue-router"; import { get, post, postBlob } from '@/utils/request.js' import { message, Modal } from 'ant-design-vue'; import { logout } from '@/config.js'; import { formatMessage } from '@/utils/localeUtils.js'; import useTableSearch from '@/utils/tableUtils.jsx'; const router = useRouter(); const TABLE_KEY = 'table-order-out-preview'; const emit = defineEmits(['reload']) const { getColumnSearchProps, } = useTableSearch(); let currentOrder = ref(null); let searchInput = ref(null); let tableData = ref([]); const open = ref(false); const showWidth = ref("60%") const records = ref([]) const loading = ref(false) let columns = [ { title: formatMessage('db.man_order_detl.order_no', '订单编号'), dataIndex: ['orderDetl$', 'orderNo'], width: 140, ellipsis: true, ...getColumnSearchProps('orderNo'), }, { title: formatMessage('db.man_order_detl.matnr', '商品编号'), dataIndex: ['orderDetl$', 'mat$', 'matnr'], width: 140, ellipsis: true, ...getColumnSearchProps('matnr'), }, { title: formatMessage('db.man_order_detl.batch', '批号'), dataIndex: ['orderDetl$', 'batch'], width: 140, ellipsis: true, ...getColumnSearchProps('batch'), }, { title: formatMessage('db.man_order_detl.anfme', '数量'), dataIndex: 'anfme', width: 140, ellipsis: true, ...getColumnSearchProps('anfme'), }, { title: formatMessage('db.man_order_detl.stock', '库存'), dataIndex: 'stock', width: 140, ellipsis: true, ...getColumnSearchProps('stock'), }, ]; const state = reactive({ selectedRowKeys: [], }); const onSelectChange = selectedRowKeys => { // console.log('selectedRowKeys changed: ', selectedRowKeys); state.selectedRowKeys = selectedRowKeys; }; const fieldList = []; getColumns(); //加载扩展字段 async function getColumns() { let fieldResp = await post('/api/matField/list', { unique: 1 }) let fieldResult = fieldResp.data; let tmp = columns; if (fieldResult.code == 200) { let data = fieldResult.data; data.forEach((item) => { tmp.push({ title: formatMessage(item.language, item.describe), name: item.name, dataIndex: item.name, key: item.name, width: 140, editable: true, }) fieldList.push(item.name); }) tmp.push({ title: formatMessage('db.man_order_detl.locNo', '出库库位'), dataIndex: 'locNo', width: 140, ellipsis: true, fixed: 'right', }) tmp.push({ title: '', dataIndex: 'handleStatus', width: 100, ellipsis: true, fixed: 'right', }) columns = tmp; } else if (result.code === 401) { message.error(result.msg); logout() } else { message.error(result.msg); } } watch(open, (newVal, oldVal) => { if (newVal) { handleOrderOutPreview() } }) const handleOk = () => { post('/api/out/orderOut/batch', tableData.value).then((resp) => { let result = resp.data; if (result.code == 200) { message.success(formatMessage('page.add.success', '出库成功')); open.value = false; emit('reload', true) } else { message.error(result.msg); } }) } const handleOrderOutPreview = () => { loading.value = true; tableData.value = [] post('/api/out/orderOut/batch/preview', { orderDetlIds: records.value, }).then((resp) => { let result = resp.data; if (result.code == 200) { tableData.value = result.data; loading.value = false; } }) } const handleOtherLocChange = (index, record) => { let stock = record.stock; record.otherLoc.forEach((item) => { if (item.locId == record.locId) { record.locNo = item.locNo; record.locDetlId = item.locDetlId; record.stock = item.stock; } }) let locDetlList = [] let tmp = tableData.value; tmp.forEach((item) => { if (!locDetlList[item.locDetlId]) { locDetlList[item.locDetlId] = item.stock; } }) tmp.forEach((item) => { if (item.locId == null) { item.stockAlarm = true; } else { let stock = locDetlList[item.locDetlId] stock = stock - item.anfme; locDetlList[item.locDetlId] = stock; if (stock >= 0) { item.stockAlarm = false; } else { item.stockAlarm = true; } } }) } defineExpose({ open, showWidth, records, }) </script> <script> export default { name: '预览订单出库' } </script> <template> <div> <a-modal v-model:open="open" :width="showWidth" :title="formatMessage('page.orderOutPreview.preview', '预览订单出库')" @ok="handleOk"> <a-table :data-source="tableData" :loading="loading" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="id" :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns"> <template #bodyCell="{ column, text, record, index }"> <template v-if="column.dataIndex === 'locNo'"> <div v-if="record.locId != null"> <a-select v-model:value="record.locId" :options="record.otherLoc" :fieldNames="{ label: 'locNo', value: 'locId' }" @change="handleOtherLocChange(index, record)"></a-select> </div> </template> <template v-if="column.dataIndex === 'handleStatus'"> <div v-if="record.locId == null"> <a-tag color="error">库存不足</a-tag> </div> <div v-else> <div v-if="record.stockAlarm != null && record.stockAlarm"> <a-tag color="error">库存不足</a-tag> </div> </div> </template> </template> </a-table> </a-modal> </div> </template> <style></style> zy-asrs-admin/src/components/orderOut/orderOutMergePreview/index.vue
New file @@ -0,0 +1,180 @@ <script setup> import { ref, watch, reactive } from 'vue'; import { useRouter } from "vue-router"; import { get, post, postBlob } from '@/utils/request.js' import { message, Modal } from 'ant-design-vue'; import { logout } from '@/config.js'; import { formatMessage } from '@/utils/localeUtils.js'; import useTableSearch from '@/utils/tableUtils.jsx'; import StockOutView from './stockOut.vue'; const router = useRouter(); const TABLE_KEY = 'table-order-out-preview'; const emit = defineEmits(['reload']) const { getColumnSearchProps, } = useTableSearch(); let currentOrder = ref(null); let searchInput = ref(null); let tableData = ref([]); const open = ref(false); const showWidth = ref("60%") const records = ref([]) const loading = ref(false) const stockOutChild = ref(null) let columns = [ { title: formatMessage('db.man_order_detl.matnr', '商品编号'), dataIndex: 'matnr', width: 140, ellipsis: true, ...getColumnSearchProps('matnr'), }, { title: formatMessage('db.man_order_detl.batch', '批号'), dataIndex: 'batch', width: 140, ellipsis: true, ...getColumnSearchProps('batch'), }, { title: formatMessage('db.man_order_detl.anfme', '数量'), dataIndex: 'anfme', width: 140, ellipsis: true, ...getColumnSearchProps('anfme'), }, ]; const state = reactive({ selectedRowKeys: [], }); const onSelectChange = selectedRowKeys => { // console.log('selectedRowKeys changed: ', selectedRowKeys); state.selectedRowKeys = selectedRowKeys; }; const fieldList = []; getColumns(); //加载扩展字段 async function getColumns() { let fieldResp = await post('/api/matField/list', { unique: 1 }) let fieldResult = fieldResp.data; let tmp = columns; if (fieldResult.code == 200) { let data = fieldResult.data; data.forEach((item) => { tmp.push({ title: formatMessage(item.language, item.describe), name: item.name, dataIndex: item.name, key: item.name, width: 140, editable: true, }) fieldList.push(item.name); }) columns = tmp; } else if (result.code === 401) { message.error(result.msg); logout() } else { message.error(result.msg); } } watch(open, (newVal, oldVal) => { if (newVal) { handleOrderMergePreview() } }) const handleOk = () => { if (state.selectedRowKeys.length == 0) { message.error(formatMessage("page.orderOut.mergeOrderOut.checkedError", "请选择至少一条数据")); return; } let param = [] state.selectedRowKeys.forEach((idx) => { let tmp = tableData.value[idx]; if (tmp != null) { param.push(tmp) } }) stockOutChild.value.open = true; stockOutChild.value.records = param; stockOutChild.value.showWidth = '55%' emit('reload', true) } const handleOrderMergePreview = () => { loading.value = true; tableData.value = [] state.selectedRowKeys = [] post('/api/out/orderOut/merge/preview', { orderIds: records.value, }).then((resp) => { let result = resp.data; if (result.code == 200) { let tmp = result.data; let index = 0; tmp.forEach((item) => { item.index = index++; }) tableData.value = tmp; loading.value = false; } }) } const handleCloseParent = () => { open.value = false; } defineExpose({ open, showWidth, records, }) </script> <script> export default { name: '预览合并订单' } </script> <template> <div> <a-modal v-model:open="open" :width="showWidth" :title="formatMessage('page.orderOutPreview.preview', '预览合并订单')" @ok="handleOk"> <a-table :data-source="tableData" :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }" :loading="loading" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="index" :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns"> <template #bodyCell="{ column, text, record, index }"> </template> </a-table> </a-modal> <StockOutView ref="stockOutChild" @closeParent="handleCloseParent" /> </div> </template> <style></style> zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue
New file @@ -0,0 +1,279 @@ <script setup> import { ref, watch, reactive } from 'vue'; import { useRouter } from "vue-router"; import { get, post, postBlob } from '@/utils/request.js' import { message, Modal } from 'ant-design-vue'; import { logout } from '@/config.js'; import { formatMessage } from '@/utils/localeUtils.js'; import useTableSearch from '@/utils/tableUtils.jsx'; const router = useRouter(); const TABLE_KEY = 'table-order-out-preview'; const emit = defineEmits(['closeParent']) const { getColumnSearchProps, } = useTableSearch(); let currentOrder = ref(null); let searchInput = ref(null); let tableData = ref([]); const operationPortList = ref([]) const open = ref(false); const showWidth = ref("60%") const records = ref([]) const loading = ref(false) let tableDataValue = [] let tableDataColSpan = [] const customColSpanProps = (index) => { let count = tableDataColSpan[index]; if (count == null) { count = 0; } return { rowSpan: count, }; } let columns = [ { title: formatMessage('db.man_order_detl.matnr', '商品编号'), dataIndex: 'matnr', width: 140, ellipsis: true, ...getColumnSearchProps('matnr'), customCell: (_, index) => { return customColSpanProps(index) }, }, { title: formatMessage('db.man_order_detl.batch', '批号'), dataIndex: 'batch', width: 140, ellipsis: true, ...getColumnSearchProps('batch'), customCell: (_, index) => { return customColSpanProps(index) }, }, ]; const state = reactive({ selectedRowKeys: [], }); const onSelectChange = selectedRowKeys => { // console.log('selectedRowKeys changed: ', selectedRowKeys); state.selectedRowKeys = selectedRowKeys; }; const fieldList = []; getColumns(); //加载扩展字段 async function getColumns() { let fieldResp = await post('/api/matField/list', { unique: 1, }) let fieldResult = fieldResp.data; let tmp = columns; if (fieldResult.code == 200) { let data = fieldResult.data; data.forEach((item) => { tmp.push({ title: formatMessage(item.language, item.describe), name: item.name, dataIndex: item.name, key: item.name, width: 140, editable: true, customCell: (_, index) => { return customColSpanProps(index) }, }) fieldList.push(item.name); }) tmp.push({ title: formatMessage('db.man_order_detl.anfme', '数量'), dataIndex: 'anfme', width: 140, ellipsis: true, fixed: 'right', }) tmp.push({ title: formatMessage('db.man_order_detl.locNo', '出库库位'), dataIndex: 'locNo', width: 140, ellipsis: true, fixed: 'right', }) tmp.push({ title: formatMessage('db.man_order_detl.operationPort', '作业口'), dataIndex: 'operationPort', width: 140, ellipsis: true, fixed: 'right', }) columns = tmp; } else if (result.code === 401) { message.error(result.msg); logout() } else { message.error(result.msg); } } async function getOperationPort() { let resp = await post('/api/operationPort/list', {}) let result = resp.data; if (result.code == 200) { let data = result.data; let tmp = [] data.forEach((item) => { tmp.push({ label: item.flag, value: item.id }) }) operationPortList.value = tmp; } else if (result.code === 401) { message.error(result.msg); logout() } else { message.error(result.msg); } } watch(open, (newVal, oldVal) => { if (newVal) { handleOrderMergePreview() } }) const handleOk = () => { post('/api/out/orderOut/merge', tableData.value).then((resp) => { let result = resp.data; if (result.code == 200) { message.success(formatMessage('page.add.success', '出库成功')); open.value = false; emit('closeParent', true) } else { message.error(result.msg); } }) } const handleOrderMergePreview = async () => { let data = records.value; if (data.length == 0) { message.error(formatMessage("page.orderOut.mergeOrderOut.checkedError", "请选择至少一条数据")); return; } loading.value = true; await getOperationPort(); tableData.value = [] tableDataValue = [] let defaultOperationPort = ""; if (operationPortList.value.length > 0) { defaultOperationPort = operationPortList.value[0].value; } post('/api/out/orderOut/merge/loc/preview', data).then((resp) => { let result = resp.data; if (result.code == 200) { let tmp = result.data; tableDataValue = tmp; let tableDataTmp = [] let idx = 0; let colSpan = [] tmp.forEach((item) => { item.locs.forEach((val) => { let dataTmp = JSON.parse(JSON.stringify(item)); dataTmp.locId = val.locId; dataTmp.locNo = val.locNo; dataTmp.locDetlId = val.locDetlId; dataTmp.anfme = val.anfme; dataTmp.key = idx; dataTmp.operationPort = defaultOperationPort; tableDataTmp.push(dataTmp); }) let count = item.locs.length; if (item.anfme > 0) { let dataTmp = JSON.parse(JSON.stringify(item)); dataTmp.locId = null; dataTmp.locNo = null; dataTmp.locDetlId = null; dataTmp.anfme = item.anfme; dataTmp.key = idx; dataTmp.operationPort = defaultOperationPort; tableDataTmp.push(dataTmp); count++; } colSpan[idx] = count idx += count; }) tableDataColSpan = colSpan; tableData.value = tableDataTmp; loading.value = false; } else { message.error(result.msg); } }) } defineExpose({ open, showWidth, records, }) </script> <script> export default { name: '预览合并订单出库' } </script> <template> <div> <a-modal v-model:open="open" :width="showWidth" :title="formatMessage('page.orderOutPreview.preview', '预览合并订单出库')" @ok="handleOk"> <a-table :data-source="tableData" :loading="loading" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="index" :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns"> <template #bodyCell="{ column, text, record, index }"> <template v-if="column.dataIndex === 'locNo'"> <div v-if="record.locId != null"> <a-tag color="green">{{ record.locNo }}</a-tag> </div> <div v-else> <a-tag color="red">库存不足</a-tag> </div> </template> <template v-if="column.dataIndex === 'operationPort'"> <a-select v-model:value="record.operationPort" :options="operationPortList"></a-select> </template> </template> </a-table> </a-modal> </div> </template> <style></style> zy-asrs-admin/src/views/out/orderOut/index.vue
New file @@ -0,0 +1,232 @@ <script setup> import { ref, computed, reactive } from 'vue'; import { useRouter } from "vue-router"; import { get, post, postBlob } from '@/utils/request.js' import { message, Modal } from 'ant-design-vue'; import { logout } from '@/config.js'; import { formatMessage } from '@/utils/localeUtils.js'; import useTableSearch from '@/utils/tableUtils.jsx'; import OrderOutBatchPreviewView from '@/components/orderOut/orderOutBatchPreview/index.vue'; import OrderOutMergePreviewView from '@/components/orderOut/orderOutMergePreview/index.vue'; const router = useRouter(); const TABLE_KEY = 'table-order-detl'; let currentPage = 1; let pageSize = 10; const { getColumnSearchProps, handleResizeColumn, } = useTableSearch(); let currentOrder = ref(null); let searchInput = ref(null); let tableData = ref([]); const orderOutBatchPreviewChild = ref(null); const orderOutMergePreviewChild = ref(null); const checkedOrderKeys = ref([]); getPage(); const columns = [ { title: formatMessage('db.man_order_detl.order_no', '订单编号'), dataIndex: 'orderNo', width: 140, ellipsis: true, ...getColumnSearchProps('orderNo'), }, { title: formatMessage('db.man_order_detl.anfme', '数量'), dataIndex: 'anfme', width: 140, ellipsis: true, ...getColumnSearchProps('anfme'), }, { title: formatMessage('db.man_order_detl.qty', '已完成数量'), dataIndex: 'qty', width: 140, ellipsis: true, ...getColumnSearchProps('qty'), }, { title: formatMessage('db.man_order_detl.work_qty', '作业中数量'), dataIndex: 'workQty', width: 140, ellipsis: true, ...getColumnSearchProps('workQty'), }, { title: formatMessage('db.man_order_detl.matnr', '商品编号'), dataIndex: ['mat$', 'matnr'], width: 140, ellipsis: true, ...getColumnSearchProps('matId$'), }, { title: formatMessage('db.man_order_detl.batch', '批号'), dataIndex: 'batch', width: 140, ellipsis: true, ...getColumnSearchProps('batch'), }, { title: formatMessage('common.operation', '操作'), name: 'oper', dataIndex: 'oper', key: 'oper', width: 140, }, ]; const state = reactive({ selectedRowKeys: [], loading: false, }); const onSelectChange = selectedRowKeys => { // console.log('selectedRowKeys changed: ', selectedRowKeys); state.selectedRowKeys = selectedRowKeys; }; function getPage() { if (currentOrder.value != null) { get('/api/orderDetl/orderId/' + currentOrder.value.id, {}).then((resp) => { let result = resp.data; if (result.code == 200) { let data = result.data; tableData.value = data; } else if (result.code === 401) { message.error(result.msg); logout() } else { message.error(result.msg); } }) } } function handleTableReload(value) { getPage() } let orderData = ref([]); let searchOrder = ref(""); getOrderData() function getOrderData() { post('/api/order/out/page', { current: currentPage, pageSize: pageSize, condition: searchOrder.value }).then((resp) => { let result = resp.data; if (result.code == 200) { let data = result.data.records; orderData.value = data } else if (result.code === 401) { message.error(result.msg); logout() } else { message.error(result.msg); } }) } const handleOrderSelected = (selectedKeys, e) => { currentOrder.value = e.selectedNodes[0]; getPage() } const handleSearchOrder = (e) => { getOrderData() } const handleBatchOrderOut = () => { let data = state.selectedRowKeys; handleOrderOutPreview(data) } const handleOrderOutPreview = (data) => { if (data.length == 0) { message.error(formatMessage("page.orderOut.batchOrderOut.error", "请选择至少一条出库明细")); return; } orderOutBatchPreviewChild.value.open = true; orderOutBatchPreviewChild.value.records = data; } const handleMergeOrderOut = () => { let orderIdList = []; checkedOrderKeys.value.forEach((idx) => { let index = parseInt(idx.split("-")[1]); orderIdList.push(orderData.value[index].id) }) if (orderIdList.length == 0) { message.error(formatMessage("page.orderOut.mergeOrderOut.error", "请选择至少一条订单")); return; } orderOutMergePreviewChild.value.open = true; orderOutMergePreviewChild.value.records = orderIdList; } const handleChildReload = () => { handleTableReload() } </script> <script> export default { name: '订单出库' } </script> <template> <div style="display: flex;"> <a-card :title="formatMessage('common.order', '订单')" style="flex: 4;margin-right: 30px;"> <a-button @click="handleMergeOrderOut()"> {{ formatMessage('common.orderOut', '合并订单') }} </a-button> <a-input v-model:value="searchOrder" @change="handleSearchOrder" :placeholder="formatMessage('page.input', '请输入')" style="margin-bottom: 8px" /> <a-tree @select="handleOrderSelected" :tree-data="orderData" v-model:checkedKeys="checkedOrderKeys" checkable blockNode> <template #title="{ orderNo, createTime$ }"> <div style="display: flex;justify-content: space-between"> <div>{{ orderNo }}</div> <div>{{ createTime$ }}</div> </div> </template> </a-tree> </a-card> <a-card style="flex: 10;"> <div class="table-header"> <a-button size="small" @click="handleBatchOrderOut()"> {{ formatMessage('common.orderOut', '批量出库') }} </a-button> </div> <a-table :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }" :data-source="tableData" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="id" :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns"> <template #bodyCell="{ column, text, record }"> <template v-if="column.dataIndex === 'oper'"> <div style="display: flex;justify-content: space-evenly;"> <a-button size="small" @click="handleOrderOutPreview([record.id])"> {{ formatMessage('common.orderOut', '出库') }} </a-button> </div> </template> </template> </a-table> </a-card> <OrderOutBatchPreviewView ref="orderOutBatchPreviewChild" @reload="handleChildReload" /> <OrderOutMergePreviewView ref="orderOutMergePreviewChild" @reload="handleChildReload" /> </div> </template> <style></style> zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/OutController.java
@@ -1,14 +1,23 @@ package com.zy.asrs.wms.asrs.controller; import com.zy.asrs.framework.common.R; import com.zy.asrs.wms.asrs.entity.dto.MergePreviewDto; import com.zy.asrs.wms.asrs.entity.dto.MergePreviewResultDto; import com.zy.asrs.wms.asrs.entity.dto.OrderOutBatchPreviewDto; import com.zy.asrs.wms.asrs.entity.param.OrderOutBatchPreviewParam; import com.zy.asrs.wms.asrs.entity.param.OrderOutMergeParam; import com.zy.asrs.wms.asrs.entity.param.OrderOutMergePreviewParam; import com.zy.asrs.wms.asrs.entity.param.OutParam; import com.zy.asrs.wms.asrs.manage.OutManage; import com.zy.asrs.wms.system.controller.BaseController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @@ -22,8 +31,44 @@ * 出库 */ @PostMapping("/out/start") @Transactional public R start(@RequestBody OutParam param) { outManage.out(param); return R.ok(); } @PostMapping("/out/orderOut/batch/preview") @Transactional public R orderOutBatchPreview(@RequestBody OrderOutBatchPreviewParam param) { List<OrderOutBatchPreviewDto> previewDtos = outManage.orderOutBatchPreview(param); return R.ok().add(previewDtos); } @PostMapping("/out/orderOut/batch") @Transactional public R orderOutBatch(@RequestBody List<OrderOutBatchPreviewDto> param) { outManage.orderOutBatch(param); return R.ok(); } @PostMapping("/out/orderOut/merge/preview") @Transactional public R orderOutMergePreview(@RequestBody OrderOutMergePreviewParam param) { List<MergePreviewDto> dtos = outManage.orderOutMergePreview(param); return R.ok().add(dtos); } @PostMapping("/out/orderOut/merge/loc/preview") @Transactional public R orderOutMergeLocPreview(@RequestBody List<MergePreviewDto> param) { List<MergePreviewResultDto> dtos = outManage.orderOutMergeLocPreview(param); return R.ok().add(dtos); } @PostMapping("/out/orderOut/merge") @Transactional public R orderOutMerge(@RequestBody List<OrderOutMergeParam> param) { outManage.orderOutMerge(param); return R.ok(); } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/LocDetl.java
@@ -104,7 +104,6 @@ * 是否删除 1: 是 0: 否 */ @ApiModelProperty(value= "是否删除 1: 是 0: 否 ") @TableLogic private Integer deleted; /** zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/OrderDetl.java
@@ -343,7 +343,7 @@ for (MatField matField : service.list(new LambdaQueryWrapper<MatField>().eq(MatField::getUnique, 1))) { FieldParam param = new FieldParam(); param.setName(matField.getName()); param.setValue(dynamicFields.get(matField.getName())); param.setValue(dynamicFields.getOrDefault(matField.getName(), "")); list.add(param); } return list; zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/BatchPreviewOtherLocDto.java
New file @@ -0,0 +1,16 @@ package com.zy.asrs.wms.asrs.entity.dto; import lombok.Data; @Data public class BatchPreviewOtherLocDto { private Long locId; private String locNo; private Double stock; private Long locDetlId; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MatUniqueObjDto.java
New file @@ -0,0 +1,17 @@ package com.zy.asrs.wms.asrs.entity.dto; import com.zy.asrs.wms.asrs.entity.param.FieldParam; import lombok.Data; import java.util.List; @Data public class MatUniqueObjDto { private String matnr; private String batch; private List<FieldParam> params; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewDto.java
New file @@ -0,0 +1,42 @@ package com.zy.asrs.wms.asrs.entity.dto; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.zy.asrs.wms.asrs.entity.param.FieldParam; import lombok.Data; import java.util.HashMap; import java.util.List; import java.util.Map; @Data public class MergePreviewDto { private String matnr; private String batch; private Double anfme; private List<Long> orderIds; private List<FieldParam> fieldParams; private String fieldParamsEncode; //动态扩展字段 public transient Map<String, Object> dynamicFields = new HashMap<>(); @JsonAnyGetter public Map<String,Object> getDynamicFields() { return dynamicFields; } public String getFieldString(String key) { return dynamicFields.get(key).toString(); } public void setField(String key, Object value) { dynamicFields.put(key, value); } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java
New file @@ -0,0 +1,49 @@ package com.zy.asrs.wms.asrs.entity.dto; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.zy.asrs.common.utils.Synchro; import com.zy.asrs.wms.asrs.entity.param.FieldParam; import lombok.Data; import java.util.HashMap; import java.util.List; import java.util.Map; @Data public class MergePreviewResultDto { private String matnr; private String batch; private Double anfme; private List<Long> orderIds; private List<MergePreviewResultLocDto> locs; private List<FieldParam> fieldParams; private String fieldParamsEncode; //动态扩展字段 public transient Map<String, Object> dynamicFields = new HashMap<>(); @JsonAnyGetter public Map<String,Object> getDynamicFields() { return dynamicFields; } public String getFieldString(String key) { return dynamicFields.get(key).toString(); } public void setField(String key, Object value) { dynamicFields.put(key, value); } public void sync(Object source) { Synchro.Copy(source, this); } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultLocDto.java
New file @@ -0,0 +1,16 @@ package com.zy.asrs.wms.asrs.entity.dto; import lombok.Data; @Data public class MergePreviewResultLocDto { private Long locId; private String locNo; private Long locDetlId; private Double anfme; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutBatchPreviewDto.java
New file @@ -0,0 +1,54 @@ package com.zy.asrs.wms.asrs.entity.dto; import com.zy.asrs.framework.common.Cools; import com.zy.asrs.framework.common.SpringUtils; import com.zy.asrs.wms.asrs.entity.LocDetl; import com.zy.asrs.wms.asrs.entity.OrderDetl; import com.zy.asrs.wms.asrs.service.LocDetlService; import com.zy.asrs.wms.asrs.service.OrderDetlService; import lombok.Data; import java.util.ArrayList; import java.util.List; @Data public class OrderOutBatchPreviewDto { private Long locId; private String locNo; private Long locDetlId; private Boolean all; private Double anfme; private Double stock; private Long orderDetlId; private List<BatchPreviewOtherLocDto> otherLoc; public LocDetl getLocDetl$() { LocDetlService service = SpringUtils.getBean(LocDetlService.class); LocDetl locDetl = service.getById(locDetlId); if (!Cools.isEmpty(locDetl)){ return locDetl; } return null; } public OrderDetl getOrderDetl$() { OrderDetlService service = SpringUtils.getBean(OrderDetlService.class); OrderDetl orderDetl = service.getById(orderDetlId); if (!Cools.isEmpty(orderDetl)){ List<OrderDetl> orderDetls = new ArrayList<>(); orderDetls.add(orderDetl); List<OrderDetl> list = service.parseDetl(orderDetls); return list.get(0); } return null; } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeDto.java
New file @@ -0,0 +1,34 @@ package com.zy.asrs.wms.asrs.entity.dto; import com.zy.asrs.common.utils.Synchro; import com.zy.asrs.wms.asrs.entity.param.FieldParam; import lombok.Data; import java.util.List; @Data public class OrderOutMergeDto { private Long locId; private String locNo; private Long locDetlId; private Long orderDetlId; private String matnr; private String batch; private Double anfme; private Long operationPort; private List<FieldParam> fieldParams; public void sync(Object source) { Synchro.Copy(source, this); } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OutDetlDto.java
@@ -20,4 +20,6 @@ */ private Double stock; private Long orderDetlId; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/FieldSortParam.java
@@ -13,4 +13,11 @@ */ private String value; public FieldSortParam() { } public FieldSortParam(String name, String value) { this.name = name; this.value = value; } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutBatchPreviewParam.java
New file @@ -0,0 +1,12 @@ package com.zy.asrs.wms.asrs.entity.param; import lombok.Data; import java.util.List; @Data public class OrderOutBatchPreviewParam { private List<Long> orderDetlIds; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergeParam.java
New file @@ -0,0 +1,28 @@ package com.zy.asrs.wms.asrs.entity.param; import lombok.Data; import java.util.List; @Data public class OrderOutMergeParam { private Long locId; private String locNo; private Long locDetlId; private String matnr; private String batch; private Double anfme; private Long operationPort; private List<FieldParam> fieldParams; private List<Long> orderIds; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java
New file @@ -0,0 +1,12 @@ package com.zy.asrs.wms.asrs.entity.param; import lombok.Data; import java.util.List; @Data public class OrderOutMergePreviewParam { private List<Long> orderIds; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/manage/OutManage.java
@@ -1,23 +1,24 @@ package com.zy.asrs.wms.asrs.manage; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wms.asrs.entity.dto.OutDetlDto; import com.zy.asrs.wms.asrs.entity.dto.OutLocDto; import com.zy.asrs.wms.asrs.entity.dto.*; import com.zy.asrs.wms.asrs.entity.enums.LocStsType; import com.zy.asrs.wms.asrs.entity.param.OutParam; import com.zy.asrs.wms.asrs.entity.enums.OrderSettleType; import com.zy.asrs.wms.asrs.entity.param.*; import com.zy.asrs.wms.asrs.entity.*; import com.zy.asrs.wms.asrs.service.*; import com.zy.asrs.wms.utils.OrderUtils; import com.zy.asrs.wms.utils.OutUtils; import com.zy.asrs.wms.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.*; /** * 出库管理 @@ -47,6 +48,10 @@ private OrderDetlService orderDetlService; @Autowired private OutUtils outUtils; @Autowired private OperationPortService operationPortService; @Autowired private OrderUtils orderUtils; /** @@ -126,4 +131,588 @@ } } } public List<OrderOutBatchPreviewDto> orderOutBatchPreview(OrderOutBatchPreviewParam param) { List<Long> orderDetlIds = param.getOrderDetlIds(); if (orderDetlIds.isEmpty()) { throw new CoolException("订单明细不能为空"); } List<OrderDetl> orderDetls = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>().in(OrderDetl::getId, orderDetlIds).orderByAsc(OrderDetl::getOrderNo, OrderDetl::getCreateTime)); if (orderDetls.isEmpty()) { throw new CoolException("订单明细不存在"); } orderDetls = orderDetlService.parseDetl(orderDetls); HashMap<Long, List<LocDetl>> orderDetlLocMap = new HashMap<>(); List<OutDetlDto> detlDtos = new ArrayList<>(); for (OrderDetl orderDetl : orderDetls) { double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D); if (issued <= 0.0D) { continue; } List<LocDetl> locDetls = locDetlService.queryStock(orderDetl.getMat$().getMatnr(), orderDetl.getBatch(), orderDetl.getUniqueField()); orderDetlLocMap.put(orderDetl.getId(), locDetls); for (LocDetl locDetl : locDetls) { if (issued > 0) { OutDetlDto outDetlDto = new OutDetlDto(); outDetlDto.setDetlId(locDetl.getId()); outDetlDto.setAnfme(issued >= locDetl.getAnfme() ? locDetl.getAnfme() : issued); outDetlDto.setStock(locDetl.getAnfme()); outDetlDto.setOrderDetlId(orderDetl.getId()); detlDtos.add(outDetlDto); issued = issued - outDetlDto.getAnfme(); }else { break; } } } HashMap<Long, List<OutDetlDto>> map = new HashMap<>(); for (OutDetlDto detlDto : detlDtos) { LocDetl locDetl = locDetlService.getById(detlDto.getDetlId()); List<OutDetlDto> dtos = map.get(locDetl.getLocId()); if (dtos == null) { dtos = new ArrayList<>(); dtos.add(detlDto); }else { dtos.add(detlDto); } map.put(locDetl.getLocId(), dtos); } List<Long> orderDetlIdsTmp = param.getOrderDetlIds(); List<OrderOutBatchPreviewDto> previewDtos = new ArrayList<>(); for (Map.Entry<Long, List<OutDetlDto>> entry : map.entrySet()) { Long locId = entry.getKey(); Loc loc = locService.getById(locId); List<OutDetlDto> outDetlDtos = entry.getValue(); for (OutDetlDto outDetlDto : outDetlDtos) { orderDetlIdsTmp.remove(outDetlDto.getOrderDetlId()); } Boolean all = outUtils.isAllForOut(locId, outDetlDtos); for (OutDetlDto outDetlDto : outDetlDtos) { OrderOutBatchPreviewDto previewDto = new OrderOutBatchPreviewDto(); previewDto.setLocId(locId); previewDto.setLocNo(loc.getLocNo()); previewDto.setLocDetlId(outDetlDto.getDetlId()); previewDto.setAll(all); previewDto.setAnfme(outDetlDto.getAnfme()); previewDto.setStock(outDetlDto.getStock()); previewDto.setOrderDetlId(outDetlDto.getOrderDetlId()); previewDtos.add(previewDto); List<BatchPreviewOtherLocDto> otherLocs = new ArrayList<>(); previewDto.setOtherLoc(otherLocs); List<LocDetl> locDetls = orderDetlLocMap.get(outDetlDto.getOrderDetlId()); for (LocDetl locDetl : locDetls) { BatchPreviewOtherLocDto otherLocDto = new BatchPreviewOtherLocDto(); otherLocDto.setLocId(locDetl.getLocId()); otherLocDto.setLocNo(locDetl.getLocNo()); otherLocDto.setStock(locDetl.getAnfme()); otherLocDto.setLocDetlId(locDetl.getId()); if (locDetl.getLocId().equals(locId)) { otherLocs.add(0, otherLocDto); continue; } if (otherLocs.isEmpty()) { otherLocs.add(otherLocDto); } for (int i = 0; i < otherLocs.size(); i++) { BatchPreviewOtherLocDto locDto = otherLocs.get(i); if (locDto.getLocId().equals(locDetl.getLocId())) { break; } otherLocs.add(otherLocDto); } } } } for (Long id : orderDetlIdsTmp) { OrderDetl orderDetl = orderDetlService.getById(id); double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D); OrderOutBatchPreviewDto previewDto = new OrderOutBatchPreviewDto(); previewDto.setLocId(null); previewDto.setLocNo(null); previewDto.setLocDetlId(null); previewDto.setAll(null); previewDto.setAnfme(issued); previewDto.setStock(0D); previewDto.setOrderDetlId(orderDetl.getId()); previewDtos.add(previewDto); } return previewDtos; } @Transactional public void orderOutBatch(List<OrderOutBatchPreviewDto> param) { if (param == null) { throw new CoolException("参数不能为空"); } if (param.isEmpty()) { throw new CoolException("参数不能为空"); } boolean noStock = true; for (OrderOutBatchPreviewDto dto : param) { if (dto.getStock() > 0) { noStock = false; break; } } if (noStock) { throw new CoolException("库存不足"); } HashMap<Long, List<OrderOutBatchPreviewDto>> detlMap = new HashMap<>(); for (OrderOutBatchPreviewDto previewDto : param) { if (previewDto.getLocId() == null) { continue; } if(detlMap.containsKey(previewDto.getLocDetlId())) { List<OrderOutBatchPreviewDto> previewDtos = detlMap.get(previewDto.getLocDetlId()); previewDtos.add(previewDto); detlMap.put(previewDto.getLocDetlId(), previewDtos); }else { List<OrderOutBatchPreviewDto> previewDtos = new ArrayList<>(); previewDtos.add(previewDto); detlMap.put(previewDto.getLocDetlId(), previewDtos); } } List<OrderOutBatchPreviewDto> dtos = new ArrayList<>(); for (Map.Entry<Long, List<OrderOutBatchPreviewDto>> entry : detlMap.entrySet()) { Long locDetlId = entry.getKey(); LocDetl locDetl = locDetlService.getById(locDetlId); if (locDetl == null) { continue; } Double stock = locDetl.getAnfme(); for (OrderOutBatchPreviewDto dto : entry.getValue()) { stock = stock - dto.getAnfme(); if (stock >= 0) { dtos.add(dto); } } } HashMap<Long, List<OrderOutBatchPreviewDto>> map = new HashMap<>(); for (OrderOutBatchPreviewDto previewDto : dtos) { if(map.containsKey(previewDto.getLocId())) { List<OrderOutBatchPreviewDto> previewDtos = map.get(previewDto.getLocId()); previewDtos.add(previewDto); map.put(previewDto.getLocId(), previewDtos); }else { List<OrderOutBatchPreviewDto> previewDtos = new ArrayList<>(); previewDtos.add(previewDto); map.put(previewDto.getLocId(), previewDtos); } } for (Map.Entry<Long, List<OrderOutBatchPreviewDto>> entry : map.entrySet()) { Long locId = entry.getKey(); List<OrderOutBatchPreviewDto> previewDtos = entry.getValue(); Boolean all = outUtils.isAllForPreview(locId, previewDtos); Loc loc = locService.getById(locId); if (loc == null) { continue; } if (!loc.getLocStsId().equals(LocStsType.F.val())) { continue; } long taskType = all ? 101L : 103L; Task task = new Task(); task.setTaskNo(workService.generateTaskNo(taskType)); task.setTaskSts(101L); task.setTaskType(taskType); task.setIoPri(workService.generateIoPri(taskType)); task.setOriginLoc(loc.getLocNo()); task.setTargetSite("A"); task.setBarcode(loc.getBarcode()); boolean res = taskService.save(task); if (!res) { throw new CoolException("保存工作档失败"); } for (OrderOutBatchPreviewDto dto : previewDtos) { LocDetl locDetl = locDetlService.getById(dto.getLocDetlId()); if(locDetl == null) { throw new CoolException("明细不存在"); } OrderDetl orderDetl = orderDetlService.getById(dto.getOrderDetlId()); if(orderDetl == null) { throw new CoolException("订单明细不存在"); } orderUtils.updateWorkQty(dto.getOrderDetlId(), dto.getAnfme()); TaskDetl taskDetl = new TaskDetl(); taskDetl.sync(locDetl); taskDetl.setTaskId(task.getId()); taskDetl.setAnfme(dto.getAnfme()); taskDetl.setStock(locDetl.getAnfme()); taskDetl.setOrderId(orderDetl.getOrderId()); taskDetl.setOrderNo(orderDetl.getOrderNo()); taskDetl.setDetlId(orderDetl.getId()); if (!taskDetlService.save(taskDetl)) { throw new CoolException("保存工作档明细失败"); } List<LocDetlField> locDetlFields = locDetlFieldService.list(new LambdaQueryWrapper<LocDetlField>().eq(LocDetlField::getDetlId, locDetl.getId())); for (LocDetlField locDetlField : locDetlFields) { TaskDetlField taskDetlField = new TaskDetlField(); taskDetlField.sync(locDetlField); taskDetlField.setDetlId(taskDetl.getId()); boolean taskDetlFieldSave = taskDetlFieldService.save(taskDetlField); if(!taskDetlFieldSave){ throw new CoolException("明细扩展生成失败"); } } } //库位F => R loc.setLocStsId(LocStsType.R.val()); loc.setUpdateTime(new Date()); boolean locUpdate = locService.updateById(loc); if(!locUpdate){ throw new CoolException("库位状态更新失败"); } } } @Transactional public List<MergePreviewDto> orderOutMergePreview(OrderOutMergePreviewParam param) { if (param == null) { throw new CoolException("参数不能为空"); } List<Long> orderIds = param.getOrderIds(); if (orderIds.isEmpty()) { throw new CoolException("订单不能为空"); } List<Order> orders = orderService.list(new LambdaQueryWrapper<Order>().in(Order::getId, orderIds)); if (orders.isEmpty()) { throw new CoolException("订单不存在"); } List<OrderDetl> orderDetls = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>().in(OrderDetl::getOrderId, orderIds)); if(orderDetls.isEmpty()){ throw new CoolException("订单明细不存在"); } orderDetls = orderDetlService.parseDetl(orderDetls); HashMap<String, Double> locDetlStockMap = new HashMap<>(); for (OrderDetl orderDetl : orderDetls) { String matUniqueKey = Utils.getMatUniqueKey(orderDetl.getMat$().getMatnr(), orderDetl.getBatch(), orderDetl.getUniqueField()); double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D); if (locDetlStockMap.containsKey(matUniqueKey)) { Double anfme = locDetlStockMap.get(matUniqueKey); anfme += issued; locDetlStockMap.put(matUniqueKey, anfme); }else { locDetlStockMap.put(matUniqueKey, issued); } } List<MergePreviewDto> mergePreviewDtos = new ArrayList<>(); for (Map.Entry<String, Double> entry : locDetlStockMap.entrySet()) { String matUniqueKey = entry.getKey(); Double anfme = entry.getValue(); MatUniqueObjDto matUniqueObj = Utils.getMatUniqueObj(matUniqueKey); HashMap<String, Object> dynamicFields = new HashMap<>(); for (FieldParam fieldParam : matUniqueObj.getParams()) { dynamicFields.put(fieldParam.getName(), fieldParam.getValue()); } MergePreviewDto dto = new MergePreviewDto(); dto.setMatnr(matUniqueObj.getMatnr()); dto.setBatch(matUniqueObj.getBatch()); dto.setAnfme(anfme); dto.setOrderIds(orderIds); dto.setFieldParamsEncode(JSON.toJSONString(matUniqueObj.getParams())); dto.setDynamicFields(dynamicFields); mergePreviewDtos.add(dto); } return mergePreviewDtos; } @Transactional public List<MergePreviewResultDto> orderOutMergeLocPreview(List<MergePreviewDto> param) { if (param == null) { throw new CoolException("参数不能为空"); } if (param.isEmpty()) { throw new CoolException("参数不能为空"); } for (MergePreviewDto dto : param) { List<FieldParam> fieldParams = JSON.parseArray(dto.getFieldParamsEncode(), FieldParam.class); dto.setFieldParams(fieldParams); } FieldSortParam sortParam = new FieldSortParam("anfme","desc"); List<FieldSortParam> sortParams = new ArrayList<>(); sortParams.add(sortParam); List<MergePreviewResultDto> resultDtos = new ArrayList<>(); for (MergePreviewDto dto : param) { List<LocDetl> locDetls = locDetlService.queryStock(dto.getMatnr(), dto.getBatch(), dto.getFieldParams(), sortParams); if(locDetls.isEmpty()){ continue; } List<MergePreviewResultLocDto> locDtos = new ArrayList<>(); MergePreviewResultDto resultDto = new MergePreviewResultDto(); resultDto.sync(dto); resultDto.setLocs(locDtos); resultDto.setOrderIds(dto.getOrderIds()); Double anfme = dto.getAnfme(); for (LocDetl locDetl : locDetls) { MergePreviewResultLocDto locDto = new MergePreviewResultLocDto(); locDto.setLocId(locDetl.getLocId()); locDto.setLocNo(locDetl.getLocNo()); locDto.setLocDetlId(locDetl.getId()); locDtos.add(locDto); if (anfme - locDetl.getAnfme() < 0) { locDto.setAnfme(anfme); break; } locDto.setAnfme(locDetl.getAnfme()); anfme -= locDetl.getAnfme(); } resultDto.setAnfme(anfme < 0 ? 0 : anfme); resultDtos.add(resultDto); } return resultDtos; } @Transactional public void orderOutMerge(List<OrderOutMergeParam> params) { if(params == null){ throw new CoolException("参数不能为空"); } if (params.isEmpty()) { throw new CoolException("参数不能为空"); } List<Long> orderIds = null; List<OrderOutMergeParam> filterParam = new ArrayList<>(); HashMap<String, OrderOutMergeParam> paramMap = new HashMap<>(); for (OrderOutMergeParam param : params) { if (param.getLocId() == null) { continue; } filterParam.add(param); String matUniqueKey = Utils.getMatUniqueKey(param.getMatnr(), param.getBatch(), param.getFieldParams()); paramMap.put(matUniqueKey, param); if (orderIds == null) { orderIds = param.getOrderIds(); } } if (orderIds == null) { throw new CoolException("订单不存在"); } List<Order> orderList = orderService.listByIds(orderIds); if (orderList.isEmpty()) { throw new CoolException("订单不存在"); } List<OrderDetl> orderDetls = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>().in(OrderDetl::getOrderId, orderIds)); if (orderDetls.isEmpty()) { throw new CoolException("订单明细不存在"); } HashMap<String, List<OrderDetl>> detlMap = new HashMap<>(); for (OrderDetl orderDetl : orderDetls) { String matUniqueKey = Utils.getMatUniqueKey(orderDetl.getMat$().getMatnr(), orderDetl.getBatch(), orderDetl.getUniqueField()); if (detlMap.containsKey(matUniqueKey)) { List<OrderDetl> detls = detlMap.get(matUniqueKey); detls.add(orderDetl); detlMap.put(matUniqueKey, detls); }else { List<OrderDetl> detls = new ArrayList<>(); detls.add(orderDetl); detlMap.put(matUniqueKey, detls); } } List<OrderOutMergeDto> orderOutMergeDtos = new ArrayList<>(); for (OrderOutMergeParam param : filterParam) { String matUniqueKey = Utils.getMatUniqueKey(param.getMatnr(), param.getBatch(), param.getFieldParams()); if (!detlMap.containsKey(matUniqueKey)) { continue; } Double requireAnfme = param.getAnfme(); List<OrderDetl> orderDetlList = detlMap.get(matUniqueKey); for (OrderDetl orderDetl : orderDetlList) { double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getQty() - orderDetl.getWorkQty()).orElse(0.0D); if (issued <= 0D) { continue; } OrderOutMergeDto orderOutMergeDto = new OrderOutMergeDto(); orderOutMergeDto.sync(param); orderOutMergeDto.setOrderDetlId(orderDetl.getId()); Double anfme = orderDetl.getAnfme(); Double updateWorkQty = null; double diffAnfme = requireAnfme - anfme; if (diffAnfme >= 0) { orderOutMergeDto.setAnfme(anfme); updateWorkQty = anfme; requireAnfme -= anfme; }else { orderOutMergeDto.setAnfme(requireAnfme); updateWorkQty = requireAnfme; requireAnfme -= requireAnfme; } orderOutMergeDtos.add(orderOutMergeDto); orderUtils.updateWorkQty(orderDetl.getId(), updateWorkQty); if (requireAnfme <= 0) { break; } } } HashMap<Long, List<OrderOutMergeDto>> map = new HashMap<>(); for (OrderOutMergeDto orderOutMergeDto : orderOutMergeDtos) { List<OrderOutMergeDto> list = null; if (map.containsKey(orderOutMergeDto.getLocId())) { list = map.get(orderOutMergeDto.getLocId()); }else { list = new ArrayList<>(); } list.add(orderOutMergeDto); map.put(orderOutMergeDto.getLocId(), list); } for (Map.Entry<Long, List<OrderOutMergeDto>> entry : map.entrySet()) { Long locId = entry.getKey(); List<OrderOutMergeDto> list = entry.getValue(); Boolean all = outUtils.isAllForMerge(locId, list); OrderOutMergeDto param = list.get(0); Long operationPortId = param.getOperationPort(); Loc loc = locService.getById(locId); if (loc == null) { throw new CoolException("库位不存在"); } if (!loc.getLocStsId().equals(LocStsType.F.val())) { throw new CoolException(loc.getLocNo() + "库位状态异常"); } OperationPort operationPort = operationPortService.getById(operationPortId); if (operationPort == null) { throw new CoolException("作业口不存在"); } long taskType = all ? 101L : 103L; Task task = new Task(); task.setTaskNo(workService.generateTaskNo(taskType)); task.setTaskSts(101L); task.setTaskType(taskType); task.setIoPri(workService.generateIoPri(taskType)); task.setOriginLoc(loc.getLocNo()); task.setTargetSite(operationPort.getFlag()); task.setBarcode(loc.getBarcode()); boolean res = taskService.save(task); if (!res) { throw new CoolException("保存工作档失败"); } for (OrderOutMergeDto merge : list) { LocDetl locDetl = locDetlService.getById(merge.getLocDetlId()); if(locDetl == null) { throw new CoolException("明细不存在"); } OrderDetl orderDetl = orderDetlService.getById(merge.getOrderDetlId()); if(orderDetl == null) { throw new CoolException("订单明细不存在"); } TaskDetl taskDetl = new TaskDetl(); taskDetl.sync(locDetl); taskDetl.setTaskId(task.getId()); taskDetl.setAnfme(merge.getAnfme()); taskDetl.setStock(locDetl.getAnfme()); taskDetl.setOrderId(orderDetl.getOrderId()); taskDetl.setOrderNo(orderDetl.getOrderNo()); taskDetl.setDetlId(orderDetl.getId()); if (!taskDetlService.save(taskDetl)) { throw new CoolException("保存工作档明细失败"); } List<LocDetlField> locDetlFields = locDetlFieldService.list(new LambdaQueryWrapper<LocDetlField>().eq(LocDetlField::getDetlId, locDetl.getId())); for (LocDetlField locDetlField : locDetlFields) { TaskDetlField taskDetlField = new TaskDetlField(); taskDetlField.sync(locDetlField); taskDetlField.setDetlId(taskDetl.getId()); boolean taskDetlFieldSave = taskDetlFieldService.save(taskDetlField); if(!taskDetlFieldSave){ throw new CoolException("明细扩展生成失败"); } } } //库位F => R loc.setLocStsId(LocStsType.R.val()); loc.setUpdateTime(new Date()); boolean locUpdate = locService.updateById(loc); if(!locUpdate){ throw new CoolException("库位状态更新失败"); } } } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/ViewLocDetlMapper.java
@@ -1,7 +1,6 @@ package com.zy.asrs.wms.asrs.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.zy.asrs.wms.asrs.entity.LocDetl; import com.zy.asrs.wms.asrs.entity.ViewLocDetl; import com.zy.asrs.wms.asrs.entity.param.FieldParam; import com.zy.asrs.wms.asrs.entity.param.FieldSortParam; @@ -16,7 +15,7 @@ @Repository public interface ViewLocDetlMapper extends BaseMapper<ViewLocDetl> { List<Map<String,Object>> getList(String matnr, String batch, List<FieldParam> param); List<Map<String, Object>> getList(String matnr, String batch, List<FieldParam> param, @Param("sortParam") List<FieldSortParam> sortParam); List<Map<String,Object>> getListLike(String matnr, String batch, List<FieldParam> param); zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/LocDetlService.java
@@ -8,7 +8,6 @@ import com.zy.asrs.wms.asrs.entity.param.FieldSortParam; import com.zy.asrs.wms.common.domain.BaseParam; import com.zy.asrs.wms.common.domain.PageParam; import org.apache.poi.ss.formula.functions.T; import java.util.List; import java.util.Map; @@ -21,6 +20,8 @@ List<LocDetl> parseLocDetl(List<LocDetl> list); List<LocDetl> listSuitableMat( List<FieldParam> param, List<FieldSortParam> sortParam); List<LocDetl> queryStock(String matnr, String batch, List<FieldParam> param); List<LocDetl> queryStock(String matnr, String batch, List<FieldParam> param, List<FieldSortParam> sortParam); } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/OrderDetlService.java
@@ -9,4 +9,6 @@ List<OrderDetl> getOrderDetlByOrderId(Long orderId); List<OrderDetl> parseDetl(List<OrderDetl> list); } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/LocDetlServiceImpl.java
@@ -5,23 +5,23 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.zy.asrs.wms.asrs.entity.LocDetl; import com.zy.asrs.wms.asrs.entity.LocDetlField; import com.zy.asrs.wms.asrs.entity.ViewLocDetl; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wms.asrs.entity.*; import com.zy.asrs.wms.asrs.entity.enums.LocStsType; import com.zy.asrs.wms.asrs.entity.param.FieldParam; import com.zy.asrs.wms.asrs.entity.param.FieldSortParam; import com.zy.asrs.wms.asrs.mapper.LocDetlMapper; import com.zy.asrs.wms.asrs.mapper.ViewLocDetlMapper; import com.zy.asrs.wms.asrs.service.LanewayRuleService; import com.zy.asrs.wms.asrs.service.LocDetlFieldService; import com.zy.asrs.wms.asrs.service.LocDetlService; import com.zy.asrs.wms.asrs.service.LocService; import com.zy.asrs.wms.common.domain.BaseParam; import com.zy.asrs.wms.common.domain.PageParam; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.*; @Service("locDetlService") public class LocDetlServiceImpl extends ServiceImpl<LocDetlMapper, LocDetl> implements LocDetlService { @@ -30,6 +30,10 @@ private ViewLocDetlMapper viewLocDetlMapper; @Autowired private LocDetlFieldService locDetlFieldService; @Autowired private LocService locService; @Autowired private LanewayRuleService lanewayRuleService; @Override public PageParam<ViewLocDetl, BaseParam> getPage(PageParam<ViewLocDetl, BaseParam> pageParam, QueryWrapper<ViewLocDetl> buildWrapper) { @@ -88,22 +92,90 @@ return list; } /** * 根据出库条件查询符合的库存 * @param param 查询条件 * @param sortParam 排序字段 * @return */ @Override public List<LocDetl> listSuitableMat( List<FieldParam> param, List<FieldSortParam> sortParam) { List<Map<String, Object>> stock = viewLocDetlMapper.listSuitableMat(param, sortParam); public List<LocDetl> queryStock(String matnr, String batch, List<FieldParam> param) { return queryStock(matnr, batch, param, null); } @Override public List<LocDetl> queryStock(String matnr, String batch, List<FieldParam> param, List<FieldSortParam> sortParam) { List<Map<String, Object>> list = viewLocDetlMapper.getList(matnr, batch, param, sortParam); List<LocDetl> locDetlsSort = resortDetls(list); return locDetlsSort; } private List<LocDetl> resortDetls(List<Map<String, Object>> list) { List<LocDetl> locDetls = new ArrayList<>(); for (Map<String, Object> objectMap : stock) { LocDetl detl = JSON.parseObject(JSON.toJSONString(objectMap), LocDetl.class); detl.syncFieldMap(objectMap); locDetls.add(detl); for (Map<String, Object> map : list) { LocDetl locDetl = JSON.parseObject(JSON.toJSONString(map), LocDetl.class); locDetls.add(locDetl); } return locDetls; locDetls = parseLocDetl(locDetls); List<Long> sortDirctLoc = new ArrayList<>(); HashMap<Long, List<LocDetl>> sortMap = new HashMap<>(); for (LocDetl locDetl : locDetls) { List<LocDetl> detls = sortMap.get(locDetl.getLocId()); if (detls == null) { detls = new ArrayList<>(); detls.add(locDetl); sortMap.put(locDetl.getLocId(), detls); }else { detls.add(locDetl); sortMap.put(locDetl.getLocId(), detls); } Loc loc = locService.getById(locDetl.getLocId()); if (loc == null) { continue; } if(!loc.getLocStsId().equals(LocStsType.F.val())){ continue; } //获取库位所在巷道 LanewayRule lanewayRule = lanewayRuleService.getLaneByLoc(loc); if(lanewayRule == null) { throw new CoolException("库位未配置巷道"); } //获取库位方向 List<Integer> direction = null; if (lanewayRule.getLaneX$().contains(loc.getRow1())) { direction = lanewayRule.getLaneX$(); }else { direction = lanewayRule.getLaneY$(); } Collections.reverse(direction); for (Integer row : direction) { Loc one = locService.getOne(new LambdaQueryWrapper<Loc>() .eq(Loc::getRow1, row) .eq(Loc::getBay1, loc.getBay1()) .eq(Loc::getLev1, loc.getLev1())); if (one == null) { continue; } sortDirctLoc.add(one.getId()); } } List<LocDetl> sortDirctDetls = new ArrayList<>(); for (Long locId : sortDirctLoc) { List<LocDetl> detls = sortMap.get(locId); if(detls == null) { continue; } sortDirctDetls.addAll(detls); } return sortDirctDetls; } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderDetlServiceImpl.java
@@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; @Service("orderDetlService") @@ -27,4 +28,13 @@ } return orderDetls; } @Override public List<OrderDetl> parseDetl(List<OrderDetl> orderDetls) { for (OrderDetl orderDetl : orderDetls) { List<OrderDetlField> list = orderDetlFieldService.list(new LambdaQueryWrapper<OrderDetlField>().eq(OrderDetlField::getDetlId, orderDetl.getId())); orderDetl.syncField(list); } return orderDetls; } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/LocUtils.java
@@ -6,7 +6,6 @@ import com.zy.asrs.wms.asrs.entity.*; import com.zy.asrs.wms.asrs.entity.enums.LocStsType; import com.zy.asrs.wms.asrs.entity.enums.LocTypeHeightType; import com.zy.asrs.wms.asrs.entity.enums.ShelvesRuleType; import com.zy.asrs.wms.asrs.entity.param.FieldParam; import com.zy.asrs.wms.asrs.mapper.ViewLocDetlMapper; import com.zy.asrs.wms.asrs.mapper.ViewTaskDetlMapper; @@ -72,7 +71,7 @@ //从库存中进行匹配 List<Loc> locs2 = new ArrayList<>(); List<Map<String, Object>> list2 = viewLocDetlMapper.getList(mat.getMatnr(), batch, uniqueFields); List<Map<String, Object>> list2 = viewLocDetlMapper.getList(mat.getMatnr(), batch, uniqueFields, null); for (Map<String, Object> map : list2) { Loc one = locService.getById(map.get("locId").toString()); if (one == null) { zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OrderUtils.java
New file @@ -0,0 +1,57 @@ package com.zy.asrs.wms.utils; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wms.asrs.entity.Order; import com.zy.asrs.wms.asrs.entity.OrderDetl; import com.zy.asrs.wms.asrs.entity.enums.OrderSettleType; import com.zy.asrs.wms.asrs.service.OrderDetlService; import com.zy.asrs.wms.asrs.service.OrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import java.util.Date; @Component public class OrderUtils { @Autowired private OrderService orderService; @Autowired private OrderDetlService orderDetlService; @Transactional public void updateWorkQty(Long orderDetlId, Double qty) { OrderDetl orderDetl = orderDetlService.getById(orderDetlId); if(orderDetl == null) { throw new CoolException("订单明细不存在"); } Order order = orderService.getById(orderDetl.getOrderId()); if(order == null) { throw new CoolException("订单不存在"); } if (order.getOrderSettle() == OrderSettleType.COMPLETE.val() || order.getOrderSettle() == OrderSettleType.CANCEL.val() || order.getOrderSettle() == OrderSettleType.WAIT_CANCEL.val() || order.getOrderSettle() == OrderSettleType.REPORT_COMPLETE.val()) { throw new CoolException("订单当前状态不可修改"); } Double workQty = orderDetl.getWorkQty(); orderDetl.setWorkQty(workQty + qty); orderDetl.setUpdateTime(new Date()); if (!orderDetlService.updateById(orderDetl)) { throw new CoolException("订单明细更新失败"); } order.setOrderSettle(OrderSettleType.WORKING.val()); order.setUpdateTime(new Date()); if(!orderService.updateById(order)) { throw new CoolException("订单更新失败"); } } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OutUtils.java
@@ -2,8 +2,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.asrs.wms.asrs.entity.LocDetl; import com.zy.asrs.wms.asrs.entity.dto.OrderOutBatchPreviewDto; import com.zy.asrs.wms.asrs.entity.dto.OrderOutMergeDto; import com.zy.asrs.wms.asrs.entity.dto.OutDetlDto; import com.zy.asrs.wms.asrs.entity.dto.OutLocDto; import com.zy.asrs.wms.asrs.entity.param.OrderOutMergeParam; import com.zy.asrs.wms.asrs.entity.param.OutParam; import com.zy.asrs.wms.asrs.service.LocDetlService; import org.springframework.beans.factory.annotation.Autowired; @@ -53,18 +56,8 @@ OutLocDto locDto = entry.getValue(); locDtos.add(locDto); List<LocDetl> list = locDetlService.list(new LambdaQueryWrapper<LocDetl>().eq(LocDetl::getLocId, locDto.getLocId())); Double sum = 0D; for (LocDetl locDetl : list) { sum += locDetl.getAnfme(); } for (OutDetlDto detl : locDto.getDetls()) { sum -= detl.getAnfme(); } locDto.setAll(sum == 0); Boolean all = this.isAllForOut(locDto.getLocId(), locDto.getDetls()); locDto.setAll(all); locDto.setOperationPort(outParam.getOperationPort()); } @@ -93,4 +86,46 @@ return locDtos; } public Boolean isAllForMerge(Long locId, List<OrderOutMergeDto> list) { List<Double> anfmeList = new ArrayList<>(); for (OrderOutMergeDto dto : list) { anfmeList.add(dto.getAnfme()); } return isAll(locId, anfmeList); } public Boolean isAllForPreview(Long locId, List<OrderOutBatchPreviewDto> list) { List<Double> anfmeList = new ArrayList<>(); for (OrderOutBatchPreviewDto outPreviewDto : list) { anfmeList.add(outPreviewDto.getAnfme()); } return isAll(locId, anfmeList); } public Boolean isAllForOut(Long locId, List<OutDetlDto> list) { List<Double> anfmeList = new ArrayList<>(); for (OutDetlDto dto : list) { anfmeList.add(dto.getAnfme()); } return isAll(locId, anfmeList); } private Boolean isAll(Long locId, List<Double> anfmeList) { if (anfmeList.isEmpty()) { return false; } List<LocDetl> locDetls = locDetlService.list(new LambdaQueryWrapper<LocDetl>().eq(LocDetl::getLocId, locId)); Double sum = 0D; for (LocDetl locDetl : locDetls) { sum += locDetl.getAnfme(); } for (Double anfme : anfmeList) { sum -= anfme; } return sum <= 0; } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/Utils.java
@@ -1,14 +1,14 @@ package com.zy.asrs.wms.utils; import com.alibaba.fastjson.JSON; import com.zy.asrs.framework.common.Cools; import com.zy.asrs.wms.asrs.entity.dto.MatUniqueObjDto; import com.zy.asrs.wms.asrs.entity.param.FieldParam; import com.zy.asrs.wms.common.constant.Constants; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.*; import java.util.function.BiConsumer; import java.util.function.Function; @@ -19,6 +19,66 @@ public static final String _LINK = "-"; public static final String _KEY_LINK = "_"; public static String getMatUniqueKey(String matnr, String batch, List<FieldParam> params) { MatUniqueObjDto dto = new MatUniqueObjDto(); dto.setMatnr(matnr); dto.setBatch(batch); dto.setParams(params); String encode = Base64.getEncoder().encodeToString(JSON.toJSONString(dto).getBytes()); return encode; } public static MatUniqueObjDto getMatUniqueObj(String matUniqueKey) { byte[] decode = Base64.getDecoder().decode(matUniqueKey); String decodeStr = new String(decode); MatUniqueObjDto dto = JSON.parseObject(decodeStr, MatUniqueObjDto.class); return dto; } public static boolean checkMatSame(String matnr1, String batch1, List<FieldParam> params1, String matnr2, String batch2, List<FieldParam> params2) { if (!matnr1.equals(matnr2)) { return false; } if (batch1 != null && batch2 != null) { if(!batch1.equals(batch2)) { return false; } } boolean check = true; if(params1 != null && params2 != null) { if(params1.size() != params2.size()) { return false; } for (int i = 0; i < params1.size(); i++) { FieldParam param1 = params1.get(i); FieldParam param2 = params2.get(i); if (!param1.getName().equals(param2.getName())) { check = false; break; } if(Cools.isEmpty(param1.getValue()) && Cools.isEmpty(param2.getValue())) { continue; } if(!param1.getValue().equals(param2.getValue())) { check = false; break; } } } return check; } /** * 通过库位号获取 排 */ zy-asrs-wms/src/main/resources/mapper/asrs/ViewLocDetlMapper.xml
@@ -15,6 +15,11 @@ </if> </foreach> </if> <if test="sortParam!=null and sortParam.size()>0"> <foreach collection="sortParam" item="item" open="order by " separator="," close=" "> ${item.name} ${item.value} </foreach> </if> </select> <select id="getListLike" resultType="map">