skyouc
11 小时以前 6cfcfa0b4d2d5a5cd28f4486594eb5db16b679c4
盘点单功能优化
8个文件已修改
2个文件已添加
1 文件已重命名
481 ■■■■ 已修改文件
rsf-admin/src/page/orders/check/CheckOrderCreate.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/check/CheckOrderList.jsx 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/check/CheckOrderModal.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/check/MatnrInfoModal.jsx 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/check/SelectMatnrModal.jsx 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CheckOrderController.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/CheckExceStatus.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/CheckOrderType.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/CheckOrderService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/check/CheckOrderCreate.jsx
@@ -42,9 +42,6 @@
import DialogCloseButton from "../../components/DialogCloseButton";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import { styled } from '@mui/material/styles';
import StatusSelectInput from "../../components/StatusSelectInput";
import OutOrderItemList from "./OutOrderItemList";
import MemoInput from "../../components/MemoInput";
import AddIcon from '@mui/icons-material/Add';
import SelectMatnrModal from "./SelectMatnrModal";
@@ -108,7 +105,7 @@
                    maxWidth="xl"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
                >
                    <Form
                        resource="outStock"
                        resource="check"
                    >
                        <DialogTitle id="form-dialog-title" sx={{
                            position: 'sticky',
@@ -206,7 +203,7 @@
export default OutOrderCreate;
const AddOutOrderButton = (setMatCreate) => {
const AddOutOrderButton = ({setMatCreate}) => {
    const record = useRecordContext();
    const addMats = (event) => {
        event.stopPropagation();
rsf-admin/src/page/orders/check/CheckOrderList.jsx
@@ -38,6 +38,8 @@
import DetailsIcon from '@mui/icons-material/Details';
import AddTaskIcon from '@mui/icons-material/AddTask';
import PublicIcon from '@mui/icons-material/Public';
import SelectMatnrModal from "./SelectMatnrModal";
import CheckOrderModal from "./CheckOrderModal";
import EditIcon from '@mui/icons-material/Edit';
import AddIcon from '@mui/icons-material/Add';
import request from '@/utils/request';
@@ -70,7 +72,7 @@
  <ReferenceInput source="type" reference="dictData" filter={{ dictTypeCode: 'sys_order_type', group: '3' }} label="table.field.checkOrder.type" alwaysOn>
    <AutocompleteInput label="table.field.checkOrder.type" optionValue="value" />
  </ReferenceInput>,
  <ReferenceInput source="wkType" reference="dictData" filter={{ dictTypeCode: 'sys_check_order_type'}} label="table.field.checkOrder.wkType" alwaysOn>
  <ReferenceInput source="wkType" reference="dictData" filter={{ dictTypeCode: 'sys_check_order_type' }} label="table.field.checkOrder.wkType" alwaysOn>
    <AutocompleteInput label="table.field.checkOrder.wkType" optionValue="value" />
  </ReferenceInput>,
  <NumberInput source="anfme" label="table.field.checkOrder.anfme" />,
@@ -97,7 +99,6 @@
  const translate = useTranslate();
  const refresh = useRefresh();
  const notify = useNotify();
  const [createDialog, setCreateDialog] = useState(false);
  const [manualDialog, setManualDialog] = useState(false);
  const [selectIds, setSelectIds] = useState([]);
@@ -140,7 +141,6 @@
        actions={(
          <TopToolbar>
            <FilterButton />
            <CreateByOrderButton setCreateDialog={setCreateDialog} />
            <MyCreateButton onClick={() => { setManualDialog(true); setmodalType(0) }} />
            <SelectColumnsButton preferenceKey='check' />
            <ImportButton value={'checkItem'} />
@@ -175,27 +175,20 @@
            <MyButton setCreateDialog={setManualDialog} setmodalType={setmodalType} />
            <EditButton label="toolbar.detail" icon={(<DetailsIcon />)}></EditButton>
            <CancelButton />
            <PublicButton setDrawerVal={setDrawerVal} drawerVal={drawerVal} setSelect={setSelect} />
          </WrapperField>
        </StyledDatagrid>
      </List>
      {/* <OutOrderCreate
      {/* <CheckOrderCreate
        open={manualDialog}
        setOpen={setManualDialog}
      /> */}
      {/* <SelectMatnrModal
      <SelectMatnrModal
        asnId={modalType}
        billReload={billReload}
        open={manualDialog}
        setOpen={setManualDialog}
      />
      <OutOrderModal
        open={createDialog}
        setOpen={setCreateDialog}
        preview={preview}
        setPreview={setPreview}
      />
      <OutStockWaveDialog open={waveRule} setOpen={setWaveRule} onClose={closeDialog} />
      {/* <OutStockWaveDialog open={waveRule} setOpen={setWaveRule} onClose={closeDialog} />
      <OutOrderPreview open={preview} setOpen={setPreview} />
      <PageEditDrawer
        title={"toolbar.publicWorking"}
@@ -251,19 +244,6 @@
  )
}
const CreateByOrderButton = ({ setCreateDialog }) => {
  const record = useRecordContext();
  const notify = useNotify();
  const refresh = useRefresh();
  const createByOrder = async (event) => {
    event.stopPropagation();
    setCreateDialog(true);
  }
  return (
    <Button onClick={createByOrder} label={'toolbar.asnCreate'}> <AddIcon /> </Button>
  )
}
const CancelButton = () => {
  const record = useRecordContext();
@@ -281,20 +261,5 @@
  return (
    record?.exceStatus == 10 ? <ConfirmButton label={"toolbar.cancel"} startIcon={<CancelOutlinedIcon />} onConfirm={cancelOrder} size={"small"} /> : <></>
  )
}
//下发执行
const PublicButton = ({ setDrawerVal, setSelect }) => {
  const record = useRecordContext();
  const refresh = useRefresh();
  const taskEvent = () => {
    setDrawerVal(true)
    setSelect(record)
    refresh();
  }
  return (
    record.workQty < record.anfme ? <Button label={"toolbar.publicWorking"} startIcon={<AddTaskIcon />} onClick={taskEvent} size={"small"} /> : <></>
  )
}
rsf-admin/src/page/orders/check/CheckOrderModal.jsx
File was renamed from rsf-admin/src/page/orders/check/OutOrderModal.jsx
@@ -91,7 +91,7 @@
    />,
]
const OutOrderModal = (props) => {
const CheckOrderModal = (props) => {
    const { open, setOpen, preview, setPreview, record } = props;
    const translate = useTranslate();
    const [params, setParams] = useState({});
@@ -257,7 +257,7 @@
    )
}
export default OutOrderModal;
export default CheckOrderModal;
const AddOutStockButton = (props) => {
    const { setOpen, setPreview, setSelect } = props;
rsf-admin/src/page/orders/check/MatnrInfoModal.jsx
New file
@@ -0,0 +1,247 @@
import React, { useState, useEffect } from "react";
import {
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    Stack,
    Grid,
    TextField,
    Box,
    Button,
    Paper,
    styled
} from '@mui/material';
import DialogCloseButton from "../../components/DialogCloseButton";
import { useTranslate, useNotify, useRefresh } from 'react-admin';
import request from '@/utils/request';
import { DataGrid } from '@mui/x-data-grid';
import SaveIcon from '@mui/icons-material/Save';
import TreeSelectInput from "@/page/components/TreeSelectInput";
const MatnrInfoModal = (props) => {
    const { open, setOpen, data, setData } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const refresh = useRefresh();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const [formData, setFormData] = useState({});
    const [tableData, setTableData] = useState([]);
    const [dyFields, setDyFields] = useState([]);
    const [selectedRows, setSelectedRows] = useState([]);
    const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData(() => ({
            [name]: value
        }));
    };
    const reset = () => {
        setFormData({
            name: '',
            code: '',
            groupId: 0
        })
    }
    const handleSubmit = () => {
        const hasarr = data.map(el => +el.matnrId)
        const selectedData = selectedRows.filter(item => !hasarr.includes(item)).map(id => (tableData.find(row => row.id === id)));
        const value = selectedData.map((el => {
            const dynamicFields = dyFields.reduce((acc, item) => {
                acc[item.fields] = el['extendFields']?.[item.fields] || '';
                return acc;
            }, {});
            return {
                matnrId: el.id,
                maktx: el.name,
                matnrCode: el.code,
                stockUnit: el.stockUnit || '',
                purUnit: el.purchaseUnit || '',
                ...dynamicFields
            }
        }))
        setData([...data, ...value]);
        setOpen(false);
        reset();
    };
    const getData = async () => {
        const res = await request.post(`/matnr/page`, {
            ...formData,
            current: 1,
            pageSize: 100,
            orderBy: "create_time desc"
        });
        if (res?.data?.code === 200) {
            setTableData(res.data.data.records);
        } else {
            notify(res.data.msg);
        }
    };
    useEffect(() => {
        getData();
    }, [open]);
    const handleSearch = () => {
        getData()
    };
    return (
        <Dialog
            open={open}
            onClose={handleClose}
            aria-labelledby="form-dialog-title"
            fullWidth
            disableRestoreFocus
            maxWidth="lg"
        >
            <DialogTitle id="form-dialog-title" sx={{
                position: 'sticky',
                top: 0,
                backgroundColor: 'background.paper',
                zIndex: 1000
            }}>
                {translate("common.action.newAddMats")}
                <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                    <DialogCloseButton onClose={handleClose} />
                </Box>
            </DialogTitle>
            <DialogContent sx={{ mt: 2 }}>
                <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
                    <Grid container spacing={2}>
                        <Grid item md={4}>
                            <TextField
                                label={translate('table.field.matnr.name')}
                                name="name"
                                value={formData.name}
                                onChange={handleChange}
                                size="small"
                            />
                        </Grid>
                        <Grid item md={4}>
                            <TextField
                                label={translate('table.field.matnr.code')}
                                name="code"
                                value={formData.code}
                                onChange={handleChange}
                                size="small"
                            />
                        </Grid>
                        <Grid item md={4}>
                            <TreeSelectInput
                                label="table.field.matnr.groupId"
                                value={formData.groupId}
                                resource={'matnrGroup'}
                                source="groupId"
                                name="groupId"
                                onChange={handleChange}
                            />
                        </Grid>
                    </Grid>
                </Box>
                <Box sx={{ mt: 2 }}>
                    <Stack direction="row" spacing={2}>
                        <Button variant="contained" onClick={handleSearch}>搜索</Button>
                    </Stack>
                </Box>
                <Box sx={{ mt: 2, height: 400, width: '100%' }}>
                    <AsnWareModalTable
                        tableData={tableData}
                        setTableData={setTableData}
                        dyFields={dyFields}
                        setDyFields={setDyFields}
                        selectedRows={selectedRows}
                        setSelectedRows={setSelectedRows}
                    />
                </Box>
            </DialogContent>
            <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
                    <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}>
                        {translate('toolbar.confirm')}
                    </Button>
                </Box>
            </DialogActions>
        </Dialog>
    );
};
export default MatnrInfoModal;
const AsnWareModalTable = ({ tableData, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
    const translate = useTranslate();
    const notify = useNotify();
    const [columns, setColumns] = useState([
        // { field: 'id', headerName: 'ID', width: 100 },
        { field: 'name', headerName: translate('table.field.matnr.name'), width: 300 },
        { field: 'code', headerName: translate('table.field.matnr.code'), width: 200 },
        { field: 'groupId$', headerName: translate('table.field.matnr.groupId'), width: 100 },
        { field: 'spec', headerName: translate('table.field.matnr.spec'), width: 100 },
        { field: 'model', headerName: translate('table.field.matnr.model'), width: 100 },
        { field: 'weight', headerName: translate('table.field.matnr.weight'), width: 100 },
        { field: 'describle', headerName: translate('table.field.matnr.describle'), width: 100 },
        { field: 'nromNum', headerName: translate('table.field.matnr.nromNum'), width: 100 },
        { field: 'unit', headerName: translate('table.field.matnr.unit'), width: 100 },
        { field: 'purchaseUnit', headerName: translate('table.field.matnr.purUnit'), width: 100 },
        { field: 'stockUnit', headerName: translate('table.field.matnr.stockUnit'), width: 100 },
        { field: 'stockLeval$', headerName: translate('table.field.matnr.stockLevel'), width: 100, sortable: false },
    ])
    const handleSelectionChange = (ids) => {
        setSelectedRows(ids)
    };
    useEffect(() => {
        getDynamicFields();
    }, []);
    const getDynamicFields = async () => {
        const {
            data: { code, data, msg },
        } = await request.get("/fields/enable/list");
        if (code === 200) {
            const cols = data.map(el => ({
                field: el.fields,
                headerName: el.fieldsAlise,
                minWidth: 100,
                flex: 1,
                editable: el.unique,
                valueGetter: (value, row) => {
                    return row.extendFields?.[el.fields] || '';
                },
            }))
            setDyFields(data)
            setColumns([...columns, ...cols])
        } else {
            notify(msg);
        }
    }
    return (
        <div style={{ height: 400, width: '100%' }}>
            <DataGrid
                size="small"
                rows={tableData}
                columns={columns}
                checkboxSelection
                onRowSelectionModelChange={handleSelectionChange}
                selectionModel={selectedRows}
                disableColumnMenu={true}
                disableColumnSorting
                disableMultipleColumnsSorting
            />
        </div>
    );
};
rsf-admin/src/page/orders/check/SelectMatnrModal.jsx
@@ -44,18 +44,14 @@
    MenuItem
} from '@mui/material';
import DialogCloseButton from "../../components/DialogCloseButton";
import StatusSelectInput from "../../components/StatusSelectInput";
import ConfirmButton from "../../components/ConfirmButton";
import MatnrInfoModal from "./MatnrInfoModal";
import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
import { Add, Edit, Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
import DictionarySelect from "../../components/DictionarySelect";
import DictSelect from "../../components/DictSelect";
import "./asnOrder.css";
const SelectMatnrModal = (props) => {
    const { open, setOpen, asnId, billReload } = props;
@@ -159,7 +155,7 @@
    const handleDelete = async () => {
        const res = await request.post(`/outStock/remove/${asnId}`);
        const res = await request.post(`/check/remove/${asnId}`);
        if (res?.data?.code === 200) {
            setOpen(false);
            refresh();
@@ -169,7 +165,7 @@
    };
    const requestGetHead = async () => {
        const res = await request.get(`/outStock/${asnId}`);
        const res = await request.get(`/check/${asnId}`);
        if (res?.data?.code === 200) {
            setFormData(res.data.data)
        } else {
@@ -178,7 +174,7 @@
    }
    const requestGetBody = async () => {
        const res = await request.post(`/outStockItem/page`, { asnId });
        const res = await request.post(`/checkItem/page`, { asnId });
        if (res?.data?.code === 200) {
            setTableData(res.data.data.records)
        } else {
@@ -219,42 +215,14 @@
                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
                        <Form defaultValues={formData}>
                            <Grid container spacing={2}>
                                {/* <Grid item md={2}>
                                    <DictSelect
                                        label={translate("table.field.asnOrder.type")}
                                        value={formData.type}
                                        onChange={(e) => handleChange(e.target.value, 'type')}
                                        dictTypeCode="sys_order_type"
                                        required
                                    />
                                </Grid> */}
                                <Grid item md={2}>
                                    <DictSelect
                                        label={translate("table.field.outStock.wkType")}
                                        label={translate("table.field.checkOrder.checkType")}
                                        value={formData.wkType}
                                        variant="filled"
                                        group='2'
                                        onChange={(e) => handleChange(e.target.value, 'wkType')}
                                        dictTypeCode="sys_business_type"
                                        dictTypeCode="sys_check_order_type"
                                        required
                                    />
                                </Grid>
                                <Grid item md={2}>
                                    <TextField
                                        label={translate("table.field.outStock.poCode")}
                                        value={formData.poCode}
                                        variant="filled"
                                        size='small'
                                        onChange={(e) => handleChange(e.target.value, 'poCode')}
                                    />
                                </Grid>
                                <Grid item md={2}>
                                    <TextField
                                        label={translate("table.field.outStock.logisNo")}
                                        value={formData.logisNo}
                                        variant="filled"
                                        size='small'
                                        onChange={(e) => handleChange(e.target.value, 'logisNo')}
                                    />
                                </Grid>
                                <Grid item md={2}>
@@ -270,11 +238,9 @@
                            </Grid>
                        </Form>
                    </Box>
                    <Box sx={{ mt: 2 }}>
                        <Stack direction="row" spacing={2}>
                            <Button variant="contained" onClick={() => setCreateDialog(true)}>新增物料</Button>
                            {/* {asnId !== '' && <ConfirmButton label={'删除'} variant="outlined" color="error" onConfirm={handleDelete} />} */}
                            <ConfirmButton label={'删除'} variant="outlined" color="error" onConfirm={handleDeleteItem} />
                        </Stack>
                    </Box>
@@ -516,6 +482,7 @@
        if (code === 200) {
            const cols = data.map(el => ({
                field: el.fields,
                key: el.id,
                headerName: el.fieldsAlise,
                minWidth: 100,
                flex: 1,
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CheckOrderController.java
@@ -10,6 +10,7 @@
import com.vincent.rsf.server.common.domain.KeyValVo;
import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.manager.controller.params.AsnOrderAndItemsParams;
import com.vincent.rsf.server.manager.entity.AsnOrder;
import com.vincent.rsf.server.manager.enums.OrderType;
import com.vincent.rsf.server.manager.service.CheckOrderService;
@@ -124,6 +125,16 @@
        ExcelUtil.build(ExcelUtil.create(orders, AsnOrder.class), response);
    }
    @PostMapping("/check/items/save")
    @ApiOperation("保存主单及明细")
    @PreAuthorize("hasAuthority('manager:check:save')")
    public R saveOutStock(@RequestBody AsnOrderAndItemsParams params) throws Exception {
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return checkOrderService.saveCheckOrder(params, getLoginUserId());
    }
    /**
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/CheckExceStatus.java
New file
@@ -0,0 +1,20 @@
package com.vincent.rsf.server.manager.enums;
public enum CheckExceStatus {
    CHECK_ORDER_STATUS_UN_EXCE("1", "未执行"),
    CHECK_ORDER_STATUS_INIT("2", "初始化"),
    CHECK_ORDER_STATUS_EXCE_ING("3", "执行中"),
    CHECK_ORDER_STATUS_EXCE_DONE("4", "执行完成"),
    ;
    CheckExceStatus(String val, String desc) {
        this.val = Short.parseShort(val);
        this.desc = desc;
    }
    public Short val;
    public String desc;
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/CheckOrderType.java
@@ -7,13 +7,25 @@
 * @version 1.0
 */
public enum CheckOrderType {
    //盘点信息,1.临时盘点, 2.抽样盘点, 3. 区域盘点,4. 差异盘点 5. 循环盘点 6. 定期盘点
    CHECK_ORDER_TYPE_TEMP("1", "临时盘点"),
    CHECK_ORDER_TYPE_ROUND("2", "抽样盘点"),
    CHECK_ORDER_TYPE_AREAS("3", "区域盘点"),
    CHECK_ORDER_TYPE_DIFF("4", "差异盘点"),
    CHECK_ORDER_TYPE_CIRCLE("5", "循环盘点"),
    CHECK_ORDER_TYPE_TIMER("6", "定期盘点"),
    ;
    CheckOrderType(String type, String desc) {
        this.type = Integer.parseInt(type);
        this.desc = desc;
    }
    public Integer type;
    public String desc;
    public static String getOrderType() {
        return null;
    }
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/CheckOrderService.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.manager.controller.params.AsnOrderAndItemsParams;
import com.vincent.rsf.server.manager.entity.AsnOrder;
import org.springframework.web.multipart.MultipartFile;
@@ -10,4 +11,6 @@
public interface CheckOrderService extends IService<AsnOrder> {
    R excelImport(MultipartFile file, HashMap<String, Object> hashMap, Long loginUserId);
    R saveCheckOrder(AsnOrderAndItemsParams params, Long loginUserId);
}
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java
@@ -8,17 +8,22 @@
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.manager.controller.params.AsnOrderAndItemsParams;
import com.vincent.rsf.server.manager.entity.AsnOrder;
import com.vincent.rsf.server.manager.entity.AsnOrderItem;
import com.vincent.rsf.server.manager.entity.Matnr;
import com.vincent.rsf.server.manager.entity.excel.CheckOrderTemplate;
import com.vincent.rsf.server.manager.enums.AsnExceStatus;
import com.vincent.rsf.server.manager.enums.CheckExceStatus;
import com.vincent.rsf.server.manager.enums.OrderType;
import com.vincent.rsf.server.manager.enums.OrderWorkType;
import com.vincent.rsf.server.manager.mapper.CheckOrderMapper;
import com.vincent.rsf.server.manager.service.AsnOrderItemService;
import com.vincent.rsf.server.manager.service.CheckOrderItemService;
import com.vincent.rsf.server.manager.service.CheckOrderService;
import com.vincent.rsf.server.manager.service.MatnrService;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -33,9 +38,10 @@
    @Autowired
    private MatnrService matnrService;
    @Autowired
    private CheckOrderItemService checkOrderItemService;
    @Autowired
    private AsnOrderItemService asnOrderItemService;
    /**
     * @author Ryan
@@ -109,4 +115,77 @@
        return R.ok("操作成功!!");
    }
    /**
     * @param
     * @return
     * @author Ryan
     * @description 保存出库主单及明细
     * @time 2025/4/29 13:47
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveCheckOrder(AsnOrderAndItemsParams params, Long loginUserId) {
        if (Objects.isNull(params.getOrders())) {
            throw new CoolException("主单信息不能为空");
        }
        AsnOrder orders = params.getOrders();
        if (StringUtils.isBlank(orders.getWkType())) {
            throw new CoolException("业务类型不能为空!!");
        }
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_CHECK_RULE_CODE, orders);
        if (StringUtils.isBlank(ruleCode)) {
            throw new CoolException("编码规则错误:请检查「SYS_CHECK_RULE_CODE」是否设置正确!!");
        }
        orders.setCode(ruleCode)
                .setType(OrderType.ORDER_CHECK.type)
                .setExceStatus(CheckExceStatus.CHECK_ORDER_STATUS_UN_EXCE.val)
                .setUpdateBy(loginUserId)
                .setCreateBy(loginUserId);
        if (!this.save(orders)) {
            throw new CoolException("主单保存失败!!");
        }
        if (params.getItems().isEmpty()) {
            throw new CoolException("盘点单明细不能为空!!");
        }
        params.setOrders(orders);
        try {
            svaeOrUpdateOrderItem(params, loginUserId);
        } catch (Exception e) {
            throw new CoolException(e.getMessage());
        }
        return R.ok();
    }
    /**
     * @param
     * @return
     * @author Ryan
     * @description 更新或保存明细
     * @time 2025/4/7 13:28
     */
    @Transactional(rollbackFor = Exception.class)
    public void svaeOrUpdateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) throws Exception {
        AsnOrder orders = params.getOrders();
        params.getItems().forEach(item -> {
            item.put("asnId", orders.getId());
            item.put("asnCode", orders.getCode());
            item.put("poCode", orders.getPoCode());
            item.put("createBy", loginUserId);
            item.put("updateBy", loginUserId);
            if (!asnOrderItemService.fieldsSave(item, loginUserId)) {
                throw new CoolException("明细保存失败!!");
            }
        });
        List<AsnOrderItem> orderItems = checkOrderItemService.list(new LambdaQueryWrapper<AsnOrderItem>()
                .eq(AsnOrderItem::getAsnId, params.getOrders().getId()));
        Double sum = orderItems.stream().mapToDouble(AsnOrderItem::getAnfme).sum();
        orders.setAnfme(sum);
        if (!this.updateById(orders)) {
            throw new CoolException("计划收货数量修改失败!!");
        }
    }
}
rsf-server/src/main/resources/application-dev.yml
@@ -15,7 +15,7 @@
#    url: jdbc:mysql://47.76.147.249:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
#    username: rsf
    username: root
    url: jdbc:mysql://192.168.4.151:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    url: jdbc:mysql://127.0.0.1:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    password: 34821015
    type: com.alibaba.druid.pool.DruidDataSource
    druid: