Showing
11 changed files
with
609 additions
and
2 deletions
| @@ -1803,3 +1803,28 @@ CREATE TABLE `procurement_supplier_quotation_project` | @@ -1803,3 +1803,28 @@ CREATE TABLE `procurement_supplier_quotation_project` | ||
| 1803 | KEY `idx_psqpj_bid_time` (`bid_time`), | 1803 | KEY `idx_psqpj_bid_time` (`bid_time`), |
| 1804 | KEY `idx_psqpj_create_time` (`create_time`) | 1804 | KEY `idx_psqpj_create_time` (`create_time`) |
| 1805 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='供应商报价项目'; | 1805 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='供应商报价项目'; |
| 1806 | + | ||
| 1807 | +CREATE TABLE `procurement_supplier_quotation_project_quote` | ||
| 1808 | +( | ||
| 1809 | + `id` varchar(32) NOT NULL COMMENT 'ID', | ||
| 1810 | + `project_id` varchar(32) NOT NULL COMMENT '报价项目ID', | ||
| 1811 | + `supplier_id` varchar(32) NOT NULL COMMENT '供应商ID(当前登录用户ID)', | ||
| 1812 | + `supplier_name` varchar(200) NOT NULL COMMENT '供应商名称', | ||
| 1813 | + `quote_time` datetime NOT NULL COMMENT '报价时间(最后一次报价时间)', | ||
| 1814 | + `product_id` varchar(32) NOT NULL COMMENT '品种ID', | ||
| 1815 | + `quantity` decimal(18, 5) NOT NULL COMMENT '数量', | ||
| 1816 | + `price` decimal(18, 10) NOT NULL COMMENT '价格', | ||
| 1817 | + `bid_status` varchar(50) DEFAULT NULL COMMENT '中标状态(中标/未中标/废标)', | ||
| 1818 | + `create_by_id` varchar(32) DEFAULT NULL COMMENT '创建人ID', | ||
| 1819 | + `create_by` varchar(64) DEFAULT NULL COMMENT '创建人', | ||
| 1820 | + `update_by_id` varchar(32) DEFAULT NULL COMMENT '更新人ID', | ||
| 1821 | + `update_by` varchar(64) DEFAULT NULL COMMENT '更新人', | ||
| 1822 | + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 1823 | + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 1824 | + PRIMARY KEY (`id`), | ||
| 1825 | + UNIQUE KEY `uk_psqpjq_project_supplier` (`project_id`, `supplier_id`), | ||
| 1826 | + KEY `idx_psqpjq_project_id` (`project_id`), | ||
| 1827 | + KEY `idx_psqpjq_supplier_id` (`supplier_id`), | ||
| 1828 | + KEY `idx_psqpjq_quote_time` (`quote_time`), | ||
| 1829 | + KEY `idx_psqpjq_create_time` (`create_time`) | ||
| 1830 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='供应商报价项目报价'; |
| 1 | +package com.lframework.xingyun.sc.procurement.controller.quotation; | ||
| 2 | + | ||
| 3 | +import com.lframework.starter.web.core.components.resp.InvokeResult; | ||
| 4 | +import com.lframework.starter.web.core.components.resp.InvokeResultBuilder; | ||
| 5 | +import com.lframework.starter.web.core.controller.DefaultBaseController; | ||
| 6 | +import com.lframework.xingyun.sc.procurement.entity.SupplierQuotationProjectQuote; | ||
| 7 | +import com.lframework.xingyun.sc.procurement.service.quotation.SupplierQuotationProjectQuoteService; | ||
| 8 | +import com.lframework.xingyun.sc.procurement.vo.quotation.SupplierQuotationProjectQuoteVo; | ||
| 9 | +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSupplierQuotationProjectQuoteBidStatusVo; | ||
| 10 | +import io.swagger.annotations.Api; | ||
| 11 | +import io.swagger.annotations.ApiImplicitParam; | ||
| 12 | +import io.swagger.annotations.ApiOperation; | ||
| 13 | +import java.util.List; | ||
| 14 | +import javax.annotation.Resource; | ||
| 15 | +import javax.validation.Valid; | ||
| 16 | +import javax.validation.constraints.NotBlank; | ||
| 17 | +import org.springframework.validation.annotation.Validated; | ||
| 18 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 22 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 23 | +import org.springframework.web.bind.annotation.RestController; | ||
| 24 | + | ||
| 25 | +@Api(tags = "供应商报价项目报价") | ||
| 26 | +@Validated | ||
| 27 | +@RestController | ||
| 28 | +@RequestMapping("/procurement/supplierQuotationProjectQuote") | ||
| 29 | +public class SupplierQuotationProjectQuoteController extends DefaultBaseController { | ||
| 30 | + | ||
| 31 | + @Resource | ||
| 32 | + private SupplierQuotationProjectQuoteService supplierQuotationProjectQuoteService; | ||
| 33 | + | ||
| 34 | + @ApiOperation("供应商报价(同一项目可多次报价,覆盖更新)") | ||
| 35 | + @PostMapping("") | ||
| 36 | + public InvokeResult<Void> quote(@Valid @RequestBody SupplierQuotationProjectQuoteVo vo) { | ||
| 37 | + supplierQuotationProjectQuoteService.quote(vo); | ||
| 38 | + return InvokeResultBuilder.success(); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @ApiOperation("查看我的报价(每项目仅一条)") | ||
| 42 | + @ApiImplicitParam(value = "projectId", name = "projectId", paramType = "query", required = true) | ||
| 43 | + @GetMapping("/my") | ||
| 44 | + public InvokeResult<SupplierQuotationProjectQuote> getMyQuote(@NotBlank(message = "projectId不能为空!") String projectId) { | ||
| 45 | + return InvokeResultBuilder.success(supplierQuotationProjectQuoteService.getMyQuote(projectId)); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @ApiOperation("查看项目供应商报价(发布方/管理方使用)") | ||
| 49 | + @ApiImplicitParam(value = "projectId", name = "projectId", paramType = "query", required = true) | ||
| 50 | + @GetMapping("/listByProject") | ||
| 51 | + public InvokeResult<List<SupplierQuotationProjectQuote>> listByProject(@NotBlank(message = "projectId不能为空!") String projectId) { | ||
| 52 | + return InvokeResultBuilder.success(supplierQuotationProjectQuoteService.listByProject(projectId)); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @ApiOperation("维护中标状态(发布方/管理方使用)") | ||
| 56 | + @PutMapping("/bidStatus") | ||
| 57 | + public InvokeResult<Void> updateBidStatus(@Valid @RequestBody UpdateSupplierQuotationProjectQuoteBidStatusVo vo) { | ||
| 58 | + supplierQuotationProjectQuoteService.updateBidStatus(vo); | ||
| 59 | + return InvokeResultBuilder.success(); | ||
| 60 | + } | ||
| 61 | +} | ||
| 62 | + |
| @@ -7,6 +7,8 @@ import com.lframework.starter.web.core.dto.BaseDto; | @@ -7,6 +7,8 @@ import com.lframework.starter.web.core.dto.BaseDto; | ||
| 7 | import com.lframework.starter.web.core.entity.BaseEntity; | 7 | import com.lframework.starter.web.core.entity.BaseEntity; |
| 8 | import java.math.BigDecimal; | 8 | import java.math.BigDecimal; |
| 9 | import java.time.LocalDateTime; | 9 | import java.time.LocalDateTime; |
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 10 | import lombok.Data; | 12 | import lombok.Data; |
| 11 | 13 | ||
| 12 | @Data | 14 | @Data |
| @@ -85,6 +87,12 @@ public class SupplierQuotationProject extends BaseEntity implements BaseDto { | @@ -85,6 +87,12 @@ public class SupplierQuotationProject extends BaseEntity implements BaseDto { | ||
| 85 | private String status; | 87 | private String status; |
| 86 | 88 | ||
| 87 | /** | 89 | /** |
| 90 | + * 供应商报价 | ||
| 91 | + */ | ||
| 92 | + @TableField(exist = false) | ||
| 93 | + private List<SupplierQuotationProjectQuote> supplierQuotationProjectQuoteList; | ||
| 94 | + | ||
| 95 | + /** | ||
| 88 | * 创建人ID | 96 | * 创建人ID |
| 89 | */ | 97 | */ |
| 90 | @TableField(fill = FieldFill.INSERT) | 98 | @TableField(fill = FieldFill.INSERT) |
| 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 | +@Data | ||
| 13 | +@TableName("procurement_supplier_quotation_project_quote") | ||
| 14 | +public class SupplierQuotationProjectQuote extends BaseEntity implements BaseDto { | ||
| 15 | + | ||
| 16 | + private static final long serialVersionUID = 1L; | ||
| 17 | + | ||
| 18 | + public static final String CACHE_NAME = "SupplierQuotationProjectQuote"; | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * ID | ||
| 22 | + */ | ||
| 23 | + private String id; | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 报价项目ID | ||
| 27 | + */ | ||
| 28 | + private String projectId; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 供应商ID(当前登录用户ID) | ||
| 32 | + */ | ||
| 33 | + private String supplierId; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 供应商名称 | ||
| 37 | + */ | ||
| 38 | + private String supplierName; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 报价时间(最后一次报价时间) | ||
| 42 | + */ | ||
| 43 | + private LocalDateTime quoteTime; | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * 品种ID | ||
| 47 | + */ | ||
| 48 | + private String productId; | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 品种名称 | ||
| 52 | + */ | ||
| 53 | + @TableField(exist = false) | ||
| 54 | + private String productName; | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 品种代号 | ||
| 58 | + */ | ||
| 59 | + @TableField(exist = false) | ||
| 60 | + private String productCode; | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * 数量 | ||
| 64 | + */ | ||
| 65 | + private BigDecimal quantity; | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * 价格 | ||
| 69 | + */ | ||
| 70 | + private BigDecimal price; | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * 中标状态(中标/未中标/废标) | ||
| 74 | + */ | ||
| 75 | + private String bidStatus; | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 创建人ID | ||
| 79 | + */ | ||
| 80 | + @TableField(fill = FieldFill.INSERT) | ||
| 81 | + private String createById; | ||
| 82 | + | ||
| 83 | + /** | ||
| 84 | + * 创建人 | ||
| 85 | + */ | ||
| 86 | + @TableField(fill = FieldFill.INSERT) | ||
| 87 | + private String createBy; | ||
| 88 | + | ||
| 89 | + /** | ||
| 90 | + * 更新人ID | ||
| 91 | + */ | ||
| 92 | + @TableField(fill = FieldFill.INSERT_UPDATE) | ||
| 93 | + private String updateById; | ||
| 94 | + | ||
| 95 | + /** | ||
| 96 | + * 更新人 | ||
| 97 | + */ | ||
| 98 | + @TableField(fill = FieldFill.INSERT_UPDATE) | ||
| 99 | + private String updateBy; | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * 创建时间 | ||
| 103 | + */ | ||
| 104 | + @TableField(fill = FieldFill.INSERT) | ||
| 105 | + private LocalDateTime createTime; | ||
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * 更新时间 | ||
| 109 | + */ | ||
| 110 | + @TableField(fill = FieldFill.INSERT_UPDATE) | ||
| 111 | + private LocalDateTime updateTime; | ||
| 112 | +} | ||
| 113 | + |
| 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.CollectionUtil; | ||
| 7 | +import com.lframework.starter.common.utils.ObjectUtil; | ||
| 8 | +import com.lframework.starter.web.core.annotations.oplog.OpLog; | ||
| 9 | +import com.lframework.starter.web.core.impl.BaseMpServiceImpl; | ||
| 10 | +import com.lframework.starter.web.core.utils.IdUtil; | ||
| 11 | +import com.lframework.starter.web.core.utils.OpLogUtil; | ||
| 12 | +import com.lframework.starter.web.core.components.security.SecurityUtil; | ||
| 13 | +import com.lframework.starter.web.inner.components.oplog.OtherOpLogType; | ||
| 14 | +import com.lframework.starter.web.inner.entity.SysRole; | ||
| 15 | +import com.lframework.starter.web.inner.entity.SysUser; | ||
| 16 | +import com.lframework.starter.web.inner.service.system.SysRoleService; | ||
| 17 | +import com.lframework.starter.web.inner.service.system.SysUserService; | ||
| 18 | +import com.lframework.xingyun.basedata.entity.BreedRelationship; | ||
| 19 | +import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; | ||
| 20 | +import com.lframework.xingyun.sc.procurement.entity.SupplierQuotationProject; | ||
| 21 | +import com.lframework.xingyun.sc.procurement.entity.SupplierQuotationProjectQuote; | ||
| 22 | +import com.lframework.xingyun.sc.procurement.mappers.quotation.SupplierQuotationProjectMapper; | ||
| 23 | +import com.lframework.xingyun.sc.procurement.mappers.quotation.SupplierQuotationProjectQuoteMapper; | ||
| 24 | +import com.lframework.xingyun.sc.procurement.service.quotation.SupplierQuotationProjectQuoteService; | ||
| 25 | +import com.lframework.xingyun.sc.procurement.vo.quotation.SupplierQuotationProjectQuoteVo; | ||
| 26 | +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSupplierQuotationProjectQuoteBidStatusVo; | ||
| 27 | +import java.io.Serializable; | ||
| 28 | +import java.time.LocalDateTime; | ||
| 29 | +import java.util.Collections; | ||
| 30 | +import java.util.List; | ||
| 31 | +import java.util.Set; | ||
| 32 | +import java.util.stream.Collectors; | ||
| 33 | +import javax.annotation.Resource; | ||
| 34 | +import org.apache.commons.lang3.StringUtils; | ||
| 35 | +import org.springframework.stereotype.Service; | ||
| 36 | +import org.springframework.transaction.annotation.Transactional; | ||
| 37 | + | ||
| 38 | +@Service | ||
| 39 | +public class SupplierQuotationProjectQuoteServiceImpl | ||
| 40 | + extends BaseMpServiceImpl<SupplierQuotationProjectQuoteMapper, SupplierQuotationProjectQuote> | ||
| 41 | + implements SupplierQuotationProjectQuoteService { | ||
| 42 | + | ||
| 43 | + private static final String BID_STATUS_WIN = "中标"; | ||
| 44 | + private static final String BID_STATUS_LOSE = "未中标"; | ||
| 45 | + private static final String BID_STATUS_ABORT = "废标"; | ||
| 46 | + | ||
| 47 | + private static final String PROJECT_STATUS_COMPLETED = "COMPLETED"; | ||
| 48 | + private static final String PROJECT_STATUS_ABORTED = "ABORTED"; | ||
| 49 | + | ||
| 50 | + private static final String PROJECT_TYPE_CENTRAL_BID = "CENTRAL_BID"; | ||
| 51 | + private static final String PROJECT_TYPE_CENTRAL_BID_CN = "集中开标"; | ||
| 52 | + private static final String PROJECT_TYPE_REAL_TIME = "REAL_TIME"; | ||
| 53 | + private static final String PROJECT_TYPE_REAL_TIME_CN = "实时成交"; | ||
| 54 | + | ||
| 55 | + private static final String ORDER_BY_PRICE_ASC = "PRICE_ASC"; | ||
| 56 | + private static final String ORDER_BY_CREATE_TIME_DESC = "CREATE_TIME_DESC"; | ||
| 57 | + | ||
| 58 | + @Resource | ||
| 59 | + private SupplierQuotationProjectMapper supplierQuotationProjectMapper; | ||
| 60 | + @Resource | ||
| 61 | + private SysUserService sysUserService; | ||
| 62 | + @Resource | ||
| 63 | + private SysRoleService sysRoleService; | ||
| 64 | + @Resource | ||
| 65 | + private BreedRelationshipService breedRelationshipService; | ||
| 66 | + | ||
| 67 | + @OpLog(type = OtherOpLogType.class, name = "供应商报价项目报价,项目ID:{}", params = {"#vo.projectId"}) | ||
| 68 | + @Transactional(rollbackFor = Exception.class) | ||
| 69 | + @Override | ||
| 70 | + public void quote(SupplierQuotationProjectQuoteVo vo) { | ||
| 71 | + SupplierQuotationProject project = supplierQuotationProjectMapper.selectById(vo.getProjectId()); | ||
| 72 | + if (project == null) { | ||
| 73 | + throw new DefaultClientException("报价项目不存在!"); | ||
| 74 | + } | ||
| 75 | + validateProjectCanQuote(project); | ||
| 76 | + validateProduct(vo.getProductId()); | ||
| 77 | + | ||
| 78 | + SysUser currentUser = getCurrentUser(); | ||
| 79 | + LocalDateTime now = LocalDateTime.now(); | ||
| 80 | + | ||
| 81 | + SupplierQuotationProjectQuote exist = getBaseMapper() | ||
| 82 | + .findByProjectAndSupplier(vo.getProjectId(), currentUser.getId()); | ||
| 83 | + if (exist == null) { | ||
| 84 | + SupplierQuotationProjectQuote data = new SupplierQuotationProjectQuote(); | ||
| 85 | + data.setId(IdUtil.getId()); | ||
| 86 | + data.setProjectId(StringUtils.trimToEmpty(vo.getProjectId())); | ||
| 87 | + data.setSupplierId(currentUser.getId()); | ||
| 88 | + data.setSupplierName(currentUser.getName()); | ||
| 89 | + data.setQuoteTime(now); | ||
| 90 | + data.setProductId(StringUtils.trimToEmpty(vo.getProductId())); | ||
| 91 | + data.setQuantity(vo.getQuantity()); | ||
| 92 | + data.setPrice(vo.getPrice()); | ||
| 93 | + data.setBidStatus(null); | ||
| 94 | + getBaseMapper().insert(data); | ||
| 95 | + } else { | ||
| 96 | + LambdaUpdateWrapper<SupplierQuotationProjectQuote> updateWrapper = Wrappers.lambdaUpdate(SupplierQuotationProjectQuote.class) | ||
| 97 | + .set(SupplierQuotationProjectQuote::getSupplierName, currentUser.getName()) | ||
| 98 | + .set(SupplierQuotationProjectQuote::getQuoteTime, now) | ||
| 99 | + .set(SupplierQuotationProjectQuote::getProductId, StringUtils.trimToEmpty(vo.getProductId())) | ||
| 100 | + .set(SupplierQuotationProjectQuote::getQuantity, vo.getQuantity()) | ||
| 101 | + .set(SupplierQuotationProjectQuote::getPrice, vo.getPrice()) | ||
| 102 | + .eq(SupplierQuotationProjectQuote::getId, exist.getId()); | ||
| 103 | + getBaseMapper().update(updateWrapper); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + OpLogUtil.setExtra(vo); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + @Override | ||
| 110 | + public SupplierQuotationProjectQuote getMyQuote(String projectId) { | ||
| 111 | + SysUser currentUser = getCurrentUser(); | ||
| 112 | + return getBaseMapper().findByProjectAndSupplier(projectId, currentUser.getId()); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + @Override | ||
| 116 | + public List<SupplierQuotationProjectQuote> listByProject(String projectId) { | ||
| 117 | + SupplierQuotationProject project = supplierQuotationProjectMapper.selectById(projectId); | ||
| 118 | + if (project == null) { | ||
| 119 | + throw new DefaultClientException("报价项目不存在!"); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + List<SysRole> sysRoleList = sysRoleService.getByUserId(SecurityUtil.getCurrentUser().getId()); | ||
| 123 | + Set<String> roleCodeSet = sysRoleList.stream() | ||
| 124 | + .map(SysRole::getCode) | ||
| 125 | + .collect(Collectors.toSet()); | ||
| 126 | + | ||
| 127 | + if (roleCodeSet.contains("gys")) { | ||
| 128 | + SupplierQuotationProjectQuote supplierQuotationProjectQuote = getMyQuote(projectId); | ||
| 129 | + if (supplierQuotationProjectQuote == null) { | ||
| 130 | + return Collections.emptyList(); | ||
| 131 | + } | ||
| 132 | + return Collections.singletonList(supplierQuotationProjectQuote); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + LocalDateTime now = LocalDateTime.now(); | ||
| 136 | + boolean centralBid = isCentralBid(project.getProjectType()); | ||
| 137 | + boolean realTime = isRealTime(project.getProjectType()); | ||
| 138 | + boolean beforeBidTime = centralBid && project.getBidTime() != null && now.isBefore(project.getBidTime()); | ||
| 139 | + | ||
| 140 | + String orderBy = ORDER_BY_CREATE_TIME_DESC; | ||
| 141 | + if (realTime) { | ||
| 142 | + orderBy = ORDER_BY_PRICE_ASC; | ||
| 143 | + } else if (centralBid && !beforeBidTime) { | ||
| 144 | + orderBy = ORDER_BY_PRICE_ASC; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + List<SupplierQuotationProjectQuote> list = getBaseMapper().listByProject(projectId, orderBy); | ||
| 148 | + if (beforeBidTime && CollectionUtil.isNotEmpty(list)) { | ||
| 149 | + list.forEach(v -> v.setPrice(null)); | ||
| 150 | + } | ||
| 151 | + return list; | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + @OpLog(type = OtherOpLogType.class, name = "维护供应商报价中标状态,项目ID:{},供应商ID:{}", params = {"#vo.projectId", "#vo.supplierId"}) | ||
| 155 | + @Transactional(rollbackFor = Exception.class) | ||
| 156 | + @Override | ||
| 157 | + public void updateBidStatus(UpdateSupplierQuotationProjectQuoteBidStatusVo vo) { | ||
| 158 | + String bidStatus = normalizeBidStatus(vo.getBidStatus()); | ||
| 159 | + SupplierQuotationProjectQuote exist = getBaseMapper() | ||
| 160 | + .findByProjectAndSupplier(vo.getProjectId(), vo.getSupplierId()); | ||
| 161 | + if (ObjectUtil.isNull(exist)) { | ||
| 162 | + throw new DefaultClientException("供应商报价记录不存在!"); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + LambdaUpdateWrapper<SupplierQuotationProjectQuote> updateWrapper = Wrappers.lambdaUpdate(SupplierQuotationProjectQuote.class) | ||
| 166 | + .set(SupplierQuotationProjectQuote::getBidStatus, bidStatus) | ||
| 167 | + .eq(SupplierQuotationProjectQuote::getId, exist.getId()); | ||
| 168 | + getBaseMapper().update(updateWrapper); | ||
| 169 | + | ||
| 170 | + OpLogUtil.setExtra(vo); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + @Override | ||
| 174 | + public void cleanCacheByKey(Serializable key) { | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + private void validateProjectCanQuote(SupplierQuotationProject project) { | ||
| 178 | + if (PROJECT_STATUS_COMPLETED.equals(project.getStatus())) { | ||
| 179 | + throw new DefaultClientException("该报价项目已完成,不允许报价!"); | ||
| 180 | + } | ||
| 181 | + if (PROJECT_STATUS_ABORTED.equals(project.getStatus())) { | ||
| 182 | + throw new DefaultClientException("该报价项目已中止,不允许报价!"); | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + LocalDateTime now = LocalDateTime.now(); | ||
| 186 | + if (project.getStartTime() != null && now.isBefore(project.getStartTime())) { | ||
| 187 | + throw new DefaultClientException("该报价项目未开始,不允许报价!"); | ||
| 188 | + } | ||
| 189 | + if (project.getEndTime() != null && now.isAfter(project.getEndTime())) { | ||
| 190 | + throw new DefaultClientException("该报价项目已截止,不允许报价!"); | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + private void validateProduct(String productId) { | ||
| 195 | + BreedRelationship breedRelationship = breedRelationshipService.findById(productId); | ||
| 196 | + if (breedRelationship == null) { | ||
| 197 | + throw new DefaultClientException("品种不存在,请重新选择!"); | ||
| 198 | + } | ||
| 199 | + } | ||
| 200 | + | ||
| 201 | + private SysUser getCurrentUser() { | ||
| 202 | + String currentUserId = SecurityUtil.getCurrentUser().getId(); | ||
| 203 | + SysUser currentUser = sysUserService.findById(currentUserId); | ||
| 204 | + if (currentUser == null) { | ||
| 205 | + throw new DefaultClientException("当前用户不存在!"); | ||
| 206 | + } | ||
| 207 | + return currentUser; | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + private String normalizeBidStatus(String bidStatus) { | ||
| 211 | + if (StringUtils.isBlank(bidStatus)) { | ||
| 212 | + throw new DefaultClientException("中标状态不能为空!"); | ||
| 213 | + } | ||
| 214 | + if (BID_STATUS_WIN.equals(bidStatus) || BID_STATUS_LOSE.equals(bidStatus) || BID_STATUS_ABORT.equals(bidStatus)) { | ||
| 215 | + return bidStatus; | ||
| 216 | + } | ||
| 217 | + throw new DefaultClientException("中标状态不合法!"); | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + private boolean isCentralBid(String projectType) { | ||
| 221 | + if (StringUtils.isBlank(projectType)) { | ||
| 222 | + return false; | ||
| 223 | + } | ||
| 224 | + return PROJECT_TYPE_CENTRAL_BID.equalsIgnoreCase(projectType) || PROJECT_TYPE_CENTRAL_BID_CN.equals(projectType); | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + private boolean isRealTime(String projectType) { | ||
| 228 | + if (StringUtils.isBlank(projectType)) { | ||
| 229 | + return false; | ||
| 230 | + } | ||
| 231 | + return PROJECT_TYPE_REAL_TIME.equalsIgnoreCase(projectType) || PROJECT_TYPE_REAL_TIME_CN.equals(projectType); | ||
| 232 | + } | ||
| 233 | +} |
| @@ -18,7 +18,9 @@ import com.lframework.starter.web.inner.components.oplog.OtherOpLogType; | @@ -18,7 +18,9 @@ import com.lframework.starter.web.inner.components.oplog.OtherOpLogType; | ||
| 18 | import com.lframework.xingyun.basedata.entity.BreedRelationship; | 18 | import com.lframework.xingyun.basedata.entity.BreedRelationship; |
| 19 | import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; | 19 | import com.lframework.xingyun.basedata.service.breed.BreedRelationshipService; |
| 20 | import com.lframework.xingyun.sc.procurement.entity.SupplierQuotationProject; | 20 | import com.lframework.xingyun.sc.procurement.entity.SupplierQuotationProject; |
| 21 | +import com.lframework.xingyun.sc.procurement.entity.SupplierQuotationProjectQuote; | ||
| 21 | import com.lframework.xingyun.sc.procurement.mappers.quotation.SupplierQuotationProjectMapper; | 22 | import com.lframework.xingyun.sc.procurement.mappers.quotation.SupplierQuotationProjectMapper; |
| 23 | +import com.lframework.xingyun.sc.procurement.service.quotation.SupplierQuotationProjectQuoteService; | ||
| 22 | import com.lframework.xingyun.sc.procurement.service.quotation.SupplierQuotationProjectService; | 24 | import com.lframework.xingyun.sc.procurement.service.quotation.SupplierQuotationProjectService; |
| 23 | import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSupplierQuotationProjectVo; | 25 | import com.lframework.xingyun.sc.procurement.vo.quotation.CreateSupplierQuotationProjectVo; |
| 24 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySupplierQuotationProjectVo; | 26 | import com.lframework.xingyun.sc.procurement.vo.quotation.QuerySupplierQuotationProjectVo; |
| @@ -53,10 +55,10 @@ public class SupplierQuotationProjectServiceImpl | @@ -53,10 +55,10 @@ public class SupplierQuotationProjectServiceImpl | ||
| 53 | //已中止 | 55 | //已中止 |
| 54 | private static final String STATUS_ABORTED_CN = "ABORTED"; | 56 | private static final String STATUS_ABORTED_CN = "ABORTED"; |
| 55 | 57 | ||
| 56 | - | ||
| 57 | - | ||
| 58 | @Resource | 58 | @Resource |
| 59 | private BreedRelationshipService breedRelationshipService; | 59 | private BreedRelationshipService breedRelationshipService; |
| 60 | + @Resource | ||
| 61 | + private SupplierQuotationProjectQuoteService supplierQuotationProjectQuoteService; | ||
| 60 | 62 | ||
| 61 | @Override | 63 | @Override |
| 62 | public PageResult<SupplierQuotationProject> query(Integer pageIndex, Integer pageSize, QuerySupplierQuotationProjectVo vo) { | 64 | public PageResult<SupplierQuotationProject> query(Integer pageIndex, Integer pageSize, QuerySupplierQuotationProjectVo vo) { |
| @@ -80,6 +82,8 @@ public class SupplierQuotationProjectServiceImpl | @@ -80,6 +82,8 @@ public class SupplierQuotationProjectServiceImpl | ||
| 80 | SupplierQuotationProject data = getBaseMapper().findById(id); | 82 | SupplierQuotationProject data = getBaseMapper().findById(id); |
| 81 | if (data != null) { | 83 | if (data != null) { |
| 82 | data.setStatus(computeStatus(data)); | 84 | data.setStatus(computeStatus(data)); |
| 85 | + List<SupplierQuotationProjectQuote> supplierQuotationProjectQuoteList = supplierQuotationProjectQuoteService.listByProject(id); | ||
| 86 | + data.setSupplierQuotationProjectQuoteList(supplierQuotationProjectQuoteList); | ||
| 83 | } | 87 | } |
| 84 | return data; | 88 | return data; |
| 85 | } | 89 | } |
| 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.SupplierQuotationProjectQuote; | ||
| 5 | +import java.util.List; | ||
| 6 | +import org.apache.ibatis.annotations.Param; | ||
| 7 | + | ||
| 8 | +public interface SupplierQuotationProjectQuoteMapper extends BaseMapper<SupplierQuotationProjectQuote> { | ||
| 9 | + | ||
| 10 | + SupplierQuotationProjectQuote findByProjectAndSupplier(@Param("projectId") String projectId, | ||
| 11 | + @Param("supplierId") String supplierId); | ||
| 12 | + | ||
| 13 | + List<SupplierQuotationProjectQuote> listByProject(@Param("projectId") String projectId, | ||
| 14 | + @Param("orderBy") String orderBy); | ||
| 15 | +} |
| 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.SupplierQuotationProjectQuote; | ||
| 5 | +import com.lframework.xingyun.sc.procurement.vo.quotation.SupplierQuotationProjectQuoteVo; | ||
| 6 | +import com.lframework.xingyun.sc.procurement.vo.quotation.UpdateSupplierQuotationProjectQuoteBidStatusVo; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +public interface SupplierQuotationProjectQuoteService extends BaseMpService<SupplierQuotationProjectQuote> { | ||
| 10 | + | ||
| 11 | + void quote(SupplierQuotationProjectQuoteVo vo); | ||
| 12 | + | ||
| 13 | + SupplierQuotationProjectQuote getMyQuote(String projectId); | ||
| 14 | + | ||
| 15 | + List<SupplierQuotationProjectQuote> listByProject(String projectId); | ||
| 16 | + | ||
| 17 | + void updateBidStatus(UpdateSupplierQuotationProjectQuoteBidStatusVo vo); | ||
| 18 | +} | ||
| 19 | + |
| 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.LocalDateTime; | ||
| 8 | +import javax.validation.constraints.NotBlank; | ||
| 9 | +import javax.validation.constraints.NotNull; | ||
| 10 | +import lombok.Data; | ||
| 11 | + | ||
| 12 | +@Data | ||
| 13 | +public class SupplierQuotationProjectQuoteVo implements BaseVo, Serializable { | ||
| 14 | + | ||
| 15 | + private static final long serialVersionUID = 1L; | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "报价项目ID", required = true) | ||
| 18 | + @NotBlank(message = "报价项目ID不能为空!") | ||
| 19 | + private String projectId; | ||
| 20 | + | ||
| 21 | + @ApiModelProperty(value = "品种ID", required = true) | ||
| 22 | + @NotBlank(message = "品种不能为空!") | ||
| 23 | + private String productId; | ||
| 24 | + | ||
| 25 | + @ApiModelProperty(value = "数量", required = true) | ||
| 26 | + @NotNull(message = "数量不能为空!") | ||
| 27 | + private BigDecimal quantity; | ||
| 28 | + | ||
| 29 | + @ApiModelProperty(value = "价格", required = true) | ||
| 30 | + @NotNull(message = "价格不能为空!") | ||
| 31 | + private BigDecimal price; | ||
| 32 | + | ||
| 33 | + @ApiModelProperty("报价时间(前端不传,后端以当前时间写入)") | ||
| 34 | + private LocalDateTime quoteTime; | ||
| 35 | +} | ||
| 36 | + |
| 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 javax.validation.constraints.NotBlank; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +@Data | ||
| 10 | +public class UpdateSupplierQuotationProjectQuoteBidStatusVo implements BaseVo, Serializable { | ||
| 11 | + | ||
| 12 | + private static final long serialVersionUID = 1L; | ||
| 13 | + | ||
| 14 | + @ApiModelProperty(value = "报价项目ID", required = true) | ||
| 15 | + @NotBlank(message = "报价项目ID不能为空!") | ||
| 16 | + private String projectId; | ||
| 17 | + | ||
| 18 | + @ApiModelProperty(value = "供应商ID(当前登录用户ID)", required = true) | ||
| 19 | + @NotBlank(message = "供应商ID不能为空!") | ||
| 20 | + private String supplierId; | ||
| 21 | + | ||
| 22 | + @ApiModelProperty(value = "中标状态(中标/未中标/废标)", required = true) | ||
| 23 | + @NotBlank(message = "中标状态不能为空!") | ||
| 24 | + private String bidStatus; | ||
| 25 | +} | ||
| 26 | + |
xingyun-sc/src/main/resources/mappers/procurement/quotation/SupplierQuotationProjectQuoteMapper.xml
0 → 100644
| 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.SupplierQuotationProjectQuoteMapper"> | ||
| 4 | + | ||
| 5 | + <resultMap id="SupplierQuotationProjectQuote" type="com.lframework.xingyun.sc.procurement.entity.SupplierQuotationProjectQuote"> | ||
| 6 | + <id column="id" property="id"/> | ||
| 7 | + <result column="project_id" property="projectId"/> | ||
| 8 | + <result column="supplier_id" property="supplierId"/> | ||
| 9 | + <result column="supplier_name" property="supplierName"/> | ||
| 10 | + <result column="quote_time" property="quoteTime"/> | ||
| 11 | + <result column="product_id" property="productId"/> | ||
| 12 | + <result column="product_name" property="productName"/> | ||
| 13 | + <result column="product_code" property="productCode"/> | ||
| 14 | + <result column="quantity" property="quantity"/> | ||
| 15 | + <result column="price" property="price"/> | ||
| 16 | + <result column="bid_status" property="bidStatus"/> | ||
| 17 | + <result column="create_by_id" property="createById"/> | ||
| 18 | + <result column="create_by" property="createBy"/> | ||
| 19 | + <result column="update_by_id" property="updateById"/> | ||
| 20 | + <result column="update_by" property="updateBy"/> | ||
| 21 | + <result column="create_time" property="createTime"/> | ||
| 22 | + <result column="update_time" property="updateTime"/> | ||
| 23 | + </resultMap> | ||
| 24 | + | ||
| 25 | + <sql id="SupplierQuotationProjectQuoteSql"> | ||
| 26 | + SELECT | ||
| 27 | + tb.id, | ||
| 28 | + tb.project_id, | ||
| 29 | + tb.supplier_id, | ||
| 30 | + tb.supplier_name, | ||
| 31 | + tb.quote_time, | ||
| 32 | + tb.product_id, | ||
| 33 | + br.product_name, | ||
| 34 | + br.code AS product_code, | ||
| 35 | + tb.quantity, | ||
| 36 | + tb.price, | ||
| 37 | + tb.bid_status, | ||
| 38 | + tb.create_by_id, | ||
| 39 | + tb.create_by, | ||
| 40 | + tb.update_by_id, | ||
| 41 | + tb.update_by, | ||
| 42 | + tb.create_time, | ||
| 43 | + tb.update_time | ||
| 44 | + FROM procurement_supplier_quotation_project_quote tb | ||
| 45 | + LEFT JOIN base_data_breed_relationship br ON br.id = tb.product_id | ||
| 46 | + </sql> | ||
| 47 | + | ||
| 48 | + <select id="findByProjectAndSupplier" resultMap="SupplierQuotationProjectQuote"> | ||
| 49 | + <include refid="SupplierQuotationProjectQuoteSql"/> | ||
| 50 | + WHERE tb.project_id = #{projectId} | ||
| 51 | + AND tb.supplier_id = #{supplierId} | ||
| 52 | + </select> | ||
| 53 | + | ||
| 54 | + <select id="listByProject" resultMap="SupplierQuotationProjectQuote"> | ||
| 55 | + <include refid="SupplierQuotationProjectQuoteSql"/> | ||
| 56 | + WHERE tb.project_id = #{projectId} | ||
| 57 | + <choose> | ||
| 58 | + <when test="orderBy == 'PRICE_ASC'"> | ||
| 59 | + ORDER BY tb.price ASC, tb.quote_time DESC, tb.id DESC | ||
| 60 | + </when> | ||
| 61 | + <otherwise> | ||
| 62 | + ORDER BY tb.create_time DESC, tb.id DESC | ||
| 63 | + </otherwise> | ||
| 64 | + </choose> | ||
| 65 | + </select> | ||
| 66 | +</mapper> |