Commit f16b8956c6d52bba13ff329caa08ae7b6e0fabd6

Authored by 房远帅
1 parent 8cd1d61f

报价:业务员报价-新增、编辑、详情、列表

Showing 17 changed files with 2250 additions and 0 deletions
  1 +package com.lframework.xingyun.sc.procurement.controller.quotation;
  2 +
  3 +import com.lframework.starter.common.exceptions.impl.DefaultClientException;
  4 +import com.lframework.starter.web.core.annotations.security.HasPermission;
  5 +import com.lframework.starter.web.core.components.resp.InvokeResult;
  6 +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder;
  7 +import com.lframework.starter.web.core.components.resp.PageResult;
  8 +import com.lframework.starter.web.core.controller.DefaultBaseController;
  9 +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotation;
  10 +import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationService;
  11 +import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationVo;
  12 +import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationVo;
  13 +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationVo;
  14 +import io.swagger.annotations.Api;
  15 +import io.swagger.annotations.ApiImplicitParam;
  16 +import io.swagger.annotations.ApiOperation;
  17 +import javax.annotation.Resource;
  18 +import javax.validation.Valid;
  19 +import javax.validation.constraints.NotBlank;
  20 +import org.springframework.validation.annotation.Validated;
  21 +import org.springframework.web.bind.annotation.GetMapping;
  22 +import org.springframework.web.bind.annotation.PostMapping;
  23 +import org.springframework.web.bind.annotation.PutMapping;
  24 +import org.springframework.web.bind.annotation.RequestBody;
  25 +import org.springframework.web.bind.annotation.RequestMapping;
  26 +import org.springframework.web.bind.annotation.RestController;
  27 +
  28 +/**
  29 + * 业务员报价 Controller
  30 + */
  31 +@Api(tags = "业务员报价")
  32 +@Validated
  33 +@RestController
  34 +@RequestMapping("/procurement/salesmanQuotation")
  35 +public class SalesmanQuotationController extends DefaultBaseController {
  36 +
  37 + /**
  38 + * 业务员报价 Service
  39 + */
  40 + @Resource
  41 + private SalesmanQuotationService salesmanQuotationService;
  42 +
  43 + @ApiOperation("生成编号")
  44 + @GetMapping("/generateCode")
  45 + public InvokeResult<String> generateCode() {
  46 + return InvokeResultBuilder.success(salesmanQuotationService.generateCode());
  47 + }
  48 +
  49 + /**
  50 + * 新增
  51 + *
  52 + * @param vo 新增参数
  53 + * @return 操作结果
  54 + */
  55 + @ApiOperation("新增")
  56 + @HasPermission({"procure-manage:sales-price:add"})
  57 + @PostMapping
  58 + public InvokeResult<Void> create(@Valid @RequestBody CreateSalesmanQuotationVo vo) {
  59 + salesmanQuotationService.create(vo);
  60 + return InvokeResultBuilder.success();
  61 + }
  62 +
  63 + /**
  64 + * 分页查询
  65 + *
  66 + * @param vo 查询条件
  67 + * @return 分页结果
  68 + */
  69 + @ApiOperation("分页查询")
  70 + @HasPermission({"procure-manage:sales-price:query"})
  71 + @GetMapping("/query")
  72 + public InvokeResult<PageResult<SalesmanQuotation>> query(@Valid QuerySalesmanQuotationVo vo) {
  73 + return InvokeResultBuilder.success(
  74 + salesmanQuotationService.query(getPageIndex(vo), getPageSize(vo), vo));
  75 + }
  76 +
  77 + /**
  78 + * 详情
  79 + *
  80 + * @param id 主键ID
  81 + * @return 详情
  82 + */
  83 + @ApiOperation("详情")
  84 + @HasPermission({"procure-manage:sales-price:query"})
  85 + @ApiImplicitParam(value = "id", name = "id", paramType = "query", required = true)
  86 + @GetMapping("")
  87 + public InvokeResult<SalesmanQuotation> get(@NotBlank(message = "id不能为空!") String id) {
  88 + SalesmanQuotation data = salesmanQuotationService.findById(id);
  89 + if (data == null) {
  90 + throw new DefaultClientException("业务员报价不存在!");
  91 + }
  92 + return InvokeResultBuilder.success(data);
  93 + }
  94 +
  95 + /**
  96 + * 修改
  97 + *
  98 + * @param vo 修改参数
  99 + * @return 操作结果
  100 + */
  101 + @ApiOperation("修改")
  102 + @HasPermission({"procure-manage:sales-price:modify"})
  103 + @PutMapping
  104 + public InvokeResult<Void> update(@Valid @RequestBody UpdateSalesmanQuotationVo vo) {
  105 + salesmanQuotationService.update(vo);
  106 + return InvokeResultBuilder.success();
  107 + }
  108 +}
  1 +package com.lframework.xingyun.sc.procurement.entity;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.FieldFill;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import com.lframework.starter.web.core.dto.BaseDto;
  7 +import com.lframework.starter.web.core.entity.BaseEntity;
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDate;
  10 +import java.time.LocalDateTime;
  11 +import java.util.List;
  12 +import lombok.Data;
  13 +
  14 +/**
  15 + * 业务员报价主表
  16 + */
  17 +@Data
  18 +@TableName("procurement_salesman_quotation")
  19 +public class SalesmanQuotation extends BaseEntity implements BaseDto {
  20 +
  21 + private static final long serialVersionUID = 1L;
  22 +
  23 + public static final String CACHE_NAME = "SalesmanQuotation";
  24 +
  25 + /**
  26 + * ID
  27 + */
  28 + private String id;
  29 +
  30 + /**
  31 + * 编号
  32 + */
  33 + private String code;
  34 +
  35 + /**
  36 + * 内贸资信ID
  37 + */
  38 + private String supplierId;
  39 +
  40 + /**
  41 + * 供应商名称
  42 + */
  43 + @TableField(exist = false)
  44 + private String supplierName;
  45 +
  46 + /**
  47 + * 采购处
  48 + */
  49 + private String purchaseDepartment;
  50 +
  51 + /**
  52 + * 采购处名称
  53 + */
  54 + @TableField(exist = false)
  55 + private String purchaseDepartmentName;
  56 +
  57 + /**
  58 + * 采购处编码
  59 + */
  60 + @TableField(exist = false)
  61 + private String purchaseDepartmentCode;
  62 +
  63 + /**
  64 + * 区域
  65 + */
  66 + private String region;
  67 +
  68 + /**
  69 + * 区域名称
  70 + */
  71 + @TableField(exist = false)
  72 + private String regionName;
  73 +
  74 + /**
  75 + * 报价时间
  76 + */
  77 + private LocalDateTime quoteTime;
  78 +
  79 + /**
  80 + * 报价时效
  81 + */
  82 + private String validityPeriod;
  83 +
  84 + /**
  85 + * 报价人ID
  86 + */
  87 + private String quoterId;
  88 +
  89 + /**
  90 + * 报价人
  91 + */
  92 + private String quoterName;
  93 +
  94 + /**
  95 + * 是否长单操作
  96 + */
  97 + private Boolean longTermOperation;
  98 +
  99 + /**
  100 + * 是否终端客户
  101 + */
  102 + private Boolean terminalCustomer;
  103 +
  104 + /**
  105 + * 是否为点价
  106 + */
  107 + private Boolean priced;
  108 +
  109 + /**
  110 + * 点价截止日期
  111 + */
  112 + private LocalDate pricingDeadline;
  113 +
  114 + /**
  115 + * 其他费用凭票到厂另行结算
  116 + */
  117 + private Boolean otherExpenseSettlement;
  118 +
  119 + /**
  120 + * 交提货方式
  121 + */
  122 + private String deliveryMode;
  123 +
  124 + /**
  125 + * 是否通货买断
  126 + */
  127 + private Boolean commodityBuyout;
  128 +
  129 + /**
  130 + * 是否质量买断
  131 + */
  132 + private Boolean qualityBuyout;
  133 +
  134 + /**
  135 + * 是否数量买断
  136 + */
  137 + private Boolean quantityBuyout;
  138 +
  139 + /**
  140 + * 是否送货上门
  141 + */
  142 + private Boolean doorDelivery;
  143 +
  144 + /**
  145 + * 装车费
  146 + */
  147 + private BigDecimal loadingFee;
  148 +
  149 + /**
  150 + * 开票品种
  151 + */
  152 + private String invoiceProductName;
  153 +
  154 + /**
  155 + * 交货日期
  156 + */
  157 + private LocalDate deliveryDate;
  158 +
  159 + /**
  160 + * 结算方式
  161 + */
  162 + private String settlementMethod;
  163 +
  164 + /**
  165 + * 结算比例(%)
  166 + */
  167 + private BigDecimal settlementRatio;
  168 +
  169 + /**
  170 + * 协调事由
  171 + */
  172 + private String coordinationReason;
  173 +
  174 + /**
  175 + * 票类状况
  176 + */
  177 + private String invoiceTypeStatus;
  178 +
  179 + /**
  180 + * 是否启用料质状况
  181 + */
  182 + private Boolean materialConditionEnabled;
  183 +
  184 + /**
  185 + * 铜米
  186 + */
  187 + private String materialConditionCopperRice;
  188 +
  189 + /**
  190 + * 光亮铜
  191 + */
  192 + private String materialConditionBrightCopper;
  193 +
  194 + /**
  195 + * 一特
  196 + */
  197 + private String materialConditionFirstClass;
  198 +
  199 + /**
  200 + * 二特
  201 + */
  202 + private String materialConditionSecondClass;
  203 +
  204 + /**
  205 + * 镀锡紫
  206 + */
  207 + private String materialConditionTinCoated;
  208 +
  209 + /**
  210 + * 角料
  211 + */
  212 + private String materialConditionScrap;
  213 +
  214 + /**
  215 + * 镀白黄
  216 + */
  217 + private String materialConditionWhiteYellow;
  218 +
  219 + /**
  220 + * 磷铜
  221 + */
  222 + private String materialConditionPhosphorCopper;
  223 +
  224 + /**
  225 + * 数量合计
  226 + */
  227 + private BigDecimal totalQuantity;
  228 +
  229 + /**
  230 + * 报价明细列表
  231 + */
  232 + @TableField(exist = false)
  233 + private List<SalesmanQuotationLine> quotationLineList;
  234 +
  235 + /**
  236 + * 创建人ID
  237 + */
  238 + @TableField(fill = FieldFill.INSERT)
  239 + private String createById;
  240 +
  241 + /**
  242 + * 创建人
  243 + */
  244 + @TableField(fill = FieldFill.INSERT)
  245 + private String createBy;
  246 +
  247 + /**
  248 + * 更新人ID
  249 + */
  250 + @TableField(fill = FieldFill.INSERT_UPDATE)
  251 + private String updateById;
  252 +
  253 + /**
  254 + * 更新人
  255 + */
  256 + @TableField(fill = FieldFill.INSERT_UPDATE)
  257 + private String updateBy;
  258 +
  259 + /**
  260 + * 创建时间
  261 + */
  262 + @TableField(fill = FieldFill.INSERT)
  263 + private LocalDateTime createTime;
  264 +
  265 + /**
  266 + * 更新时间
  267 + */
  268 + @TableField(fill = FieldFill.INSERT_UPDATE)
  269 + private LocalDateTime updateTime;
  270 +}
  1 +package com.lframework.xingyun.sc.procurement.entity;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.FieldFill;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import com.lframework.starter.web.core.dto.BaseDto;
  7 +import com.lframework.starter.web.core.entity.BaseEntity;
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDateTime;
  10 +import lombok.Data;
  11 +
  12 +/**
  13 + * 业务员报价明细表
  14 + */
  15 +@Data
  16 +@TableName("procurement_salesman_quotation_line")
  17 +public class SalesmanQuotationLine extends BaseEntity implements BaseDto {
  18 +
  19 + private static final long serialVersionUID = 1L;
  20 +
  21 + public static final String CACHE_NAME = "SalesmanQuotationLine";
  22 +
  23 + /**
  24 + * ID
  25 + */
  26 + private String id;
  27 +
  28 + /**
  29 + * 业务员报价ID
  30 + */
  31 + private String quotationId;
  32 +
  33 + /**
  34 + * 品种ID
  35 + */
  36 + private String productId;
  37 +
  38 + /**
  39 + * 品种名称
  40 + */
  41 + @TableField(exist = false)
  42 + private String productName;
  43 +
  44 + /**
  45 + * 品种代号
  46 + */
  47 + @TableField(exist = false)
  48 + private String productCode;
  49 +
  50 + /**
  51 + * 品种类型
  52 + */
  53 + @TableField(exist = false)
  54 + private String productType;
  55 +
  56 + /**
  57 + * 品种固定损耗率
  58 + */
  59 + @TableField(exist = false)
  60 + private BigDecimal fixedAttritionRate;
  61 +
  62 + /**
  63 + * 料型
  64 + */
  65 + private String materialType;
  66 +
  67 + /**
  68 + * 数量
  69 + */
  70 + private BigDecimal quantity;
  71 +
  72 + /**
  73 + * 采购价
  74 + */
  75 + private BigDecimal purchasePrice;
  76 +
  77 + /**
  78 + * 买断料预计损耗
  79 + */
  80 + private BigDecimal estimatedLoss;
  81 +
  82 + /**
  83 + * 申请损耗
  84 + */
  85 + private BigDecimal applicationAttrition;
  86 +
  87 + /**
  88 + * 前端行标识
  89 + */
  90 + private String itemId;
  91 +
  92 + /**
  93 + * 创建人ID
  94 + */
  95 + @TableField(fill = FieldFill.INSERT)
  96 + private String createById;
  97 +
  98 + /**
  99 + * 创建人
  100 + */
  101 + @TableField(fill = FieldFill.INSERT)
  102 + private String createBy;
  103 +
  104 + /**
  105 + * 更新人ID
  106 + */
  107 + @TableField(fill = FieldFill.INSERT_UPDATE)
  108 + private String updateById;
  109 +
  110 + /**
  111 + * 更新人
  112 + */
  113 + @TableField(fill = FieldFill.INSERT_UPDATE)
  114 + private String updateBy;
  115 +
  116 + /**
  117 + * 创建时间
  118 + */
  119 + @TableField(fill = FieldFill.INSERT)
  120 + private LocalDateTime createTime;
  121 +
  122 + /**
  123 + * 更新时间
  124 + */
  125 + @TableField(fill = FieldFill.INSERT_UPDATE)
  126 + private LocalDateTime updateTime;
  127 +}
  1 +package com.lframework.xingyun.sc.procurement.impl.quotation;
  2 +
  3 +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  4 +import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  5 +import com.lframework.starter.common.exceptions.impl.DefaultClientException;
  6 +import com.lframework.starter.common.utils.ObjectUtil;
  7 +import com.lframework.starter.web.core.annotations.oplog.OpLog;
  8 +import com.lframework.starter.web.core.impl.BaseMpServiceImpl;
  9 +import com.lframework.starter.web.core.utils.IdUtil;
  10 +import com.lframework.starter.web.core.utils.OpLogUtil;
  11 +import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
  12 +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine;
  13 +import com.lframework.xingyun.sc.procurement.mappers.quotation.SalesmanQuotationLineMapper;
  14 +import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationLineService;
  15 +import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationLineVo;
  16 +import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo;
  17 +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo;
  18 +import java.io.Serializable;
  19 +import java.util.List;
  20 +import org.apache.commons.lang3.StringUtils;
  21 +import org.springframework.stereotype.Service;
  22 +import org.springframework.transaction.annotation.Transactional;
  23 +
  24 +/**
  25 + * 业务员报价明细 Service 实现
  26 + */
  27 +@Service
  28 +public class SalesmanQuotationLineServiceImpl
  29 + extends BaseMpServiceImpl<SalesmanQuotationLineMapper, SalesmanQuotationLine>
  30 + implements SalesmanQuotationLineService {
  31 +
  32 + /**
  33 + * 查询列表
  34 + *
  35 + * @param vo 查询条件
  36 + * @return 明细列表
  37 + */
  38 + @Override
  39 + public List<SalesmanQuotationLine> query(QuerySalesmanQuotationLineVo vo) {
  40 + return getBaseMapper().query(vo);
  41 + }
  42 +
  43 + /**
  44 + * 根据ID查询
  45 + *
  46 + * @param id 主键ID
  47 + * @return 明细信息
  48 + */
  49 + @Override
  50 + public SalesmanQuotationLine findById(String id) {
  51 + return getBaseMapper().selectById(id);
  52 + }
  53 +
  54 + /**
  55 + * 创建
  56 + *
  57 + * @param vo 创建参数
  58 + * @return 主键ID
  59 + */
  60 + @OpLog(type = OtherOpLogType.class, name = "新增业务员报价明细,ID:{}", params = {"#id"})
  61 + @Transactional(rollbackFor = Exception.class)
  62 + @Override
  63 + public String create(CreateSalesmanQuotationLineVo vo) {
  64 + SalesmanQuotationLine data = new SalesmanQuotationLine();
  65 + data.setId(IdUtil.getId());
  66 + data.setQuotationId(vo.getQuotationId());
  67 + data.setProductId(vo.getProductId());
  68 + data.setMaterialType(StringUtils.defaultIfBlank(vo.getMaterialType(), null));
  69 + data.setQuantity(vo.getQuantity());
  70 + data.setPurchasePrice(vo.getPurchasePrice());
  71 + data.setApplicationAttrition(vo.getApplicationAttrition());
  72 + data.setItemId(StringUtils.defaultIfBlank(vo.getItemId(), IdUtil.getId()));
  73 +
  74 + getBaseMapper().insert(data);
  75 +
  76 + OpLogUtil.setVariable("id", data.getId());
  77 + OpLogUtil.setExtra(vo);
  78 + return data.getId();
  79 + }
  80 +
  81 + /**
  82 + * 修改
  83 + *
  84 + * @param vo 修改参数
  85 + */
  86 + @OpLog(type = OtherOpLogType.class, name = "修改业务员报价明细,ID:{}", params = {"#vo.id"})
  87 + @Transactional(rollbackFor = Exception.class)
  88 + @Override
  89 + public void update(UpdateSalesmanQuotationLineVo vo) {
  90 + SalesmanQuotationLine data = getBaseMapper().selectById(vo.getId());
  91 + if (ObjectUtil.isNull(data)) {
  92 + throw new DefaultClientException("业务员报价明细不存在!");
  93 + }
  94 +
  95 + LambdaUpdateWrapper<SalesmanQuotationLine> updateWrapper = Wrappers.lambdaUpdate(SalesmanQuotationLine.class)
  96 + .set(SalesmanQuotationLine::getQuotationId, vo.getQuotationId())
  97 + .set(SalesmanQuotationLine::getProductId, vo.getProductId())
  98 + .set(SalesmanQuotationLine::getMaterialType, StringUtils.defaultIfBlank(vo.getMaterialType(), null))
  99 + .set(SalesmanQuotationLine::getQuantity, vo.getQuantity())
  100 + .set(SalesmanQuotationLine::getPurchasePrice, vo.getPurchasePrice())
  101 + .set(SalesmanQuotationLine::getApplicationAttrition, vo.getApplicationAttrition())
  102 + .set(SalesmanQuotationLine::getItemId, StringUtils.defaultIfBlank(vo.getItemId(), data.getItemId()))
  103 + .eq(SalesmanQuotationLine::getId, vo.getId());
  104 +
  105 + getBaseMapper().update(updateWrapper);
  106 +
  107 + OpLogUtil.setVariable("id", data.getId());
  108 + OpLogUtil.setExtra(vo);
  109 + }
  110 +
  111 + /**
  112 + * 清理缓存
  113 + *
  114 + * @param key 缓存键
  115 + */
  116 + @Override
  117 + public void cleanCacheByKey(Serializable key) {
  118 + }
  119 +}
  1 +package com.lframework.xingyun.sc.procurement.impl.quotation;
  2 +
  3 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4 +import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  5 +import com.github.pagehelper.PageInfo;
  6 +import com.lframework.starter.common.exceptions.impl.DefaultClientException;
  7 +import com.lframework.starter.common.utils.Assert;
  8 +import com.lframework.starter.common.utils.CollectionUtil;
  9 +import com.lframework.starter.common.utils.ObjectUtil;
  10 +import com.lframework.starter.web.core.annotations.oplog.OpLog;
  11 +import com.lframework.starter.web.core.components.resp.PageResult;
  12 +import com.lframework.starter.web.core.components.security.SecurityUtil;
  13 +import com.lframework.starter.web.core.impl.BaseMpServiceImpl;
  14 +import com.lframework.starter.web.core.utils.IdUtil;
  15 +import com.lframework.starter.web.core.utils.OpLogUtil;
  16 +import com.lframework.starter.web.core.utils.PageHelperUtil;
  17 +import com.lframework.starter.web.core.utils.PageResultUtil;
  18 +import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
  19 +import com.lframework.starter.web.inner.entity.SysUser;
  20 +import com.lframework.starter.web.inner.service.system.SysUserService;
  21 +import com.lframework.xingyun.basedata.entity.BreedRelationship;
  22 +import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService;
  23 +import com.lframework.xingyun.sc.procurement.entity.ProcurementDomesticCustomerCredit;
  24 +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotation;
  25 +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine;
  26 +import com.lframework.xingyun.sc.procurement.mappers.quotation.SalesmanQuotationMapper;
  27 +import com.lframework.xingyun.sc.procurement.service.credit.ProcurementDomesticCustomerCreditService;
  28 +import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationLineService;
  29 +import com.lframework.xingyun.sc.procurement.service.quotation.SalesmanQuotationService;
  30 +import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationLineVo;
  31 +import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationVo;
  32 +import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo;
  33 +import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationVo;
  34 +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo;
  35 +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationVo;
  36 +import java.io.Serializable;
  37 +import java.math.BigDecimal;
  38 +import java.math.RoundingMode;
  39 +import java.time.LocalDate;
  40 +import java.time.LocalDateTime;
  41 +import java.time.format.DateTimeFormatter;
  42 +import java.util.ArrayList;
  43 +import java.util.Collections;
  44 +import java.util.List;
  45 +import java.util.Map;
  46 +import java.util.stream.Collectors;
  47 +import org.apache.commons.lang3.StringUtils;
  48 +import org.springframework.stereotype.Service;
  49 +import org.springframework.transaction.annotation.Transactional;
  50 +import javax.annotation.Resource;
  51 +
  52 +/**
  53 + * 业务员报价 Service 实现
  54 + */
  55 +@Service
  56 +public class SalesmanQuotationServiceImpl
  57 + extends BaseMpServiceImpl<SalesmanQuotationMapper, SalesmanQuotation>
  58 + implements SalesmanQuotationService {
  59 + @Resource
  60 + private SysUserService sysUserService;
  61 + @Resource
  62 + private ProcurementDomesticCustomerCreditService procurementDomesticCustomerCreditService;
  63 + @Resource
  64 + private BreedRelationshipService breedRelationshipService;
  65 + @Resource
  66 + private SalesmanQuotationLineService salesmanQuotationLineService;
  67 +
  68 + /**
  69 + * 编号前缀
  70 + */
  71 + private static final String CODE_PREFIX = "BJ";
  72 +
  73 + /**
  74 + * 默认协调事由
  75 + */
  76 + private static final String DEFAULT_COORDINATION_REASON = "受市场影响,申请协调";
  77 +
  78 + /**
  79 + * 默认票类状况
  80 + */
  81 + private static final String DEFAULT_INVOICE_TYPE_STATUS = "增票";
  82 +
  83 + /**
  84 + * 分页查询
  85 + *
  86 + * @param pageIndex 页码
  87 + * @param pageSize 页大小
  88 + * @param vo 查询条件
  89 + * @return 分页结果
  90 + */
  91 + @Override
  92 + public PageResult<SalesmanQuotation> query(Integer pageIndex, Integer pageSize, QuerySalesmanQuotationVo vo) {
  93 + Assert.greaterThanZero(pageIndex);
  94 + Assert.greaterThanZero(pageSize);
  95 +
  96 + PageHelperUtil.startPage(pageIndex, pageSize);
  97 + List<SalesmanQuotation> datas = this.query(vo);
  98 + return PageResultUtil.convert(new PageInfo<>(datas));
  99 + }
  100 +
  101 + /**
  102 + * 查询列表
  103 + *
  104 + * @param vo 查询条件
  105 + * @return 列表
  106 + */
  107 + @Override
  108 + public List<SalesmanQuotation> query(QuerySalesmanQuotationVo vo) {
  109 + return getBaseMapper().query(vo);
  110 + }
  111 +
  112 + /**
  113 + * 根据ID查询
  114 + *
  115 + * @param id 主键ID
  116 + * @return 业务员报价
  117 + */
  118 + @Override
  119 + public SalesmanQuotation findById(String id) {
  120 + SalesmanQuotation data = getBaseMapper().findById(id);
  121 + if (data == null) {
  122 + return null;
  123 + }
  124 +
  125 + QuerySalesmanQuotationLineVo lineQueryVo = new QuerySalesmanQuotationLineVo();
  126 + lineQueryVo.setQuotationId(id);
  127 + data.setQuotationLineList(salesmanQuotationLineService.query(lineQueryVo));
  128 +
  129 + return data;
  130 + }
  131 +
  132 + /**
  133 + * 新增
  134 + *
  135 + * @param vo 新增参数
  136 + * @return 主键ID
  137 + */
  138 + @OpLog(type = OtherOpLogType.class, name = "新增业务员报价,ID:{}", params = {"#id"})
  139 + @Transactional(rollbackFor = Exception.class)
  140 + @Override
  141 + public String create(CreateSalesmanQuotationVo vo) {
  142 + SysUser currentUser = getCurrentUser();
  143 + ProcurementDomesticCustomerCredit supplier = getSupplierOrThrow(vo.getSupplierId());
  144 + validateCreateVo(vo);
  145 + checkCodeUnique(StringUtils.trimToEmpty(vo.getCode()));
  146 +
  147 + Map<String, BreedRelationship> quotationBreedMap = getBreedMap(vo.getQuotationLineList().stream()
  148 + .map(CreateSalesmanQuotationLineVo::getProductId)
  149 + .collect(Collectors.toList()));
  150 + SalesmanQuotation data = buildCreateEntity(vo, supplier, currentUser);
  151 + getBaseMapper().insert(data);
  152 +
  153 + saveCreateLines(data.getId(), vo.getQuotationLineList(), quotationBreedMap, vo.getPriced());
  154 +
  155 + OpLogUtil.setVariable("id", data.getId());
  156 + OpLogUtil.setExtra(vo);
  157 + return data.getId();
  158 + }
  159 +
  160 + /**
  161 + * 修改
  162 + *
  163 + * @param vo 修改参数
  164 + */
  165 + @OpLog(type = OtherOpLogType.class, name = "修改业务员报价,ID:{}", params = {"#vo.id"})
  166 + @Transactional(rollbackFor = Exception.class)
  167 + @Override
  168 + public void update(UpdateSalesmanQuotationVo vo) {
  169 + SalesmanQuotation data = getBaseMapper().selectById(vo.getId());
  170 + if (ObjectUtil.isNull(data)) {
  171 + throw new DefaultClientException("业务员报价不存在!");
  172 + }
  173 +
  174 + ProcurementDomesticCustomerCredit supplier = getSupplierOrThrow(vo.getSupplierId());
  175 + validateUpdateVo(vo);
  176 +
  177 + Map<String, BreedRelationship> quotationBreedMap = getBreedMap(vo.getQuotationLineList().stream()
  178 + .map(UpdateSalesmanQuotationLineVo::getProductId)
  179 + .collect(Collectors.toList()));
  180 + fillUpdateEntity(data, vo, supplier);
  181 + getBaseMapper().updateById(data);
  182 +
  183 + saveOrUpdateLines(data.getId(), vo.getQuotationLineList(), quotationBreedMap, vo.getPriced());
  184 +
  185 + OpLogUtil.setVariable("id", data.getId());
  186 + OpLogUtil.setExtra(vo);
  187 + }
  188 +
  189 + /**
  190 + * 构建新增实体
  191 + *
  192 + * @param vo 新增参数
  193 + * @param supplier 供应商
  194 + * @param currentUser 当前用户
  195 + * @return 业务员报价实体
  196 + */
  197 + private SalesmanQuotation buildCreateEntity(CreateSalesmanQuotationVo vo,
  198 + ProcurementDomesticCustomerCredit supplier, SysUser currentUser) {
  199 + SalesmanQuotation data = new SalesmanQuotation();
  200 + data.setId(IdUtil.getId());
  201 + data.setCode(StringUtils.trimToEmpty(vo.getCode()));
  202 + data.setQuoteTime(LocalDateTime.now());
  203 + data.setQuoterId(currentUser.getId());
  204 + data.setQuoterName(currentUser.getName());
  205 + fillCommonEntity(data, vo, supplier);
  206 + return data;
  207 + }
  208 +
  209 + /**
  210 + * 填充修改实体
  211 + *
  212 + * @param data 实体
  213 + * @param vo 修改参数
  214 + * @param supplier 供应商
  215 + */
  216 + private void fillUpdateEntity(SalesmanQuotation data, UpdateSalesmanQuotationVo vo,
  217 + ProcurementDomesticCustomerCredit supplier) {
  218 + data.setSupplierId(supplier.getId());
  219 + data.setPurchaseDepartment(supplier.getPurchaseDepartment());
  220 + data.setRegion(supplier.getRegion());
  221 + data.setValidityPeriod(vo.getValidityPeriod());
  222 + data.setLongTermOperation(vo.getLongTermOperation());
  223 + data.setTerminalCustomer(vo.getTerminalCustomer());
  224 + data.setPriced(vo.getPriced());
  225 + data.setPricingDeadline(vo.getPricingDeadline());
  226 + data.setOtherExpenseSettlement(vo.getOtherExpenseSettlement());
  227 + data.setDeliveryMode(vo.getDeliveryMode());
  228 + data.setCommodityBuyout(vo.getCommodityBuyout());
  229 + data.setQualityBuyout(vo.getQualityBuyout());
  230 + data.setQuantityBuyout(vo.getQuantityBuyout());
  231 + data.setDoorDelivery(vo.getDoorDelivery());
  232 + data.setLoadingFee(vo.getLoadingFee());
  233 + data.setInvoiceProductName(vo.getInvoiceProductName());
  234 + data.setDeliveryDate(vo.getDeliveryDate());
  235 + data.setSettlementMethod(vo.getSettlementMethod());
  236 + data.setSettlementRatio(vo.getSettlementRatio());
  237 + data.setCoordinationReason(DEFAULT_COORDINATION_REASON);
  238 + data.setInvoiceTypeStatus(DEFAULT_INVOICE_TYPE_STATUS);
  239 + data.setMaterialConditionEnabled(vo.getMaterialConditionEnabled());
  240 + data.setMaterialConditionCopperRice(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionCopperRice()));
  241 + data.setMaterialConditionBrightCopper(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionBrightCopper()));
  242 + data.setMaterialConditionFirstClass(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionFirstClass()));
  243 + data.setMaterialConditionSecondClass(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionSecondClass()));
  244 + data.setMaterialConditionTinCoated(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionTinCoated()));
  245 + data.setMaterialConditionScrap(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionScrap()));
  246 + data.setMaterialConditionWhiteYellow(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionWhiteYellow()));
  247 + data.setMaterialConditionPhosphorCopper(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionPhosphorCopper()));
  248 + data.setTotalQuantity(calculateTotalQuantity(vo.getQuotationLineList()));
  249 + }
  250 +
  251 + /**
  252 + * 填充公共实体字段
  253 + *
  254 + * @param data 实体
  255 + * @param vo 参数
  256 + * @param supplier 供应商
  257 + */
  258 + private void fillCommonEntity(SalesmanQuotation data, CreateSalesmanQuotationVo vo,
  259 + ProcurementDomesticCustomerCredit supplier) {
  260 + data.setSupplierId(supplier.getId());
  261 + data.setPurchaseDepartment(supplier.getPurchaseDepartment());
  262 + data.setRegion(supplier.getRegion());
  263 + data.setValidityPeriod(vo.getValidityPeriod());
  264 + data.setLongTermOperation(vo.getLongTermOperation());
  265 + data.setTerminalCustomer(vo.getTerminalCustomer());
  266 + data.setPriced(vo.getPriced());
  267 + data.setPricingDeadline(vo.getPricingDeadline());
  268 + data.setOtherExpenseSettlement(vo.getOtherExpenseSettlement());
  269 + data.setDeliveryMode(vo.getDeliveryMode());
  270 + data.setCommodityBuyout(vo.getCommodityBuyout());
  271 + data.setQualityBuyout(vo.getQualityBuyout());
  272 + data.setQuantityBuyout(vo.getQuantityBuyout());
  273 + data.setDoorDelivery(vo.getDoorDelivery());
  274 + data.setLoadingFee(vo.getLoadingFee());
  275 + data.setInvoiceProductName(vo.getInvoiceProductName());
  276 + data.setDeliveryDate(vo.getDeliveryDate());
  277 + data.setSettlementMethod(vo.getSettlementMethod());
  278 + data.setSettlementRatio(vo.getSettlementRatio());
  279 + data.setCoordinationReason(DEFAULT_COORDINATION_REASON);
  280 + data.setInvoiceTypeStatus(DEFAULT_INVOICE_TYPE_STATUS);
  281 + data.setMaterialConditionEnabled(vo.getMaterialConditionEnabled());
  282 + data.setMaterialConditionCopperRice(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionCopperRice()));
  283 + data.setMaterialConditionBrightCopper(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionBrightCopper()));
  284 + data.setMaterialConditionFirstClass(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionFirstClass()));
  285 + data.setMaterialConditionSecondClass(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionSecondClass()));
  286 + data.setMaterialConditionTinCoated(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionTinCoated()));
  287 + data.setMaterialConditionScrap(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionScrap()));
  288 + data.setMaterialConditionWhiteYellow(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionWhiteYellow()));
  289 + data.setMaterialConditionPhosphorCopper(normalizeMaterialText(vo.getMaterialConditionEnabled(), vo.getMaterialConditionPhosphorCopper()));
  290 + data.setTotalQuantity(calculateTotalQuantity(vo.getQuotationLineList()));
  291 + }
  292 +
  293 + /**
  294 + * 校验新增参数
  295 + *
  296 + * @param vo 新增参数
  297 + */
  298 + private void validateCreateVo(CreateSalesmanQuotationVo vo) {
  299 + validatePricingRule(vo.getPriced(), vo.getPricingDeadline());
  300 + validateQuotationLines(vo.getQuotationLineList(), vo.getPriced());
  301 + }
  302 +
  303 + /**
  304 + * 校验修改参数
  305 + *
  306 + * @param vo 修改参数
  307 + */
  308 + private void validateUpdateVo(UpdateSalesmanQuotationVo vo) {
  309 + validatePricingRule(vo.getPriced(), vo.getPricingDeadline());
  310 + validateQuotationLines(vo.getQuotationLineList(), vo.getPriced());
  311 + }
  312 +
  313 + /**
  314 + * 校验点价规则
  315 + *
  316 + * @param priced 是否为点价
  317 + * @param pricingDeadline 点价截止日期
  318 + */
  319 + private void validatePricingRule(Boolean priced, LocalDate pricingDeadline) {
  320 + if (Boolean.FALSE.equals(priced) && pricingDeadline == null) {
  321 + throw new DefaultClientException("非点价时,点价截止日期不能为空!");
  322 + }
  323 + }
  324 +
  325 + /**
  326 + * 校验报价明细
  327 + *
  328 + * @param lineList 明细列表
  329 + * @param priced 是否为点价
  330 + */
  331 + private void validateQuotationLines(List<? extends CreateSalesmanQuotationLineVo> lineList, Boolean priced) {
  332 + if (CollectionUtil.isEmpty(lineList)) {
  333 + throw new DefaultClientException("报价明细不能为空!");
  334 + }
  335 +
  336 + if (!Boolean.TRUE.equals(priced)) {
  337 + return;
  338 + }
  339 +
  340 + for (CreateSalesmanQuotationLineVo lineVo : lineList) {
  341 + if (lineVo.getPurchasePrice() == null) {
  342 + throw new DefaultClientException("点价时,采购价不能为空!");
  343 + }
  344 + }
  345 + }
  346 +
  347 + /**
  348 + * 保存新增明细
  349 + *
  350 + * @param quotationId 主表ID
  351 + * @param lineList 明细列表
  352 + * @param breedMap 品种映射
  353 + * @param priced 是否为点价
  354 + */
  355 + private void saveCreateLines(String quotationId, List<CreateSalesmanQuotationLineVo> lineList,
  356 + Map<String, BreedRelationship> breedMap, Boolean priced) {
  357 + for (CreateSalesmanQuotationLineVo lineVo : lineList) {
  358 + CreateSalesmanQuotationLineVo createLineVo = new CreateSalesmanQuotationLineVo();
  359 + createLineVo.setQuotationId(quotationId);
  360 + createLineVo.setProductId(lineVo.getProductId());
  361 + createLineVo.setMaterialType(lineVo.getMaterialType());
  362 + createLineVo.setQuantity(lineVo.getQuantity());
  363 + createLineVo.setPurchasePrice(lineVo.getPurchasePrice());
  364 + createLineVo.setApplicationAttrition(lineVo.getApplicationAttrition());
  365 + createLineVo.setItemId(lineVo.getItemId());
  366 + String lineId = salesmanQuotationLineService.create(createLineVo);
  367 +
  368 + BreedRelationship breedRelationship = breedMap.get(lineVo.getProductId());
  369 + BigDecimal estimatedLoss = calculateEstimatedLoss(lineVo.getPurchasePrice(),
  370 + lineVo.getApplicationAttrition(), breedRelationship.getAttritionRate(), priced);
  371 + updateLineEstimatedLoss(lineId, estimatedLoss);
  372 + }
  373 + }
  374 +
  375 + /**
  376 + * 保存或更新明细
  377 + *
  378 + * @param quotationId 主表ID
  379 + * @param lineList 明细列表
  380 + * @param breedMap 品种映射
  381 + * @param priced 是否为点价
  382 + */
  383 + private void saveOrUpdateLines(String quotationId, List<UpdateSalesmanQuotationLineVo> lineList,
  384 + Map<String, BreedRelationship> breedMap, Boolean priced) {
  385 + QuerySalesmanQuotationLineVo queryVo = new QuerySalesmanQuotationLineVo();
  386 + queryVo.setQuotationId(quotationId);
  387 + List<SalesmanQuotationLine> oldLineList = salesmanQuotationLineService.query(queryVo);
  388 + Map<String, SalesmanQuotationLine> oldLineMap = CollectionUtil.isEmpty(oldLineList)
  389 + ? Collections.emptyMap()
  390 + : oldLineList.stream().collect(Collectors.toMap(SalesmanQuotationLine::getId, v -> v));
  391 +
  392 + List<String> existIdList = new ArrayList<>();
  393 + for (UpdateSalesmanQuotationLineVo lineVo : lineList) {
  394 + BreedRelationship breedRelationship = breedMap.get(lineVo.getProductId());
  395 + BigDecimal estimatedLoss = calculateEstimatedLoss(lineVo.getPurchasePrice(),
  396 + lineVo.getApplicationAttrition(), breedRelationship.getAttritionRate(), priced);
  397 +
  398 + if (StringUtils.isNotBlank(lineVo.getId())) {
  399 + SalesmanQuotationLine oldLine = oldLineMap.get(lineVo.getId());
  400 + if (oldLine == null) {
  401 + throw new DefaultClientException("报价明细不存在或不属于当前报价单!");
  402 + }
  403 +
  404 + existIdList.add(lineVo.getId());
  405 + lineVo.setQuotationId(quotationId);
  406 + if (StringUtils.isBlank(lineVo.getItemId())) {
  407 + lineVo.setItemId(oldLine.getItemId());
  408 + }
  409 + salesmanQuotationLineService.update(lineVo);
  410 + updateLineEstimatedLoss(lineVo.getId(), estimatedLoss);
  411 + } else {
  412 + CreateSalesmanQuotationLineVo createLineVo = new CreateSalesmanQuotationLineVo();
  413 + createLineVo.setQuotationId(quotationId);
  414 + createLineVo.setProductId(lineVo.getProductId());
  415 + createLineVo.setMaterialType(lineVo.getMaterialType());
  416 + createLineVo.setQuantity(lineVo.getQuantity());
  417 + createLineVo.setPurchasePrice(lineVo.getPurchasePrice());
  418 + createLineVo.setApplicationAttrition(lineVo.getApplicationAttrition());
  419 + createLineVo.setItemId(StringUtils.defaultIfBlank(lineVo.getItemId(), IdUtil.getId()));
  420 + String lineId = salesmanQuotationLineService.create(createLineVo);
  421 + updateLineEstimatedLoss(lineId, estimatedLoss);
  422 + existIdList.add(lineId);
  423 + }
  424 + }
  425 +
  426 + List<SalesmanQuotationLine> safeOldLineList = oldLineList == null ? Collections.emptyList() : oldLineList;
  427 + List<String> needDeleteIdList = safeOldLineList.stream()
  428 + .map(SalesmanQuotationLine::getId)
  429 + .filter(oldLineId -> !existIdList.contains(oldLineId))
  430 + .collect(Collectors.toList());
  431 + if (CollectionUtil.isNotEmpty(needDeleteIdList)) {
  432 + salesmanQuotationLineService.removeByIds(needDeleteIdList);
  433 + }
  434 + }
  435 +
  436 + /**
  437 + * 更新预计损耗
  438 + *
  439 + * @param lineId 明细ID
  440 + * @param estimatedLoss 预计损耗
  441 + */
  442 + private void updateLineEstimatedLoss(String lineId, BigDecimal estimatedLoss) {
  443 + SalesmanQuotationLine updateLine = new SalesmanQuotationLine();
  444 + updateLine.setId(lineId);
  445 + updateLine.setEstimatedLoss(estimatedLoss);
  446 + salesmanQuotationLineService.updateById(updateLine);
  447 + }
  448 +
  449 + /**
  450 + * 计算数量合计
  451 + *
  452 + * @param lineList 明细列表
  453 + * @return 数量合计
  454 + */
  455 + private BigDecimal calculateTotalQuantity(List<? extends CreateSalesmanQuotationLineVo> lineList) {
  456 + BigDecimal totalQuantity = BigDecimal.ZERO;
  457 + for (CreateSalesmanQuotationLineVo lineVo : lineList) {
  458 + totalQuantity = totalQuantity.add(lineVo.getQuantity());
  459 + }
  460 + return totalQuantity.setScale(1, RoundingMode.HALF_UP);
  461 + }
  462 +
  463 + /**
  464 + * 计算预计损耗
  465 + *
  466 + * @param purchasePrice 采购价
  467 + * @param applicationAttrition 申请损耗
  468 + * @param fixedAttrition 固定损耗率
  469 + * @param priced 是否为点价
  470 + * @return 预计损耗
  471 + */
  472 + private BigDecimal calculateEstimatedLoss(BigDecimal purchasePrice, BigDecimal applicationAttrition,
  473 + BigDecimal fixedAttrition, Boolean priced) {
  474 + if (!Boolean.TRUE.equals(priced) || purchasePrice == null) {
  475 + return null;
  476 + }
  477 +
  478 + BigDecimal useRate = applicationAttrition != null ? applicationAttrition : fixedAttrition;
  479 + if (useRate == null) {
  480 + return null;
  481 + }
  482 +
  483 + return purchasePrice.multiply(useRate)
  484 + .divide(new BigDecimal("100"), 10, RoundingMode.HALF_UP);
  485 + }
  486 +
  487 + /**
  488 + * 查询必填品种映射
  489 + *
  490 + * @param productIds 品种ID集合
  491 + * @return 品种映射
  492 + */
  493 + private Map<String, BreedRelationship> getBreedMap(List<String> productIds) {
  494 + if (CollectionUtil.isEmpty(productIds)) {
  495 + throw new DefaultClientException("报价明细不能为空!");
  496 + }
  497 + return getBreedMapByOptionalIds(productIds);
  498 + }
  499 +
  500 + /**
  501 + * 查询可选品种映射
  502 + *
  503 + * @param productIds 品种ID集合
  504 + * @return 品种映射
  505 + */
  506 + private Map<String, BreedRelationship> getBreedMapByOptionalIds(List<String> productIds) {
  507 + if (CollectionUtil.isEmpty(productIds)) {
  508 + return Collections.emptyMap();
  509 + }
  510 +
  511 + LambdaQueryWrapper<BreedRelationship> queryWrapper = Wrappers.lambdaQuery(BreedRelationship.class)
  512 + .in(BreedRelationship::getId, productIds);
  513 + List<BreedRelationship> breedRelationshipList = breedRelationshipService.list(queryWrapper);
  514 + Map<String, BreedRelationship> breedMap = CollectionUtil.isEmpty(breedRelationshipList)
  515 + ? Collections.emptyMap()
  516 + : breedRelationshipList.stream().collect(Collectors.toMap(BreedRelationship::getId, v -> v));
  517 + for (String productId : productIds) {
  518 + if (!breedMap.containsKey(productId)) {
  519 + throw new DefaultClientException("存在无效的品种,请重新选择!");
  520 + }
  521 + }
  522 + return breedMap;
  523 + }
  524 +
  525 + /**
  526 + * 获取料质状况字段值
  527 + *
  528 + * @param enabled 是否启用
  529 + * @param value 字段值
  530 + * @return 最终字段值
  531 + */
  532 + private String normalizeMaterialText(Boolean enabled, String value) {
  533 + if (!Boolean.TRUE.equals(enabled)) {
  534 + return null;
  535 + }
  536 + return StringUtils.trimToNull(value);
  537 + }
  538 +
  539 + /**
  540 + * 查询当前用户
  541 + *
  542 + * @return 当前用户
  543 + */
  544 + private SysUser getCurrentUser() {
  545 + String currentUserId = SecurityUtil.getCurrentUser().getId();
  546 + SysUser currentUser = sysUserService.findById(currentUserId);
  547 + if (currentUser == null) {
  548 + throw new DefaultClientException("当前用户不存在!");
  549 + }
  550 + return currentUser;
  551 + }
  552 +
  553 + /**
  554 + * 查询供应商
  555 + *
  556 + * @param supplierId 供应商ID
  557 + * @return 供应商信息
  558 + */
  559 + private ProcurementDomesticCustomerCredit getSupplierOrThrow(String supplierId) {
  560 + ProcurementDomesticCustomerCredit supplier = procurementDomesticCustomerCreditService.findById(supplierId);
  561 + if (supplier == null) {
  562 + throw new DefaultClientException("内贸资信不存在!");
  563 + }
  564 + if (!"PASS".equals(supplier.getStatus())) {
  565 + throw new DefaultClientException("该内贸资信未审核通过,不允许报价!");
  566 + }
  567 + if (Boolean.TRUE.equals(supplier.getFreeze())) {
  568 + throw new DefaultClientException("该内贸资信已冻结,不允许报价!");
  569 + }
  570 + if (StringUtils.isBlank(supplier.getPurchaseDepartment()) || StringUtils.isBlank(supplier.getRegion())) {
  571 + throw new DefaultClientException("该内贸资信缺少采购处或区域信息!");
  572 + }
  573 + return supplier;
  574 + }
  575 +
  576 + @Override
  577 + public String generateCode() {
  578 + return doGenerateCode();
  579 + }
  580 +
  581 + /**
  582 + * 生成编号
  583 + *
  584 + * @return 编号
  585 + */
  586 + private String doGenerateCode() {
  587 + LocalDateTime now = LocalDateTime.now();
  588 + String monthPrefix = CODE_PREFIX + now.format(DateTimeFormatter.ofPattern("yyMM"));
  589 + String maxCode = getBaseMapper().getMaxCodeByMonth(monthPrefix);
  590 + int seq = 1;
  591 + if (StringUtils.isNotBlank(maxCode) && maxCode.length() >= 4) {
  592 + seq = Integer.parseInt(maxCode.substring(maxCode.length() - 4)) + 1;
  593 + }
  594 + return CODE_PREFIX + now.format(DateTimeFormatter.ofPattern("yyMMdd")) + String.format("%04d", seq);
  595 + }
  596 +
  597 + private void checkCodeUnique(String code) {
  598 + if (StringUtils.isBlank(code)) {
  599 + throw new DefaultClientException("编号不能为空!");
  600 + }
  601 +
  602 + LambdaQueryWrapper<SalesmanQuotation> wrapper = Wrappers.lambdaQuery(SalesmanQuotation.class)
  603 + .eq(SalesmanQuotation::getCode, code);
  604 + if (getBaseMapper().selectCount(wrapper) > 0) {
  605 + throw new DefaultClientException("编号已存在,请重新获取!");
  606 + }
  607 + }
  608 +
  609 + /**
  610 + * 清理缓存
  611 + *
  612 + * @param key 缓存键
  613 + */
  614 + @Override
  615 + public void cleanCacheByKey(Serializable key) {
  616 + }
  617 +}
  1 +package com.lframework.xingyun.sc.procurement.mappers.quotation;
  2 +
  3 +import com.lframework.starter.web.core.mapper.BaseMapper;
  4 +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine;
  5 +import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo;
  6 +import java.util.List;
  7 +import org.apache.ibatis.annotations.Param;
  8 +
  9 +/**
  10 + * 业务员报价明细 Mapper
  11 + */
  12 +public interface SalesmanQuotationLineMapper extends BaseMapper<SalesmanQuotationLine> {
  13 +
  14 + /**
  15 + * 查询列表
  16 + *
  17 + * @param vo 查询条件
  18 + * @return 明细列表
  19 + */
  20 + List<SalesmanQuotationLine> query(@Param("vo") QuerySalesmanQuotationLineVo vo);
  21 +}
  1 +package com.lframework.xingyun.sc.procurement.mappers.quotation;
  2 +
  3 +import com.lframework.starter.web.core.annotations.permission.DataPermission;
  4 +import com.lframework.starter.web.core.annotations.permission.DataPermissions;
  5 +import com.lframework.starter.web.core.mapper.BaseMapper;
  6 +import com.lframework.starter.web.inner.components.permission.OrderDataPermissionDataPermissionType;
  7 +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotation;
  8 +import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationVo;
  9 +import java.util.List;
  10 +import org.apache.ibatis.annotations.Param;
  11 +
  12 +/**
  13 + * 业务员报价 Mapper
  14 + */
  15 +public interface SalesmanQuotationMapper extends BaseMapper<SalesmanQuotation> {
  16 +
  17 + /**
  18 + * 查询列表
  19 + *
  20 + * @param vo 查询条件
  21 + * @return 业务员报价列表
  22 + */
  23 + @DataPermissions(type = OrderDataPermissionDataPermissionType.class, value = {
  24 + @DataPermission(template = "order", alias = "tb")
  25 + })
  26 + List<SalesmanQuotation> query(@Param("vo") QuerySalesmanQuotationVo vo);
  27 +
  28 + /**
  29 + * 根据ID查询
  30 + *
  31 + * @param id 主键ID
  32 + * @return 业务员报价
  33 + */
  34 + SalesmanQuotation findById(@Param("id") String id);
  35 +
  36 + /**
  37 + * 查询月内最大编号
  38 + *
  39 + * @param monthPrefix 月前缀
  40 + * @return 最大编号
  41 + */
  42 + String getMaxCodeByMonth(@Param("monthPrefix") String monthPrefix);
  43 +}
  1 +package com.lframework.xingyun.sc.procurement.service.quotation;
  2 +
  3 +import com.lframework.starter.web.core.service.BaseMpService;
  4 +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine;
  5 +import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationLineVo;
  6 +import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationLineVo;
  7 +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationLineVo;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * 业务员报价明细 Service
  12 + */
  13 +public interface SalesmanQuotationLineService extends BaseMpService<SalesmanQuotationLine> {
  14 +
  15 + /**
  16 + * 查询列表
  17 + *
  18 + * @param vo 查询条件
  19 + * @return 明细列表
  20 + */
  21 + List<SalesmanQuotationLine> query(QuerySalesmanQuotationLineVo vo);
  22 +
  23 + /**
  24 + * 根据ID查询
  25 + *
  26 + * @param id 主键ID
  27 + * @return 明细信息
  28 + */
  29 + SalesmanQuotationLine findById(String id);
  30 +
  31 + /**
  32 + * 创建
  33 + *
  34 + * @param vo 创建参数
  35 + * @return 主键ID
  36 + */
  37 + String create(CreateSalesmanQuotationLineVo vo);
  38 +
  39 + /**
  40 + * 修改
  41 + *
  42 + * @param vo 修改参数
  43 + */
  44 + void update(UpdateSalesmanQuotationLineVo vo);
  45 +}
  1 +package com.lframework.xingyun.sc.procurement.service.quotation;
  2 +
  3 +import com.lframework.starter.web.core.components.resp.PageResult;
  4 +import com.lframework.starter.web.core.service.BaseMpService;
  5 +import com.lframework.xingyun.sc.procurement.entity.SalesmanQuotation;
  6 +import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSalesmanQuotationVo;
  7 +import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySalesmanQuotationVo;
  8 +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSalesmanQuotationVo;
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * 业务员报价 Service
  13 + */
  14 +public interface SalesmanQuotationService extends BaseMpService<SalesmanQuotation> {
  15 +
  16 + /**
  17 + * 分页查询
  18 + *
  19 + * @param pageIndex 页码
  20 + * @param pageSize 页大小
  21 + * @param vo 查询条件
  22 + * @return 分页结果
  23 + */
  24 + PageResult<SalesmanQuotation> query(Integer pageIndex, Integer pageSize, QuerySalesmanQuotationVo vo);
  25 +
  26 + /**
  27 + * 查询列表
  28 + *
  29 + * @param vo 查询条件
  30 + * @return 列表
  31 + */
  32 + List<SalesmanQuotation> query(QuerySalesmanQuotationVo vo);
  33 +
  34 + /**
  35 + * 根据ID查询
  36 + *
  37 + * @param id 主键ID
  38 + * @return 业务员报价
  39 + */
  40 + SalesmanQuotation findById(String id);
  41 +
  42 + /**
  43 + * 新增
  44 + *
  45 + * @param vo 新增参数
  46 + * @return 主键ID
  47 + */
  48 + String create(CreateSalesmanQuotationVo vo);
  49 +
  50 + /**
  51 + * 修改
  52 + *
  53 + * @param vo 修改参数
  54 + */
  55 + void update(UpdateSalesmanQuotationVo vo);
  56 +
  57 + /**
  58 + * 生成编号
  59 + *
  60 + * @return 编号
  61 + */
  62 + String generateCode();
  63 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.quotation;
  2 +
  3 +import com.lframework.starter.web.core.vo.BaseVo;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import java.io.Serializable;
  6 +import java.math.BigDecimal;
  7 +import javax.validation.constraints.Digits;
  8 +import javax.validation.constraints.NotBlank;
  9 +import javax.validation.constraints.NotNull;
  10 +import lombok.Data;
  11 +import org.hibernate.validator.constraints.Length;
  12 +
  13 +/**
  14 + * 新增业务员报价明细入参
  15 + */
  16 +@Data
  17 +public class CreateSalesmanQuotationLineVo implements BaseVo, Serializable {
  18 +
  19 + private static final long serialVersionUID = 1L;
  20 +
  21 + /**
  22 + * 业务员报价ID
  23 + */
  24 + @ApiModelProperty("业务员报价ID")
  25 + private String quotationId;
  26 +
  27 + /**
  28 + * 品种ID
  29 + */
  30 + @ApiModelProperty(value = "品种ID", required = true)
  31 + @NotBlank(message = "品种不能为空!")
  32 + private String productId;
  33 +
  34 + /**
  35 + * 料型
  36 + */
  37 + @ApiModelProperty("料型")
  38 + @Length(max = 200, message = "料型最多允许200个字符!")
  39 + private String materialType;
  40 +
  41 + /**
  42 + * 数量
  43 + */
  44 + @ApiModelProperty(value = "数量", required = true)
  45 + @NotNull(message = "数量不能为空!")
  46 + @Digits(integer = 14, fraction = 5, message = "数量最多支持14位整数和5位小数!")
  47 + private BigDecimal quantity;
  48 +
  49 + /**
  50 + * 采购价
  51 + */
  52 + @ApiModelProperty("采购价")
  53 + @Digits(integer = 14, fraction = 10, message = "采购价最多支持14位整数和10位小数!")
  54 + private BigDecimal purchasePrice;
  55 +
  56 + /**
  57 + * 申请损耗
  58 + */
  59 + @ApiModelProperty("申请损耗")
  60 + @Digits(integer = 8, fraction = 10, message = "申请损耗最多支持8位整数和10位小数!")
  61 + private BigDecimal applicationAttrition;
  62 +
  63 + /**
  64 + * 前端行标识
  65 + */
  66 + @ApiModelProperty("前端行标识")
  67 + private String itemId;
  68 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.quotation;
  2 +
  3 +import com.lframework.starter.web.core.vo.BaseVo;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import java.io.Serializable;
  6 +import java.math.BigDecimal;
  7 +import java.time.LocalDate;
  8 +import java.util.List;
  9 +import javax.validation.Valid;
  10 +import javax.validation.constraints.Digits;
  11 +import javax.validation.constraints.NotBlank;
  12 +import javax.validation.constraints.NotEmpty;
  13 +import javax.validation.constraints.NotNull;
  14 +import lombok.Data;
  15 +import org.hibernate.validator.constraints.Length;
  16 +
  17 +/**
  18 + * 新增业务员报价入参
  19 + */
  20 +@Data
  21 +public class CreateSalesmanQuotationVo implements BaseVo, Serializable {
  22 +
  23 + private static final long serialVersionUID = 1L;
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @ApiModelProperty(value = "编号", required = true)
  29 + @NotBlank(message = "编号不能为空!")
  30 + @Length(max = 20, message = "编号最多允许20个字符!")
  31 + private String code;
  32 +
  33 + /**
  34 + * 内贸资信ID
  35 + */
  36 + @ApiModelProperty(value = "内贸资信ID", required = true)
  37 + @NotBlank(message = "供应商不能为空!")
  38 + private String supplierId;
  39 +
  40 + /**
  41 + * 报价时效
  42 + */
  43 + @ApiModelProperty(value = "报价时效", required = true)
  44 + @NotBlank(message = "报价时效不能为空!")
  45 + @Length(max = 200, message = "报价时效最多允许200个字符!")
  46 + private String validityPeriod;
  47 +
  48 + /**
  49 + * 是否长单操作
  50 + */
  51 + @ApiModelProperty(value = "是否长单操作", required = true)
  52 + @NotNull(message = "是否长单操作不能为空!")
  53 + private Boolean longTermOperation;
  54 +
  55 + /**
  56 + * 是否终端客户
  57 + */
  58 + @ApiModelProperty(value = "是否终端客户", required = true)
  59 + @NotNull(message = "是否终端客户不能为空!")
  60 + private Boolean terminalCustomer;
  61 +
  62 + /**
  63 + * 是否为点价
  64 + */
  65 + @ApiModelProperty(value = "是否为点价", required = true)
  66 + @NotNull(message = "是否为点价不能为空!")
  67 + private Boolean priced;
  68 +
  69 + /**
  70 + * 点价截止日期
  71 + */
  72 + @ApiModelProperty("点价截止日期")
  73 + private LocalDate pricingDeadline;
  74 +
  75 + /**
  76 + * 其他费用凭票到厂另行结算
  77 + */
  78 + @ApiModelProperty(value = "其他费用凭票到厂另行结算", required = true)
  79 + @NotNull(message = "其他费用凭票到厂另行结算不能为空!")
  80 + private Boolean otherExpenseSettlement;
  81 +
  82 + /**
  83 + * 交提货方式
  84 + */
  85 + @ApiModelProperty(value = "交提货方式", required = true)
  86 + @NotBlank(message = "交提货方式不能为空!")
  87 + @Length(max = 50, message = "交提货方式最多允许50个字符!")
  88 + private String deliveryMode;
  89 +
  90 + /**
  91 + * 是否通货买断
  92 + */
  93 + @ApiModelProperty(value = "是否通货买断", required = true)
  94 + @NotNull(message = "是否通货买断不能为空!")
  95 + private Boolean commodityBuyout;
  96 +
  97 + /**
  98 + * 是否质量买断
  99 + */
  100 + @ApiModelProperty(value = "是否质量买断", required = true)
  101 + @NotNull(message = "是否质量买断不能为空!")
  102 + private Boolean qualityBuyout;
  103 +
  104 + /**
  105 + * 是否数量买断
  106 + */
  107 + @ApiModelProperty(value = "是否数量买断", required = true)
  108 + @NotNull(message = "是否数量买断不能为空!")
  109 + private Boolean quantityBuyout;
  110 +
  111 + /**
  112 + * 是否送货上门
  113 + */
  114 + @ApiModelProperty(value = "是否送货上门", required = true)
  115 + @NotNull(message = "是否送货上门不能为空!")
  116 + private Boolean doorDelivery;
  117 +
  118 + /**
  119 + * 装车费
  120 + */
  121 + @ApiModelProperty("装车费")
  122 + @Digits(integer = 14, fraction = 5, message = "装车费最多支持14位整数和5位小数!")
  123 + private BigDecimal loadingFee;
  124 +
  125 + /**
  126 + * 开票品种
  127 + */
  128 + @ApiModelProperty(value = "开票品种", required = true)
  129 + @NotBlank(message = "开票品种不能为空!")
  130 + @Length(max = 200, message = "开票品种最多允许200个字符!")
  131 + private String invoiceProductName;
  132 +
  133 + /**
  134 + * 交货日期
  135 + */
  136 + @ApiModelProperty(value = "交货日期", required = true)
  137 + @NotNull(message = "交货日期不能为空!")
  138 + private LocalDate deliveryDate;
  139 +
  140 + /**
  141 + * 结算方式
  142 + */
  143 + @ApiModelProperty(value = "结算方式", required = true)
  144 + @NotBlank(message = "结算方式不能为空!")
  145 + @Length(max = 200, message = "结算方式最多允许200个字符!")
  146 + private String settlementMethod;
  147 +
  148 + /**
  149 + * 结算比例
  150 + */
  151 + @ApiModelProperty(value = "结算比例(%)", required = true)
  152 + @NotNull(message = "结算比例不能为空!")
  153 + @Digits(integer = 8, fraction = 5, message = "结算比例最多支持8位整数和5位小数!")
  154 + private BigDecimal settlementRatio;
  155 +
  156 + /**
  157 + * 是否启用料质状况
  158 + */
  159 + @ApiModelProperty(value = "是否启用料质状况", required = true)
  160 + @NotNull(message = "是否启用料质状况不能为空!")
  161 + private Boolean materialConditionEnabled;
  162 +
  163 + /**
  164 + * 铜米
  165 + */
  166 + @ApiModelProperty("铜米")
  167 + @Length(max = 500, message = "铜米内容最多允许500个字符!")
  168 + private String materialConditionCopperRice;
  169 +
  170 + /**
  171 + * 光亮铜
  172 + */
  173 + @ApiModelProperty("光亮铜")
  174 + @Length(max = 500, message = "光亮铜内容最多允许500个字符!")
  175 + private String materialConditionBrightCopper;
  176 +
  177 + /**
  178 + * 一特
  179 + */
  180 + @ApiModelProperty("一特")
  181 + @Length(max = 500, message = "一特内容最多允许500个字符!")
  182 + private String materialConditionFirstClass;
  183 +
  184 + /**
  185 + * 二特
  186 + */
  187 + @ApiModelProperty("二特")
  188 + @Length(max = 500, message = "二特内容最多允许500个字符!")
  189 + private String materialConditionSecondClass;
  190 +
  191 + /**
  192 + * 镀锡紫
  193 + */
  194 + @ApiModelProperty("镀锡紫")
  195 + @Length(max = 500, message = "镀锡紫内容最多允许500个字符!")
  196 + private String materialConditionTinCoated;
  197 +
  198 + /**
  199 + * 角料
  200 + */
  201 + @ApiModelProperty("角料")
  202 + @Length(max = 500, message = "角料内容最多允许500个字符!")
  203 + private String materialConditionScrap;
  204 +
  205 + /**
  206 + * 镀白黄
  207 + */
  208 + @ApiModelProperty("镀白黄")
  209 + @Length(max = 500, message = "镀白黄内容最多允许500个字符!")
  210 + private String materialConditionWhiteYellow;
  211 +
  212 + /**
  213 + * 磷铜
  214 + */
  215 + @ApiModelProperty("磷铜")
  216 + @Length(max = 500, message = "磷铜内容最多允许500个字符!")
  217 + private String materialConditionPhosphorCopper;
  218 +
  219 + /**
  220 + * 报价明细列表
  221 + */
  222 + @ApiModelProperty(value = "报价明细列表", required = true)
  223 + @Valid
  224 + @NotEmpty(message = "报价明细不能为空!")
  225 + private List<CreateSalesmanQuotationLineVo> quotationLineList;
  226 +
  227 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.quotation;
  2 +
  3 +import com.lframework.starter.web.core.vo.BaseVo;
  4 +import java.io.Serializable;
  5 +import lombok.Data;
  6 +
  7 +/**
  8 + * 查询业务员报价明细入参
  9 + */
  10 +@Data
  11 +public class QuerySalesmanQuotationLineVo implements BaseVo, Serializable {
  12 +
  13 + private static final long serialVersionUID = 1L;
  14 +
  15 + /**
  16 + * 业务员报价ID
  17 + */
  18 + private String quotationId;
  19 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.quotation;
  2 +
  3 +import com.lframework.starter.web.core.vo.BaseVo;
  4 +import com.lframework.starter.web.core.vo.PageVo;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import java.io.Serializable;
  7 +import java.time.LocalDate;
  8 +import lombok.Data;
  9 +
  10 +/**
  11 + * 查询业务员报价入参
  12 + */
  13 +@Data
  14 +public class QuerySalesmanQuotationVo extends PageVo implements BaseVo, Serializable {
  15 +
  16 + private static final long serialVersionUID = 1L;
  17 +
  18 + /**
  19 + * 编号
  20 + */
  21 + @ApiModelProperty("编号")
  22 + private String code;
  23 +
  24 + /**
  25 + * 供应商名称
  26 + */
  27 + @ApiModelProperty("供应商名称")
  28 + private String supplierName;
  29 +
  30 + /**
  31 + * 报价人
  32 + */
  33 + @ApiModelProperty("报价人")
  34 + private String quoterName;
  35 +
  36 + /**
  37 + * 采购处
  38 + */
  39 + @ApiModelProperty("采购处")
  40 + private String purchaseDepartment;
  41 +
  42 + /**
  43 + * 区域
  44 + */
  45 + @ApiModelProperty("区域")
  46 + private String region;
  47 +
  48 + /**
  49 + * 是否为点价
  50 + */
  51 + @ApiModelProperty("是否为点价")
  52 + private Boolean priced;
  53 +
  54 + /**
  55 + * 报价时间开始
  56 + */
  57 + @ApiModelProperty("报价时间开始")
  58 + private LocalDate quoteDateStart;
  59 +
  60 + /**
  61 + * 报价时间结束
  62 + */
  63 + @ApiModelProperty("报价时间结束")
  64 + private LocalDate quoteDateEnd;
  65 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.quotation;
  2 +
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * 修改业务员报价明细入参
  8 + */
  9 +@Data
  10 +public class UpdateSalesmanQuotationLineVo extends CreateSalesmanQuotationLineVo {
  11 +
  12 + private static final long serialVersionUID = 1L;
  13 +
  14 + /**
  15 + * ID
  16 + */
  17 + @ApiModelProperty("ID")
  18 + private String id;
  19 +
  20 +}
  1 +package com.lframework.xingyun.sc.procurement.vo.quotation;
  2 +
  3 +import com.lframework.starter.web.core.vo.BaseVo;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import java.io.Serializable;
  6 +import java.math.BigDecimal;
  7 +import java.time.LocalDate;
  8 +import java.util.List;
  9 +import javax.validation.Valid;
  10 +import javax.validation.constraints.Digits;
  11 +import javax.validation.constraints.NotBlank;
  12 +import javax.validation.constraints.NotEmpty;
  13 +import javax.validation.constraints.NotNull;
  14 +import lombok.Data;
  15 +import org.hibernate.validator.constraints.Length;
  16 +
  17 +/**
  18 + * 修改业务员报价入参
  19 + */
  20 +@Data
  21 +public class UpdateSalesmanQuotationVo implements BaseVo, Serializable {
  22 +
  23 + private static final long serialVersionUID = 1L;
  24 +
  25 + /**
  26 + * ID
  27 + */
  28 + @ApiModelProperty(value = "ID", required = true)
  29 + @NotBlank(message = "id不能为空!")
  30 + private String id;
  31 +
  32 + /**
  33 + * 内贸资信ID
  34 + */
  35 + @ApiModelProperty(value = "内贸资信ID", required = true)
  36 + @NotBlank(message = "供应商不能为空!")
  37 + private String supplierId;
  38 +
  39 + /**
  40 + * 报价时效
  41 + */
  42 + @ApiModelProperty(value = "报价时效", required = true)
  43 + @NotBlank(message = "报价时效不能为空!")
  44 + @Length(max = 200, message = "报价时效最多允许200个字符!")
  45 + private String validityPeriod;
  46 +
  47 + /**
  48 + * 是否长单操作
  49 + */
  50 + @ApiModelProperty(value = "是否长单操作", required = true)
  51 + @NotNull(message = "是否长单操作不能为空!")
  52 + private Boolean longTermOperation;
  53 +
  54 + /**
  55 + * 是否终端客户
  56 + */
  57 + @ApiModelProperty(value = "是否终端客户", required = true)
  58 + @NotNull(message = "是否终端客户不能为空!")
  59 + private Boolean terminalCustomer;
  60 +
  61 + /**
  62 + * 是否为点价
  63 + */
  64 + @ApiModelProperty(value = "是否为点价", required = true)
  65 + @NotNull(message = "是否为点价不能为空!")
  66 + private Boolean priced;
  67 +
  68 + /**
  69 + * 点价截止日期
  70 + */
  71 + @ApiModelProperty("点价截止日期")
  72 + private LocalDate pricingDeadline;
  73 +
  74 + /**
  75 + * 其他费用凭票到厂另行结算
  76 + */
  77 + @ApiModelProperty(value = "其他费用凭票到厂另行结算", required = true)
  78 + @NotNull(message = "其他费用凭票到厂另行结算不能为空!")
  79 + private Boolean otherExpenseSettlement;
  80 +
  81 + /**
  82 + * 交提货方式
  83 + */
  84 + @ApiModelProperty(value = "交提货方式", required = true)
  85 + @NotBlank(message = "交提货方式不能为空!")
  86 + @Length(max = 50, message = "交提货方式最多允许50个字符!")
  87 + private String deliveryMode;
  88 +
  89 + /**
  90 + * 是否通货买断
  91 + */
  92 + @ApiModelProperty(value = "是否通货买断", required = true)
  93 + @NotNull(message = "是否通货买断不能为空!")
  94 + private Boolean commodityBuyout;
  95 +
  96 + /**
  97 + * 是否质量买断
  98 + */
  99 + @ApiModelProperty(value = "是否质量买断", required = true)
  100 + @NotNull(message = "是否质量买断不能为空!")
  101 + private Boolean qualityBuyout;
  102 +
  103 + /**
  104 + * 是否数量买断
  105 + */
  106 + @ApiModelProperty(value = "是否数量买断", required = true)
  107 + @NotNull(message = "是否数量买断不能为空!")
  108 + private Boolean quantityBuyout;
  109 +
  110 + /**
  111 + * 是否送货上门
  112 + */
  113 + @ApiModelProperty(value = "是否送货上门", required = true)
  114 + @NotNull(message = "是否送货上门不能为空!")
  115 + private Boolean doorDelivery;
  116 +
  117 + /**
  118 + * 装车费
  119 + */
  120 + @ApiModelProperty("装车费")
  121 + @Digits(integer = 14, fraction = 5, message = "装车费最多支持14位整数和5位小数!")
  122 + private BigDecimal loadingFee;
  123 +
  124 + /**
  125 + * 开票品种
  126 + */
  127 + @ApiModelProperty(value = "开票品种", required = true)
  128 + @NotBlank(message = "开票品种不能为空!")
  129 + @Length(max = 200, message = "开票品种最多允许200个字符!")
  130 + private String invoiceProductName;
  131 +
  132 + /**
  133 + * 交货日期
  134 + */
  135 + @ApiModelProperty(value = "交货日期", required = true)
  136 + @NotNull(message = "交货日期不能为空!")
  137 + private LocalDate deliveryDate;
  138 +
  139 + /**
  140 + * 结算方式
  141 + */
  142 + @ApiModelProperty(value = "结算方式", required = true)
  143 + @NotBlank(message = "结算方式不能为空!")
  144 + @Length(max = 200, message = "结算方式最多允许200个字符!")
  145 + private String settlementMethod;
  146 +
  147 + /**
  148 + * 结算比例
  149 + */
  150 + @ApiModelProperty(value = "结算比例(%)", required = true)
  151 + @NotNull(message = "结算比例不能为空!")
  152 + @Digits(integer = 8, fraction = 5, message = "结算比例最多支持8位整数和5位小数!")
  153 + private BigDecimal settlementRatio;
  154 +
  155 + /**
  156 + * 是否启用料质状况
  157 + */
  158 + @ApiModelProperty(value = "是否启用料质状况", required = true)
  159 + @NotNull(message = "是否启用料质状况不能为空!")
  160 + private Boolean materialConditionEnabled;
  161 +
  162 + /**
  163 + * 铜米
  164 + */
  165 + @ApiModelProperty("铜米")
  166 + @Length(max = 500, message = "铜米内容最多允许500个字符!")
  167 + private String materialConditionCopperRice;
  168 +
  169 + /**
  170 + * 光亮铜
  171 + */
  172 + @ApiModelProperty("光亮铜")
  173 + @Length(max = 500, message = "光亮铜内容最多允许500个字符!")
  174 + private String materialConditionBrightCopper;
  175 +
  176 + /**
  177 + * 一特
  178 + */
  179 + @ApiModelProperty("一特")
  180 + @Length(max = 500, message = "一特内容最多允许500个字符!")
  181 + private String materialConditionFirstClass;
  182 +
  183 + /**
  184 + * 二特
  185 + */
  186 + @ApiModelProperty("二特")
  187 + @Length(max = 500, message = "二特内容最多允许500个字符!")
  188 + private String materialConditionSecondClass;
  189 +
  190 + /**
  191 + * 镀锡紫
  192 + */
  193 + @ApiModelProperty("镀锡紫")
  194 + @Length(max = 500, message = "镀锡紫内容最多允许500个字符!")
  195 + private String materialConditionTinCoated;
  196 +
  197 + /**
  198 + * 角料
  199 + */
  200 + @ApiModelProperty("角料")
  201 + @Length(max = 500, message = "角料内容最多允许500个字符!")
  202 + private String materialConditionScrap;
  203 +
  204 + /**
  205 + * 镀白黄
  206 + */
  207 + @ApiModelProperty("镀白黄")
  208 + @Length(max = 500, message = "镀白黄内容最多允许500个字符!")
  209 + private String materialConditionWhiteYellow;
  210 +
  211 + /**
  212 + * 磷铜
  213 + */
  214 + @ApiModelProperty("磷铜")
  215 + @Length(max = 500, message = "磷铜内容最多允许500个字符!")
  216 + private String materialConditionPhosphorCopper;
  217 +
  218 + /**
  219 + * 报价明细列表
  220 + */
  221 + @ApiModelProperty(value = "报价明细列表", required = true)
  222 + @Valid
  223 + @NotEmpty(message = "报价明细不能为空!")
  224 + private List<UpdateSalesmanQuotationLineVo> quotationLineList;
  225 +
  226 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="com.lframework.xingyun.sc.procurement.mappers.quotation.SalesmanQuotationLineMapper">
  4 +
  5 + <resultMap id="SalesmanQuotationLine" type="com.lframework.xingyun.sc.procurement.entity.SalesmanQuotationLine">
  6 + <id column="id" property="id"/>
  7 + <result column="quotation_id" property="quotationId"/>
  8 + <result column="product_id" property="productId"/>
  9 + <result column="product_name" property="productName"/>
  10 + <result column="product_code" property="productCode"/>
  11 + <result column="product_type" property="productType"/>
  12 + <result column="fixed_attrition_rate" property="fixedAttritionRate"/>
  13 + <result column="material_type" property="materialType"/>
  14 + <result column="quantity" property="quantity"/>
  15 + <result column="purchase_price" property="purchasePrice"/>
  16 + <result column="estimated_loss" property="estimatedLoss"/>
  17 + <result column="application_attrition" property="applicationAttrition"/>
  18 + <result column="item_id" property="itemId"/>
  19 + <result column="create_by_id" property="createById"/>
  20 + <result column="create_by" property="createBy"/>
  21 + <result column="update_by_id" property="updateById"/>
  22 + <result column="update_by" property="updateBy"/>
  23 + <result column="create_time" property="createTime"/>
  24 + <result column="update_time" property="updateTime"/>
  25 + </resultMap>
  26 +
  27 + <sql id="SalesmanQuotationLineSql">
  28 + SELECT
  29 + tb.id,
  30 + tb.quotation_id,
  31 + tb.product_id,
  32 + br.product_name,
  33 + br.code AS product_code,
  34 + br.type AS product_type,
  35 + br.attrition_rate AS fixed_attrition_rate,
  36 + tb.material_type,
  37 + tb.quantity,
  38 + tb.purchase_price,
  39 + tb.estimated_loss,
  40 + tb.application_attrition,
  41 + tb.item_id,
  42 + tb.create_by_id,
  43 + tb.create_by,
  44 + tb.update_by_id,
  45 + tb.update_by,
  46 + tb.create_time,
  47 + tb.update_time
  48 + FROM procurement_salesman_quotation_line tb
  49 + LEFT JOIN base_data_breed_relationship br ON br.id = tb.product_id
  50 + </sql>
  51 +
  52 + <select id="query" resultMap="SalesmanQuotationLine">
  53 + <include refid="SalesmanQuotationLineSql"/>
  54 + <where>
  55 + <if test="vo.quotationId != null and vo.quotationId != ''">
  56 + AND tb.quotation_id = #{vo.quotationId}
  57 + </if>
  58 + </where>
  59 + ORDER BY tb.create_time ASC
  60 + </select>
  61 +</mapper>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="com.lframework.xingyun.sc.procurement.mappers.quotation.SalesmanQuotationMapper">
  4 +
  5 + <resultMap id="SalesmanQuotation" type="com.lframework.xingyun.sc.procurement.entity.SalesmanQuotation">
  6 + <id column="id" property="id"/>
  7 + <result column="code" property="code"/>
  8 + <result column="supplier_id" property="supplierId"/>
  9 + <result column="supplier_name" property="supplierName"/>
  10 + <result column="purchase_department" property="purchaseDepartment"/>
  11 + <result column="purchase_department_name" property="purchaseDepartmentName"/>
  12 + <result column="purchase_department_code" property="purchaseDepartmentCode"/>
  13 + <result column="region" property="region"/>
  14 + <result column="region_name" property="regionName"/>
  15 + <result column="quote_time" property="quoteTime"/>
  16 + <result column="validity_period" property="validityPeriod"/>
  17 + <result column="quoter_id" property="quoterId"/>
  18 + <result column="quoter_name" property="quoterName"/>
  19 + <result column="long_term_operation" property="longTermOperation"/>
  20 + <result column="terminal_customer" property="terminalCustomer"/>
  21 + <result column="priced" property="priced"/>
  22 + <result column="pricing_deadline" property="pricingDeadline"/>
  23 + <result column="other_expense_settlement" property="otherExpenseSettlement"/>
  24 + <result column="delivery_mode" property="deliveryMode"/>
  25 + <result column="commodity_buyout" property="commodityBuyout"/>
  26 + <result column="quality_buyout" property="qualityBuyout"/>
  27 + <result column="quantity_buyout" property="quantityBuyout"/>
  28 + <result column="door_delivery" property="doorDelivery"/>
  29 + <result column="loading_fee" property="loadingFee"/>
  30 + <result column="invoice_product_name" property="invoiceProductName"/>
  31 + <result column="delivery_date" property="deliveryDate"/>
  32 + <result column="settlement_method" property="settlementMethod"/>
  33 + <result column="settlement_ratio" property="settlementRatio"/>
  34 + <result column="coordination_reason" property="coordinationReason"/>
  35 + <result column="invoice_type_status" property="invoiceTypeStatus"/>
  36 + <result column="material_condition_enabled" property="materialConditionEnabled"/>
  37 + <result column="material_condition_copper_rice" property="materialConditionCopperRice"/>
  38 + <result column="material_condition_bright_copper" property="materialConditionBrightCopper"/>
  39 + <result column="material_condition_first_class" property="materialConditionFirstClass"/>
  40 + <result column="material_condition_second_class" property="materialConditionSecondClass"/>
  41 + <result column="material_condition_tin_coated" property="materialConditionTinCoated"/>
  42 + <result column="material_condition_scrap" property="materialConditionScrap"/>
  43 + <result column="material_condition_white_yellow" property="materialConditionWhiteYellow"/>
  44 + <result column="material_condition_phosphor_copper" property="materialConditionPhosphorCopper"/>
  45 + <result column="total_quantity" property="totalQuantity"/>
  46 + <result column="create_by_id" property="createById"/>
  47 + <result column="create_by" property="createBy"/>
  48 + <result column="update_by_id" property="updateById"/>
  49 + <result column="update_by" property="updateBy"/>
  50 + <result column="create_time" property="createTime"/>
  51 + <result column="update_time" property="updateTime"/>
  52 + </resultMap>
  53 +
  54 + <sql id="SalesmanQuotationSql">
  55 + SELECT
  56 + tb.id,
  57 + tb.code,
  58 + tb.supplier_id,
  59 + pdc.unit_name AS supplier_name,
  60 + tb.purchase_department,
  61 + sd.name AS purchase_department_name,
  62 + sd.code AS purchase_department_code,
  63 + tb.region,
  64 + sd1.name AS region_name,
  65 + tb.quote_time,
  66 + tb.validity_period,
  67 + tb.quoter_id,
  68 + tb.quoter_name,
  69 + tb.long_term_operation,
  70 + tb.terminal_customer,
  71 + tb.priced,
  72 + tb.pricing_deadline,
  73 + tb.other_expense_settlement,
  74 + tb.delivery_mode,
  75 + tb.commodity_buyout,
  76 + tb.quality_buyout,
  77 + tb.quantity_buyout,
  78 + tb.door_delivery,
  79 + tb.loading_fee,
  80 + tb.invoice_product_name,
  81 + tb.delivery_date,
  82 + tb.settlement_method,
  83 + tb.settlement_ratio,
  84 + tb.coordination_reason,
  85 + tb.invoice_type_status,
  86 + tb.material_condition_enabled,
  87 + tb.material_condition_copper_rice,
  88 + tb.material_condition_bright_copper,
  89 + tb.material_condition_first_class,
  90 + tb.material_condition_second_class,
  91 + tb.material_condition_tin_coated,
  92 + tb.material_condition_scrap,
  93 + tb.material_condition_white_yellow,
  94 + tb.material_condition_phosphor_copper,
  95 + tb.total_quantity,
  96 + tb.create_by_id,
  97 + tb.create_by,
  98 + tb.update_by_id,
  99 + tb.update_by,
  100 + tb.create_time,
  101 + tb.update_time
  102 + FROM procurement_salesman_quotation tb
  103 + LEFT JOIN procurement_domestic_customer_credit pdc ON pdc.id = tb.supplier_id
  104 + LEFT JOIN sys_dept sd ON sd.id = tb.purchase_department
  105 + LEFT JOIN sys_dept sd1 ON sd1.id = tb.region
  106 + </sql>
  107 +
  108 + <select id="query" resultMap="SalesmanQuotation">
  109 + <include refid="SalesmanQuotationSql"/>
  110 + <where>
  111 + <if test="vo.code != null and vo.code != ''">
  112 + AND tb.code LIKE CONCAT('%', #{vo.code}, '%')
  113 + </if>
  114 + <if test="vo.supplierName != null and vo.supplierName != ''">
  115 + AND pdc.unit_name LIKE CONCAT('%', #{vo.supplierName}, '%')
  116 + </if>
  117 + <if test="vo.quoterName != null and vo.quoterName != ''">
  118 + AND tb.quoter_name LIKE CONCAT('%', #{vo.quoterName}, '%')
  119 + </if>
  120 + <if test="vo.purchaseDepartment != null and vo.purchaseDepartment != ''">
  121 + AND tb.purchase_department = #{vo.purchaseDepartment}
  122 + </if>
  123 + <if test="vo.region != null and vo.region != ''">
  124 + AND tb.region = #{vo.region}
  125 + </if>
  126 + <if test="vo.priced != null">
  127 + AND tb.priced = #{vo.priced}
  128 + </if>
  129 + <if test="vo.quoteDateStart != null">
  130 + AND DATE(tb.quote_time) <![CDATA[ >= ]]> #{vo.quoteDateStart}
  131 + </if>
  132 + <if test="vo.quoteDateEnd != null">
  133 + AND DATE(tb.quote_time) <![CDATA[ <= ]]> #{vo.quoteDateEnd}
  134 + </if>
  135 + </where>
  136 + ORDER BY tb.create_time DESC
  137 + </select>
  138 +
  139 + <select id="findById" resultMap="SalesmanQuotation">
  140 + <include refid="SalesmanQuotationSql"/>
  141 + WHERE tb.id = #{id}
  142 + </select>
  143 +
  144 + <select id="getMaxCodeByMonth" resultType="java.lang.String">
  145 + SELECT tb.code
  146 + FROM procurement_salesman_quotation tb
  147 + WHERE tb.code LIKE CONCAT(#{monthPrefix}, '%')
  148 + ORDER BY CAST(RIGHT(tb.code, 4) AS UNSIGNED) DESC
  149 + LIMIT 1
  150 + </select>
  151 +</mapper>