package cn.iocoder.yudao.module.crm.controller.admin.quotation;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
import cn.iocoder.yudao.module.crm.controller.admin.quotation.vo.CrmSaleQuotationPageReqVO;
|
import cn.iocoder.yudao.module.crm.controller.admin.quotation.vo.CrmSaleQuotationRespVO;
|
import cn.iocoder.yudao.module.crm.controller.admin.quotation.vo.CrmSaleQuotationSaveReqVO;
|
import cn.iocoder.yudao.module.crm.dal.dataobject.quotation.CrmSaleQuotationDO;
|
import cn.iocoder.yudao.module.crm.dal.dataobject.quotation.CrmSaleQuotationProductDO;
|
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
import cn.iocoder.yudao.module.crm.service.quotation.CrmSaleQuotationService;
|
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
|
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
|
import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
|
import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO;
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
import jakarta.annotation.Resource;
|
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.validation.Valid;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.validation.annotation.Validated;
|
import org.springframework.web.bind.annotation.*;
|
|
import java.io.IOException;
|
import java.util.List;
|
import java.util.Map;
|
|
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
|
@Tag(name = "管理后台 - CRM 销售报价单")
|
@RestController
|
@RequestMapping("/crm/sale-quotation")
|
@Validated
|
public class CrmSaleQuotationController {
|
|
@Resource
|
private CrmSaleQuotationService saleQuotationService;
|
|
@Resource
|
private AdminUserApi adminUserApi;
|
@Resource
|
private DeptApi deptApi;
|
@Resource
|
private MdmItemApi mdmItemApi;
|
@Resource
|
private MdmUnitMeasureApi mdmUnitMeasureApi;
|
@Resource
|
private CrmCustomerService customerService;
|
|
@PostMapping("/create")
|
@Operation(summary = "创建销售报价单")
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:create')")
|
public CommonResult<Long> createSaleQuotation(@Valid @RequestBody CrmSaleQuotationSaveReqVO createReqVO) {
|
return success(saleQuotationService.createSaleQuotation(createReqVO, getLoginUserId()));
|
}
|
|
@PutMapping("/update")
|
@Operation(summary = "更新销售报价单")
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:update')")
|
public CommonResult<Boolean> updateSaleQuotation(@Valid @RequestBody CrmSaleQuotationSaveReqVO updateReqVO) {
|
saleQuotationService.updateSaleQuotation(updateReqVO);
|
return success(true);
|
}
|
|
@DeleteMapping("/delete")
|
@Operation(summary = "删除销售报价单")
|
@Parameter(name = "ids", description = "编号数组", required = true)
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:delete')")
|
public CommonResult<Boolean> deleteSaleQuotation(@RequestParam("ids") List<Long> ids) {
|
saleQuotationService.deleteSaleQuotation(ids);
|
return success(true);
|
}
|
|
@GetMapping("/get")
|
@Operation(summary = "获得销售报价单")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:query')")
|
public CommonResult<CrmSaleQuotationRespVO> getSaleQuotation(@RequestParam("id") Long id) {
|
CrmSaleQuotationDO saleQuotation = saleQuotationService.getSaleQuotation(id);
|
if (saleQuotation == null) {
|
return success(null);
|
}
|
List<CrmSaleQuotationProductDO> productList = saleQuotationService.getSaleQuotationProductListByQuotationId(id);
|
return success(buildSaleQuotationRespVO(saleQuotation, productList));
|
}
|
|
@GetMapping("/page")
|
@Operation(summary = "获得销售报价单分页")
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:query')")
|
public CommonResult<PageResult<CrmSaleQuotationRespVO>> getSaleQuotationPage(@Valid CrmSaleQuotationPageReqVO pageReqVO) {
|
PageResult<CrmSaleQuotationDO> pageResult = saleQuotationService.getSaleQuotationPage(pageReqVO, getLoginUserId());
|
return success(buildSaleQuotationRespVOPageResult(pageResult));
|
}
|
|
@GetMapping("/page-by-customer")
|
@Operation(summary = "获得销售报价单分页(基于客户)")
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:query')")
|
public CommonResult<PageResult<CrmSaleQuotationRespVO>> getSaleQuotationPageByCustomerId(@Valid CrmSaleQuotationPageReqVO pageReqVO) {
|
PageResult<CrmSaleQuotationDO> pageResult = saleQuotationService.getSaleQuotationPageByCustomerId(pageReqVO);
|
return success(buildSaleQuotationRespVOPageResult(pageResult));
|
}
|
|
@GetMapping("/page-by-business")
|
@Operation(summary = "获得销售报价单分页(基于商机)")
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:query')")
|
public CommonResult<PageResult<CrmSaleQuotationRespVO>> getSaleQuotationPageByBusinessId(@Valid CrmSaleQuotationPageReqVO pageReqVO) {
|
PageResult<CrmSaleQuotationDO> pageResult = saleQuotationService.getSaleQuotationPageByBusinessId(pageReqVO);
|
return success(buildSaleQuotationRespVOPageResult(pageResult));
|
}
|
|
@GetMapping("/export-excel")
|
@Operation(summary = "导出销售报价单 Excel")
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:export')")
|
@ApiAccessLog(operateType = EXPORT)
|
public void exportSaleQuotationExcel(@Valid CrmSaleQuotationPageReqVO pageReqVO,
|
HttpServletResponse response) throws IOException {
|
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
List<CrmSaleQuotationRespVO> list = buildSaleQuotationRespVOPageResult(
|
saleQuotationService.getSaleQuotationPage(pageReqVO, getLoginUserId())).getList();
|
ExcelUtils.write(response, "销售报价单.xls", "数据", CrmSaleQuotationRespVO.class, list);
|
}
|
|
@PostMapping("/convert-contract")
|
@Operation(summary = "转为合同")
|
@Parameter(name = "id", description = "报价单编号", required = true)
|
@PreAuthorize("@ss.hasPermission('crm:sale-quotation:convert-contract')")
|
public CommonResult<Long> convertToContract(@RequestParam("id") Long id) {
|
return success(saleQuotationService.convertToContract(id, getLoginUserId()));
|
}
|
|
// ==================== 构建响应 VO ====================
|
|
private CrmSaleQuotationRespVO buildSaleQuotationRespVO(CrmSaleQuotationDO saleQuotation, List<CrmSaleQuotationProductDO> productList) {
|
CrmSaleQuotationRespVO respVO = BeanUtils.toBean(saleQuotation, CrmSaleQuotationRespVO.class);
|
// 1. 构建物料明细
|
if (CollUtil.isNotEmpty(productList)) {
|
Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(convertSet(productList, CrmSaleQuotationProductDO::getItemId));
|
Map<Long, MdmUnitMeasureRespDTO> unitMap = convertMap(
|
mdmUnitMeasureApi.getUnitMeasureList(
|
convertSet(productList, CrmSaleQuotationProductDO::getItemUnitId)).getCheckedData(),
|
MdmUnitMeasureRespDTO::getId);
|
respVO.setItems(BeanUtils.toBean(productList, CrmSaleQuotationRespVO.Item.class, item -> {
|
MdmItemRespDTO mdmItem = itemMap.get(item.getItemId());
|
if (mdmItem != null) {
|
item.setItemCode(mdmItem.getCode());
|
item.setItemName(mdmItem.getName());
|
item.setItemBarCode(mdmItem.getBarCode());
|
}
|
MapUtils.findAndThen(unitMap, item.getItemUnitId(), unit -> item.setItemUnitName(unit.getName()));
|
}));
|
}
|
// 2. 填充客户名称
|
if (saleQuotation.getCustomerId() != null) {
|
CrmCustomerDO customer = customerService.getCustomer(saleQuotation.getCustomerId());
|
if (customer != null) {
|
respVO.setCustomerName(customer.getName());
|
}
|
}
|
// 3. 填充关联信息
|
fillSaleQuotationRelatedFields(respVO);
|
return respVO;
|
}
|
|
private PageResult<CrmSaleQuotationRespVO> buildSaleQuotationRespVOPageResult(PageResult<CrmSaleQuotationDO> pageResult) {
|
if (CollUtil.isEmpty(pageResult.getList())) {
|
return PageResult.empty(pageResult.getTotal());
|
}
|
// 1. 报价明细
|
List<CrmSaleQuotationProductDO> productList = saleQuotationService.getSaleQuotationProductListByQuotationIds(
|
convertSet(pageResult.getList(), CrmSaleQuotationDO::getId));
|
Map<Long, List<CrmSaleQuotationProductDO>> productMap = convertMultiMap(productList, CrmSaleQuotationProductDO::getQuotationId);
|
// 1.2 物料信息
|
Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(convertSet(productList, CrmSaleQuotationProductDO::getItemId));
|
// 1.3 客户信息
|
Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap(
|
convertSet(pageResult.getList(), CrmSaleQuotationDO::getCustomerId));
|
// 1.4 用户信息
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
convertSet(pageResult.getList(), CrmSaleQuotationDO::getOwnerUserId));
|
// 1.5 部门信息
|
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
|
convertSet(pageResult.getList(), CrmSaleQuotationDO::getOwnerUserId));
|
|
// 2. 开始拼接
|
return BeanUtils.toBean(pageResult, CrmSaleQuotationRespVO.class, vo -> {
|
vo.setItems(BeanUtils.toBean(productMap.get(vo.getId()), CrmSaleQuotationRespVO.Item.class,
|
item -> MapUtils.findAndThen(itemMap, item.getItemId(), mdmItem -> item.setItemCode(mdmItem.getCode())
|
.setItemName(mdmItem.getName()).setItemBarCode(mdmItem.getBarCode()))));
|
MapUtils.findAndThen(customerMap, vo.getCustomerId(), customer -> vo.setCustomerName(customer.getName()));
|
MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname()));
|
MapUtils.findAndThen(deptMap, vo.getOwnerUserId(), dept -> vo.setOwnerUserDeptName(dept.getName()));
|
});
|
}
|
|
private void fillSaleQuotationRelatedFields(CrmSaleQuotationRespVO vo) {
|
// 填充负责人名称
|
if (vo.getOwnerUserId() != null) {
|
AdminUserRespDTO user = adminUserApi.getUser(vo.getOwnerUserId());
|
if (user != null) {
|
vo.setOwnerUserName(user.getNickname());
|
// 填充部门名称
|
if (user.getDeptId() != null) {
|
DeptRespDTO dept = deptApi.getDept(user.getDeptId());
|
if (dept != null) {
|
vo.setOwnerUserDeptName(dept.getName());
|
}
|
}
|
}
|
}
|
// 填充创建人名称
|
if (vo.getCreator() != null) {
|
try {
|
AdminUserRespDTO user = adminUserApi.getUser(Long.valueOf(vo.getCreator()));
|
if (user != null) {
|
vo.setCreatorName(user.getNickname());
|
}
|
} catch (NumberFormatException ignored) {
|
}
|
}
|
}
|
|
}
|