diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientQuoteController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientQuoteController.java index d8d8f3fa..3d074678 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientQuoteController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientQuoteController.java @@ -8,6 +8,7 @@ import com.ruoyi.system.service.bid.IBizClientQuoteService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; @RestController @RequestMapping("/bid/clientquote") @@ -41,4 +42,30 @@ public class BizClientQuoteController extends BaseController { public AjaxResult remove(@PathVariable Long quoteId) { return toAjax(service.deleteClientQuoteById(quoteId)); } + + // ========== 甲方报价历史 - 统计 ========== + + @GetMapping("/statistics") + public AjaxResult statistics(BizClientQuote query) { + return success(service.selectClientQuoteStatistics(query)); + } + + @GetMapping("/monthly-trend") + public AjaxResult monthlyTrend() { + return success(service.selectMonthlyTrend()); + } + + // ========== 按物料ID查询报价历史 ========== + + @GetMapping("/by-material/{materialId}") + public AjaxResult byMaterial(@PathVariable Long materialId) { + return success(service.selectClientQuotesByMaterialId(materialId)); + } + + // ========== 基于历史报价快速新建 ========== + + @PostMapping("/quick-create/{quoteId}") + public AjaxResult quickCreate(@PathVariable Long quoteId) { + return success(service.copyFromExisting(quoteId)); + } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizQuotationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizQuotationController.java index 07421023..59c0fa33 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizQuotationController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizQuotationController.java @@ -1,6 +1,7 @@ package com.ruoyi.web.controller.bid; import java.util.List; +import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -11,11 +12,13 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.system.domain.bid.BizQuotation; import com.ruoyi.system.service.bid.IBizQuotationService; +import com.ruoyi.system.mapper.bid.BizQuotationItemMapper; @RestController @RequestMapping("/bid/quotation") public class BizQuotationController extends BaseController { @Autowired private IBizQuotationService service; + @Autowired private BizQuotationItemMapper quotationItemMapper; @PreAuthorize("@ss.hasPermi('bid:quotation:list')") @GetMapping("/list") @@ -70,4 +73,15 @@ public class BizQuotationController extends BaseController { public AjaxResult remove(@PathVariable Long[] quotationIds) { return toAjax(service.deleteBizQuotationByIds(quotationIds)); } + + /** + * 按供应商ID查询报价明细(展开为每行一条物料) + * 用于供应商管理页面的"报价历史"Tab + */ + @PreAuthorize("@ss.hasPermi('bid:quotation:list')") + @GetMapping("/supplier-items/{supplierId}") + public AjaxResult supplierItems(@PathVariable Long supplierId) { + List> list = quotationItemMapper.selectItemsBySupplierId(supplierId); + return success(list); + } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClientQuote.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClientQuote.java index e4b075c8..01cda00a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClientQuote.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClientQuote.java @@ -1,10 +1,11 @@ package com.ruoyi.system.domain.bid; +import com.ruoyi.common.core.domain.BaseEntity; import java.math.BigDecimal; import java.util.Date; import java.util.List; -public class BizClientQuote { +public class BizClientQuote extends BaseEntity { private Long quoteId; private Long tenantId; private String quoteNo; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClientQuoteItem.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClientQuoteItem.java index 6c930095..af1773aa 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClientQuoteItem.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizClientQuoteItem.java @@ -5,6 +5,7 @@ import java.math.BigDecimal; public class BizClientQuoteItem { private Long itemId; private Long quoteId; + private Long materialId; private String materialName; private String spec; private String modelNo; @@ -20,6 +21,8 @@ public class BizClientQuoteItem { public void setItemId(Long v){itemId=v;} public Long getQuoteId(){return quoteId;} public void setQuoteId(Long v){quoteId=v;} + public Long getMaterialId(){return materialId;} + public void setMaterialId(Long v){materialId=v;} public String getMaterialName(){return materialName;} public void setMaterialName(String v){materialName=v;} public String getSpec(){return spec;} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientQuoteMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientQuoteMapper.java index 86932167..a1937699 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientQuoteMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientQuoteMapper.java @@ -4,8 +4,10 @@ import com.ruoyi.system.domain.bid.BizClientQuote; import com.ruoyi.system.domain.bid.BizClientQuoteItem; import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Map; public interface BizClientQuoteMapper { + // ========== CRUD ========== List selectClientQuoteList(@Param("q") BizClientQuote query); BizClientQuote selectClientQuoteById(@Param("quoteId") Long quoteId); List selectItemsByQuoteId(@Param("quoteId") Long quoteId); @@ -15,4 +17,14 @@ public interface BizClientQuoteMapper { int deleteClientQuoteById(@Param("quoteId") Long quoteId); int deleteItemsByQuoteId(@Param("quoteId") Long quoteId); String selectNextQuoteNo(); + + // ========== 甲方报价历史 - 统计 ========== + Map selectClientQuoteStatistics(@Param("q") BizClientQuote query); + List> selectMonthlyTrend(); + + // ========== 按物料ID关联查询 ========== + List> selectClientQuotesByMaterialId(@Param("materialId") Long materialId); + + // ========== 快速复制 ========== + List selectItemsByQuoteIdForCopy(@Param("quoteId") Long quoteId); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizQuotationItemMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizQuotationItemMapper.java index 5787d8a9..4a4d8fe2 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizQuotationItemMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizQuotationItemMapper.java @@ -1,10 +1,13 @@ package com.ruoyi.system.mapper.bid; import com.ruoyi.system.domain.bid.BizQuotationItem; +import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Map; public interface BizQuotationItemMapper { List selectItemsByQuotationId(Long quotationId); + List> selectItemsBySupplierId(@Param("supplierId") Long supplierId); int insertBizQuotationItem(BizQuotationItem item); int deleteByQuotationId(Long quotationId); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientQuoteService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientQuoteService.java index 1105dc0e..b57eeaa9 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientQuoteService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientQuoteService.java @@ -2,6 +2,7 @@ package com.ruoyi.system.service.bid; import com.ruoyi.system.domain.bid.BizClientQuote; import java.util.List; +import java.util.Map; public interface IBizClientQuoteService { List selectClientQuoteList(BizClientQuote query); @@ -9,4 +10,14 @@ public interface IBizClientQuoteService { int insertClientQuote(BizClientQuote quote); int updateClientQuote(BizClientQuote quote); int deleteClientQuoteById(Long quoteId); + + // 甲方报价历史 - 统计 + Map selectClientQuoteStatistics(BizClientQuote query); + List> selectMonthlyTrend(); + + // 按物料ID查询报价历史 + List> selectClientQuotesByMaterialId(Long materialId); + + // 基于历史报价快速新建 + BizClientQuote copyFromExisting(Long quoteId); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientQuoteServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientQuoteServiceImpl.java index b670e374..9ca051e3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientQuoteServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientQuoteServiceImpl.java @@ -10,6 +10,7 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; +import java.util.Map; @Service public class BizClientQuoteServiceImpl implements IBizClientQuoteService { @@ -85,4 +86,70 @@ public class BizClientQuoteServiceImpl implements IBizClientQuoteService { mapper.deleteItemsByQuoteId(quoteId); return mapper.deleteClientQuoteById(quoteId); } + + // ========== 甲方报价历史 - 统计 ========== + + @Override + public Map selectClientQuoteStatistics(BizClientQuote query) { + return mapper.selectClientQuoteStatistics(query); + } + + @Override + public List> selectMonthlyTrend() { + return mapper.selectMonthlyTrend(); + } + + // ========== 按物料ID查询 ========== + + @Override + public List> selectClientQuotesByMaterialId(Long materialId) { + return mapper.selectClientQuotesByMaterialId(materialId); + } + + // ========== 基于历史报价快速新建 ========== + + @Override + @Transactional + public BizClientQuote copyFromExisting(Long quoteId) { + BizClientQuote existing = mapper.selectClientQuoteById(quoteId); + if (existing == null) { + throw new RuntimeException("报价单不存在: " + quoteId); + } + // 创建新的报价单(复制主表信息,重置状态和金额) + BizClientQuote newQuote = new BizClientQuote(); + newQuote.setQuoteNo(mapper.selectNextQuoteNo()); + newQuote.setClientName(existing.getClientName()); + newQuote.setRfqId(existing.getRfqId()); + newQuote.setRfqNo(existing.getRfqNo()); + newQuote.setRfqTitle(existing.getRfqTitle()); + newQuote.setStatus("draft"); + newQuote.setValidityDate(existing.getValidityDate()); + newQuote.setCurrency(existing.getCurrency()); + newQuote.setRemark(existing.getRemark()); + newQuote.setTotalAmount(BigDecimal.ZERO); + + int rows = mapper.insertClientQuote(newQuote); + + // 复制明细 + List items = mapper.selectItemsByQuoteId(quoteId); + if (items != null && !items.isEmpty()) { + BigDecimal total = BigDecimal.ZERO; + for (BizClientQuoteItem item : items) { + // 重置为新行 + item.setItemId(null); + item.setQuoteId(newQuote.getQuoteId()); + // 保留原物料信息和价格,方便用户修改 + if (item.getUnitPrice() != null && item.getQuantity() != null) { + BigDecimal line = item.getUnitPrice().multiply(item.getQuantity()).setScale(2, RoundingMode.HALF_UP); + item.setTotalPrice(line); + total = total.add(line); + } + mapper.insertClientQuoteItem(item); + } + newQuote.setTotalAmount(total); + mapper.updateClientQuote(newQuote); + } + newQuote.setItems(items); + return newQuote; + } } diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizClientQuoteMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizClientQuoteMapper.xml index 12a219a8..a8a89249 100644 --- a/ruoyi-system/src/main/resources/mapper/bid/BizClientQuoteMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/bid/BizClientQuoteMapper.xml @@ -3,31 +3,48 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + + + + quote_id AS quoteId, tenant_id AS tenantId, quote_no AS quoteNo, + client_name AS clientName, rfq_id AS rfqId, rfq_no AS rfqNo, rfq_title AS rfqTitle, + status, validity_date AS validityDate, total_amount AS totalAmount, + currency, remark, create_by AS createBy, create_time AS createTime + + + + + + item_id AS itemId, quote_id AS quoteId, material_id AS materialId, + material_name AS materialName, spec, model_no AS modelNo, unit, quantity, + cost_price AS costPrice, unit_price AS unitPrice, total_price AS totalPrice, + delivery_days AS deliveryDays, remark + + @@ -44,9 +61,9 @@ - INSERT INTO biz_client_quote_item (quote_id,material_name,spec,model_no,unit,quantity, + INSERT INTO biz_client_quote_item (quote_id,material_id,material_name,spec,model_no,unit,quantity, cost_price,unit_price,total_price,delivery_days,remark) - VALUES (#{quoteId},#{materialName},#{spec},#{modelNo},#{unit},#{quantity}, + VALUES (#{quoteId},#{materialId},#{materialName},#{spec},#{modelNo},#{unit},#{quantity}, #{costPrice},#{unitPrice},#{totalPrice},#{deliveryDays},#{remark}) @@ -59,4 +76,63 @@ DELETE FROM biz_client_quote WHERE quote_id=#{quoteId} DELETE FROM biz_client_quote_item WHERE quote_id=#{quoteId} + + + + + + + + + + + + + + + + + diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizMaterialMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizMaterialMapper.xml index d04508e1..91501e06 100644 --- a/ruoyi-system/src/main/resources/mapper/bid/BizMaterialMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/bid/BizMaterialMapper.xml @@ -92,14 +92,14 @@ ORDER BY q.submit_time DESC - + diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizQuotationItemMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizQuotationItemMapper.xml index 4d76e511..28d14469 100644 --- a/ruoyi-system/src/main/resources/mapper/bid/BizQuotationItemMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/bid/BizQuotationItemMapper.xml @@ -19,6 +19,23 @@ SELECT * FROM biz_quotation_item WHERE quotation_id=#{quotationId} + + + INSERT INTO biz_quotation_item(quotation_id,rfq_item_id,material_name,spec,unit,quantity,unit_price,total_price,delivery_days,remark) VALUES(#{quotationId},#{rfqItemId},#{materialName},#{spec},#{unit},#{quantity},#{unitPrice},#{totalPrice},#{deliveryDays},#{remark}) diff --git a/ruoyi-ui/src/api/bid/clientquote.js b/ruoyi-ui/src/api/bid/clientquote.js index 9d4106de..ba094b89 100644 --- a/ruoyi-ui/src/api/bid/clientquote.js +++ b/ruoyi-ui/src/api/bid/clientquote.js @@ -1,7 +1,19 @@ import request from '@/utils/request' const baseUrl = '/bid/clientquote' + +// ========== CRUD ========== export const listClientQuote = (params) => request({ url: baseUrl + '/list', method: 'get', params }) export const getClientQuote = (id) => request({ url: baseUrl + '/' + id, method: 'get' }) export const addClientQuote = (data) => request({ url: baseUrl, method: 'post', data }) export const updateClientQuote = (data) => request({ url: baseUrl, method: 'put', data }) export const delClientQuote = (id) => request({ url: baseUrl + '/' + id, method: 'delete' }) + +// ========== 甲方报价历史 ========== +// 统计数据 +export const getClientQuoteStatistics = (params) => request({ url: baseUrl + '/statistics', method: 'get', params }) +// 月度趋势 +export const getMonthlyTrend = () => request({ url: baseUrl + '/monthly-trend', method: 'get' }) +// 按物料ID查询报价历史 +export const getClientQuoteByMaterial = (materialId) => request({ url: baseUrl + '/by-material/' + materialId, method: 'get' }) +// 基于历史报价快速新建 +export const quickCreateFromQuote = (quoteId) => request({ url: baseUrl + '/quick-create/' + quoteId, method: 'post' }) diff --git a/ruoyi-ui/src/api/bid/quotation.js b/ruoyi-ui/src/api/bid/quotation.js index 907dc7d3..90af95ce 100644 --- a/ruoyi-ui/src/api/bid/quotation.js +++ b/ruoyi-ui/src/api/bid/quotation.js @@ -8,3 +8,6 @@ export const submitQuotation = (id) => request({ url: baseUrl + '/submit/' + id, export const acceptQuotation = (id) => request({ url: baseUrl + '/accept/' + id, method: 'put' }) export const rejectQuotation = (id) => request({ url: baseUrl + '/reject/' + id, method: 'put' }) export const delQuotation = (ids) => request({ url: baseUrl + '/' + ids, method: 'delete' }) + +// 按供应商ID查询报价明细(展开为每行一条物料) +export const getSupplierQuoteItems = (supplierId) => request({ url: baseUrl + '/supplier-items/' + supplierId, method: 'get' }) diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js index 60f2a6e6..702ec5be 100644 --- a/ruoyi-ui/src/router/index.js +++ b/ruoyi-ui/src/router/index.js @@ -112,6 +112,19 @@ export const dynamicRoutes = [ } ] }, + { + path: '/quotemgr/clientquote/detail', + component: Layout, + hidden: true, + children: [ + { + path: '', + component: () => import('@/views/bid/clientquote/detail'), + name: 'ClientQuoteDetail', + meta: { title: '甲方报价单详情', activeMenu: '/quotemgr/clientquote' } + } + ] + }, { path: '/system/user-auth', component: Layout, diff --git a/ruoyi-ui/src/views/bid/clientquote/detail.vue b/ruoyi-ui/src/views/bid/clientquote/detail.vue index 71298ddc..6e8845e4 100644 --- a/ruoyi-ui/src/views/bid/clientquote/detail.vue +++ b/ruoyi-ui/src/views/bid/clientquote/detail.vue @@ -72,9 +72,36 @@ - + @@ -92,22 +119,22 @@ - + - + - + - + @@ -200,6 +227,7 @@ + + diff --git a/ruoyi-ui/src/views/bid/clientquote/index.vue b/ruoyi-ui/src/views/bid/clientquote/index.vue index c0f15b61..0bb6463e 100644 --- a/ruoyi-ui/src/views/bid/clientquote/index.vue +++ b/ruoyi-ui/src/views/bid/clientquote/index.vue @@ -1,113 +1,691 @@ + + + + + diff --git a/ruoyi-ui/src/views/bid/material/components/ClientQuoteTab.vue b/ruoyi-ui/src/views/bid/material/components/ClientQuoteTab.vue index 02048919..a6af825d 100644 --- a/ruoyi-ui/src/views/bid/material/components/ClientQuoteTab.vue +++ b/ruoyi-ui/src/views/bid/material/components/ClientQuoteTab.vue @@ -3,72 +3,100 @@
甲方报价记录 - 导出Excel +
+ 查看全部历史 + 导出Excel +
- - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + +
+ +

暂无甲方报价记录

+ 去创建报价 +