From 40d9cd510741a098bd52cbe22a5f9e5528f45abc Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期三, 23 四月 2025 17:09:01 +0800 Subject: [PATCH] # 新增 1. 通过单据新增出库单功能 2. 新增生成出库单接口 --- rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java | 104 ++++++++++++++--- rsf-admin/src/page/orders/outStock/OutOrderModal.jsx | 146 +++++++++++++---------- rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java | 8 + rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java | 2 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java | 14 ++ rsf-admin/src/i18n/zh.js | 2 rsf-admin/src/i18n/en.js | 2 rsf-server/src/main/java/com/vincent/rsf/server/common/domain/PageParam.java | 28 ++-- 8 files changed, 209 insertions(+), 97 deletions(-) diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js index eb60a5f..0f29dff 100644 --- a/rsf-admin/src/i18n/en.js +++ b/rsf-admin/src/i18n/en.js @@ -51,6 +51,7 @@ before: 'Time Before' }, action: { + search: 'Search', reset: 'Reset', expand: 'Expand', expandAll: 'Expand All', @@ -919,6 +920,7 @@ batch: 'batch', confirm: 'confirm', cancel: "cancel", + query: "Query", bulkExport: "Bulk Export", continue: 'Continue Receipt', confirmSelect: 'Confirm Select', diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js index b0c673a..44b724e 100644 --- a/rsf-admin/src/i18n/zh.js +++ b/rsf-admin/src/i18n/zh.js @@ -51,6 +51,7 @@ before: '缁撴潫鏃堕棿' }, action: { + search: '鎼滅储', reset: '閲嶇疆', expand: '灞曞紑', expandAll: '鍏ㄩ儴灞曞紑', @@ -970,6 +971,7 @@ selectSite: '閫夋嫨绔欑偣', confirmSelect: '纭閫夋嫨', cancel: "鍙栨秷", + query: "鏌ヨ", top: "缃《", resort: "鎺掑簭", subzone: '缁戝畾鍒嗗尯', diff --git a/rsf-admin/src/page/orders/outStock/OutOrderModal.jsx b/rsf-admin/src/page/orders/outStock/OutOrderModal.jsx index ac8a896..95b48a6 100644 --- a/rsf-admin/src/page/orders/outStock/OutOrderModal.jsx +++ b/rsf-admin/src/page/orders/outStock/OutOrderModal.jsx @@ -36,13 +36,16 @@ Form, SaveButton, useRefresh, + useGetList, } from 'react-admin'; import DialogCloseButton from "../../components/DialogCloseButton"; import { styled } from '@mui/material/styles'; import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; -import { Grid, Stack } from "@mui/system"; +import { Grid, Stack, width } from "@mui/system"; +import request from '@/utils/request'; import SaveIcon from '@mui/icons-material/Save'; - +import debounce from "lodash/debounce"; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ '& .css-1vooibu-MuiSvgIcon-root': { @@ -95,6 +98,62 @@ setOpen(false); } }; + const CustomFilter = () => { + const { filterValues, setFilters, refetch } = useListContext('deliveryItem'); + const [formValues, setFormValues] = useState(filterValues); + const handleChange = (event) => { + setFormValues(formValues => ({ + ...formValues, + [event.target.name]: event.target.value + })); + }; + + const handleSubmit = (event) => { + setParams(formValues) + }; + + return ( + <Form> + <Grid container rowSpacing={2} columnSpacing={2} > + <Stack> + <TextInput + source="condition" + label="common.action.search" + resettable + defaultValue={params?.condition} + onChange={handleChange} /> + </Stack> + <Stack> + <TextInput + source="matnrName" + label="table.field.deliveryItem.matnrName" + defaultValue={params?.matnrName} + onChange={handleChange} + /> + </Stack> + <Stack> + <TextInput + source="matnrCode" + label="table.field.deliveryItem.matnrCode" + defaultValue={params?.matnrCode} + onChange={handleChange} /> + </Stack> + <Stack> + <TextInput + source="splrName" + label="table.field.deliveryItem.splrName" + defaultValue={params?.splrName} + onChange={handleChange} /> + </Stack> + </Grid> + <DialogActions> + <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > + <SaveButton onClick={handleSubmit} label={"toolbar.query"} /> + </Toolbar> + </DialogActions> + </Form> + ); + }; return ( <Dialog open={open} @@ -129,9 +188,8 @@ }), marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, }} - storeKey='selectDelivery' - queryOptions={params} filters={<CustomFilter />} + queryOptions={{ meta: { ...params } }} empty={false} sort={{ field: "create_time", order: "desc" }} actions={( @@ -143,7 +201,7 @@ > <StyledDatagrid preferenceKey='deliveryItem' - bulkActionButtons={() => <></>} + bulkActionButtons={<AddOutStockButton setOpen={setOpen}/>} rowClick={(id, resource, record) => false} expand={false} expandSingle={true} @@ -173,63 +231,25 @@ export default OutOrderModal; -const CustomFilter = () => { - const { filterValues, setFilters } = useListContext('deliveryItem'); - const [formValues, setFormValues] = useState(filterValues); - - const handleChange = (event) => { - setFormValues(formValues => ({ - ...formValues, - [event.target.name]: event.target.value - })); - }; - - const handleSubmit = (event) => { - console.log('---------->'); - console.log(formValues); - event.preventDefault(); - setFilters(formValues, null, true); - }; +const AddOutStockButton = (props) => { + const { setOpen } = props; + const { selectedIds, onUnselectItems } = useListContext(); + const notify = useNotify(); + const confirm = async (event) => { + console.log(selectedIds); + const res = await request.post(`/outStock/generate/orders`, {ids: selectedIds}); + if (res?.data?.code === 200) { + notify(res.data.msg); + } else { + notify(res.data.msg); + } + onUnselectItems(); + setOpen(false); + } return ( - <Form> - <Grid container rowSpacing={2} columnSpacing={2} > - <Stack> - <TextInput - source="matnrName" - label="table.field.deliveryItem.matnrName" - resettable - onChange={handleChange} - /> - </Stack> - <Stack> - <TextInput - source="matnrCode" - label="table.field.deliveryItem.matnrCode" - resettable - onChange={handleChange} /> - </Stack> - <Stack> - <TextInput - source="splrName" - label="table.field.deliveryItem.splrName" - resettable - onChange={handleChange} /> - </Stack> - <Stack> - <TextInput - source="splrName" - label="table.field.deliveryItem.splrName" - resettable - onChange={handleChange} /> - </Stack> - </Grid> - <DialogActions> - <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > - <SaveButton onClick={handleSubmit}/> - {/* <Button variant="contained" label="toolbar.confirm" startIcon={<SaveIcon />} onClick={handleSubmit} /> */} - </Toolbar> - </DialogActions> - </Form> - ); -}; + <Button label={"toolbar.confirmSelect"} onClick={confirm}> + <CheckCircleIcon /> + </Button> + ) +} \ No newline at end of file diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/PageParam.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/PageParam.java index 7cb5cfb..e116812 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/PageParam.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/PageParam.java @@ -71,7 +71,7 @@ } public QueryWrapper<T> buildWrapper(boolean like, List<String> fields) { - return this.buildWrapper(like, null,"create_time", fields); + return this.buildWrapper(like, null, "create_time", fields); } @SuppressWarnings("all") @@ -133,26 +133,26 @@ if (!Cools.isEmpty(where.getCondition()) && !Cools.isEmpty(cls)) { List<String> columns = new ArrayList<>(); - for (Field field : Cools.getAllFields(cls)){ + for (Field field : Cools.getAllFields(cls)) { if (Modifier.isFinal(field.getModifiers()) || Modifier.isStatic(field.getModifiers()) - || Modifier.isTransient(field.getModifiers())){ + || Modifier.isTransient(field.getModifiers())) { continue; } - if (field.isAnnotationPresent(TableField.class)){ + if (field.isAnnotationPresent(TableField.class)) { TableField annotation = field.getAnnotation(TableField.class); if (!annotation.exist()) { continue; } } - String column = Utils.toSymbolCase(field.getName(), '_'); + String column = Utils.toSymbolCase(field.getName(), '_'); columns.add(column); } if (!columns.isEmpty()) { queryWrapper.and(wrapper -> { - for (int i=0;i<columns.size();i++){ + for (int i = 0; i < columns.size(); i++) { String column = columns.get(i); String condition = where.getCondition(); if (i == 0) { @@ -168,7 +168,7 @@ } @SuppressWarnings("all") - public QueryWrapper<T> buildWrapper(boolean like, Consumer<QueryWrapper<T>> consumer,String timeField, List<String> fields) { + public QueryWrapper<T> buildWrapper(boolean like, Consumer<QueryWrapper<T>> consumer, String timeField, List<String> fields) { QueryWrapper<T> queryWrapper = new QueryWrapper<>(); Map<String, Object> map = where.getMap(); for (String key : map.keySet()) { @@ -192,9 +192,9 @@ key = Utils.toSymbolCase(key, '_'); } if (like && !fields.contains(key)) { - queryWrapper.like("`" + key + "`", val); + queryWrapper.like("`" + key + "`", val); } else { - queryWrapper.eq("`" + key + "`", val); + queryWrapper.eq("`" + key + "`", val); } } } @@ -223,21 +223,21 @@ if (!Cools.isEmpty(where.getCondition()) && !Cools.isEmpty(cls)) { List<String> columns = new ArrayList<>(); - for (Field field : Cools.getAllFields(cls)){ + for (Field field : Cools.getAllFields(cls)) { if (Modifier.isFinal(field.getModifiers()) || Modifier.isStatic(field.getModifiers()) - || Modifier.isTransient(field.getModifiers())){ + || Modifier.isTransient(field.getModifiers())) { continue; } - if (field.isAnnotationPresent(TableField.class)){ + if (field.isAnnotationPresent(TableField.class)) { TableField annotation = field.getAnnotation(TableField.class); if (!annotation.exist()) { continue; } } - String column = Utils.toSymbolCase(field.getName(), '_'); + String column = Utils.toSymbolCase(field.getName(), '_'); columns.add(column); } // if (!columns.isEmpty()) { @@ -254,7 +254,7 @@ // } if (!columns.isEmpty()) { queryWrapper.and(wrapper -> { - for (int i=0;i<columns.size();i++){ + for (int i = 0; i < columns.size(); i++) { String column = columns.get(i); String condition = where.getCondition(); if (i == 0) { diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java index b442995..3149703 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/OutStockController.java @@ -190,4 +190,18 @@ } ExcelUtil.build(ExcelUtil.create(orderTemplates, AsnOrderTemplate.class), response); } + + + @PreAuthorize("hasAuthority('manager:outStock:update')") + @ApiOperation("閫氳繃DO鍗曠敓鎴愬嚭搴撳崟") + @PostMapping("/outStock/generate/orders") + public R genOutStock(@RequestBody Map<String, Object> params) { + if (Objects.isNull(params.get("ids"))) { + return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒"); + } + List<Long> ids = (List<Long>) params.get("ids"); + return outStockService.genOutStock(ids); + } + + } diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java index ec3e03f..90450e4 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/OutStockService.java @@ -12,4 +12,6 @@ public interface OutStockService extends IService<AsnOrder> { R cancelOutOrder(String id); + + R genOutStock(List<Long> ids); } diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java index 421985e..3b19c58 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java @@ -11,10 +11,7 @@ import com.vincent.rsf.server.api.service.ReportMsgService; import com.vincent.rsf.server.manager.controller.params.AsnOrderAndItemsParams; import com.vincent.rsf.server.manager.controller.params.BatchUpdateParam; -import com.vincent.rsf.server.manager.entity.AsnOrder; -import com.vincent.rsf.server.manager.entity.AsnOrderItem; -import com.vincent.rsf.server.manager.entity.AsnOrderItemLog; -import com.vincent.rsf.server.manager.entity.AsnOrderLog; +import com.vincent.rsf.server.manager.entity.*; import com.vincent.rsf.server.manager.enums.AsnExceStatus; import com.vincent.rsf.server.manager.mapper.AsnOrderMapper; import com.vincent.rsf.server.manager.mapper.PurchaseMapper; @@ -22,6 +19,7 @@ import com.vincent.rsf.server.system.constant.SerialRuleCode; import com.vincent.rsf.server.system.mapper.SerialRuleMapper; import com.vincent.rsf.server.system.utils.SerialRuleUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -42,29 +40,31 @@ public class OutStockServiceImpl extends ServiceImpl<AsnOrderMapper, AsnOrder> implements OutStockService { @Autowired - private ReceiveMsgService receiveMsgService; - @Autowired - private ReportMsgService reportMsgService; - @Resource - private PurchaseMapper purchaseMapper; - @Autowired private AsnOrderItemService asnOrderItemService; @Autowired private AsnOrderLogService asnOrderLogService; @Autowired private AsnOrderItemLogService asnOrderItemLogService; - @Resource - private SerialRuleMapper serialRuleMapper; + + @Autowired + private DeliveryItemService deliveryItemService; + + @Autowired + private DeliveryService deliveryService; + @Autowired + private MatnrService matnrService; + + /** - * @author Ryan - * @description 鏇存柊鎴栦繚瀛樻槑缁� * @param * @return + * @author Ryan + * @description 鏇存柊鎴栦繚瀛樻槑缁� * @time 2025/4/7 13:28 */ @Transactional(rollbackFor = Exception.class) - private void svaeOrUpdateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) throws Exception{ + private void svaeOrUpdateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) throws Exception { AsnOrder orders = params.getOrders(); params.getItems().forEach(item -> { @@ -88,14 +88,14 @@ /** - * @author Ryan - * @description 鍒犻櫎鍘熶富鍗曞強鏄庣粏锛屽姞鍏ュ巻鍙叉。 * @param * @return + * @author Ryan + * @description 鍒犻櫎鍘熶富鍗曞強鏄庣粏锛屽姞鍏ュ巻鍙叉。 * @time 2025/3/19 19:53 */ @Transactional(rollbackFor = Exception.class) - private void operateOrderLogs(AsnOrder asrder) throws Exception{ + private void operateOrderLogs(AsnOrder asrder) throws Exception { if (Objects.isNull(asrder) || Objects.isNull(asrder.getId())) { throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒"); } @@ -148,10 +148,10 @@ } /** - * @author Ryan - * @description 鍙栨秷鍑哄簱鍗曟嵁 * @param * @return + * @author Ryan + * @description 鍙栨秷鍑哄簱鍗曟嵁 * @time 2025/4/22 10:40 */ @Override @@ -174,4 +174,68 @@ } return R.ok("鎿嶄綔鎴愬姛"); } + + /** + * @param + * @return + * @author Ryan + * @description 閫氳繃DO鍗曠敓鎴愬嚭搴撳崟 + * @time 2025/4/23 16:24 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public R genOutStock(List<Long> ids) { + if (Objects.isNull(ids) || ids.isEmpty()) { + throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒"); + } + List<DeliveryItem> items = deliveryItemService.list(new LambdaQueryWrapper<DeliveryItem>().in(DeliveryItem::getId, ids)); + if (items.isEmpty()) { + throw new CoolException("鍗曟嵁涓嶅瓨鍦紒锛�"); + } + Map<Long, List<DeliveryItem>> listMap = items.stream().collect(Collectors.groupingBy(DeliveryItem::getDeliveryId)); + listMap.keySet().forEach(key -> { + //TODO 鍒ゆ柇鍗曟嵁鏄惁宸茬粡瀛樺湪锛屽瀛樺湪鍒欑疮鍔犱慨鏀瑰瓙琛紝涓嶅瓨鍦ㄦ墠鏂板缓 + Delivery delivery = deliveryService.getById(key); + if (Objects.isNull(delivery)) { + throw new CoolException("鍗曟嵁涓嶅瓨鍦紒锛�"); + } + AsnOrder order = new AsnOrder(); + BeanUtils.copyProperties(delivery, order); + String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_OUT_STOCK_CODE, order); + if (Objects.isNull(ruleCode) || StringUtils.isBlank(ruleCode)) { + throw new CoolException("缂栫爜瑙勫垯閿欒锛氳妫�鏌� 銆孲YS_OUT_STOCK_CODE銆嶇紪鐮佹槸鍚﹁缃垚鍔�"); + } + order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val) + .setCode(ruleCode) + .setPoId(delivery.getId()) + .setId(null) + .setPoCode(delivery.getCode()); + if (!this.save(order)) { + throw new CoolException("涓诲崟淇濆瓨澶辫触锛侊紒"); + } + List<AsnOrderItem> orderItems = new ArrayList<>(); + listMap.get(key).forEach(item -> { + AsnOrderItem orderItem = new AsnOrderItem(); + BeanUtils.copyProperties(item, orderItem); + orderItem.setId(null) + .setPoCode(order.getPoCode()) + .setAsnId(order.getId()) + .setAsnCode(order.getCode()) + .setPlatItemId(item.getPlatItemId()) + .setPoDetlId(item.getId()); + orderItems.add(orderItem); + }); + + double sum = orderItems.stream().mapToDouble(AsnOrderItem::getAnfme).sum(); + //淇敼璁″垝鏁伴噺 + order.setAnfme(sum); + if (!this.saveOrUpdate(order)) { + throw new CoolException("涓诲崟鏁伴噺淇敼澶辫触锛侊紒"); + } + if (!asnOrderItemService.saveBatch(orderItems)) { + throw new CoolException("鏄庣粏淇濆瓨澶辫触锛侊紒"); + } + }); + return R.ok(); + } } diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java index bada2f7..ed14ec0 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Map; +import java.util.Objects; /** * Created by vincent on 1/30/2024 @@ -42,6 +43,13 @@ } public <T extends BaseParam> T buildParam(Map<String, Object> map, Class<T> clz) { + if (!Objects.isNull(map.get("meta"))) { + Map<String, Object> meta = (Map<String, Object>) map.get("meta"); + meta.keySet().forEach(key -> { + map.put(key, meta.get(key)); + }); + map.remove("meta"); + } T t = null; try { t = clz.getDeclaredConstructor().newInstance(); -- Gitblit v1.9.1