#
Junjie
2024-09-07 11b3ac7e9f6bc9144ddd7a5261cf69796f38d7b3
#
15个文件已修改
15个文件已添加
2188 ■■■■■ 已修改文件
zy-asrs-admin/src/components/orderOut/orderOutBatchPreview/index.vue 237 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-admin/src/components/orderOut/orderOutMergePreview/index.vue 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-admin/src/components/orderOut/orderOutMergePreview/stockOut.vue 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-admin/src/views/out/orderOut/index.vue 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/OutController.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/LocDetl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/OrderDetl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/BatchPreviewOtherLocDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MatUniqueObjDto.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewDto.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultDto.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/MergePreviewResultLocDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutBatchPreviewDto.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OrderOutMergeDto.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/OutDetlDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/FieldSortParam.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutBatchPreviewParam.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergeParam.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/param/OrderOutMergePreviewParam.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/manage/OutManage.java 601 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/ViewLocDetlMapper.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/LocDetlService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/OrderDetlService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/LocDetlServiceImpl.java 110 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/OrderDetlServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/LocUtils.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OrderUtils.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/OutUtils.java 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/java/com/zy/asrs/wms/utils/Utils.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wms/src/main/resources/mapper/asrs/ViewLocDetlMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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">