diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/XzdHtglHtbgqd.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/XzdHtglHtbgqd.java new file mode 100644 index 00000000..d72fb2e9 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/XzdHtglHtbgqd.java @@ -0,0 +1,142 @@ +package org.dromara.xzd.comprehensive.domain; + +import org.dromara.common.mybatis.core.domain.BaseEntity; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.math.BigDecimal; + +import java.io.Serial; + +/** + * 合同管理-合同变更清单对象 xzd_htgl_htbgqd + * + * @author Lion Li + * @date 2025-10-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("xzd_htgl_htbgqd") +public class XzdHtglHtbgqd extends BaseEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @TableId(value = "id") + private Long id; + + /** + * 立项(1、承包合同信息,2、承包合同变更,3分包合同信息,4、分包合同变更,5、采购合同信息,6、采购合同变更,7、综合服务信息,8、综合服务变更) + */ + private Long type; + + /** + * 附件(路径/关联ID) + */ + private String attachment; + + /** + * 编码 + */ + private String code; + + /** + * 合同名称(带*,必填) + */ + private String contractName; + + /** + * 报销单号 + */ + private String bidNo; + + /** + * 计算单位(带*,必填) + */ + private String calculateUnit; + + /** + * 原数值 + */ + private BigDecimal originalValue; + + /** + * 变更后数值 + */ + private BigDecimal afterChangeValue; + + /** + * 原含税单价 + */ + private BigDecimal originalTaxInclUnitPrice; + + /** + * 变更后含税单价 + */ + private BigDecimal afterChangeTaxInclUnitPrice; + + /** + * 原含税金额 + */ + private BigDecimal originalTaxInclAmount; + + /** + * 变更后含税金额 + */ + private BigDecimal afterChangeTaxInclAmount; + + /** + * 原税率 + */ + private BigDecimal originalTaxRate; + + /** + * 变更后税率 + */ + private BigDecimal afterChangeTaxRate; + + /** + * 原WBS + */ + private String originalWbs; + + /** + * 变更后WBS + */ + private String afterChangeWbs; + + /** + * 原CBS + */ + private String originalCbs; + + /** + * 变更后CBS + */ + private String afterChangeCbs; + + /** + * 成本预算金额 + */ + private BigDecimal costBudgetAmount; + + /** + * 成本预算来源 + */ + private String costBudgetSource; + + /** + * 备注 + */ + private String remark; + + /** + * 已结价税合计 + */ + private Long settledPriceTotal; + + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/bo/XzdHtglHtbgqdBo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/bo/XzdHtglHtbgqdBo.java new file mode 100644 index 00000000..48209fde --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/bo/XzdHtglHtbgqdBo.java @@ -0,0 +1,144 @@ +package org.dromara.xzd.comprehensive.domain.bo; + +import org.dromara.xzd.comprehensive.domain.XzdHtglHtbgqd; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; +import java.math.BigDecimal; + +/** + * 合同管理-合同变更清单业务对象 xzd_htgl_htbgqd + * + * @author Lion Li + * @date 2025-10-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = XzdHtglHtbgqd.class, reverseConvertGenerate = false) +public class XzdHtglHtbgqdBo extends BaseEntity { + + /** + * 主键ID + */ + @NotNull(message = "主键ID不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 立项(1、承包合同信息,2、承包合同变更,3分包合同信息,4、分包合同变更,5、采购合同信息,6、采购合同变更,7、综合服务信息,8、综合服务变更) + */ + @NotNull(message = "立项(1、承包合同信息,2、承包合同变更,3分包合同信息,4、分包合同变更,5、采购合同信息,6、采购合同变更,7、综合服务信息,8、综合服务变更)不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long type; + + /** + * 附件(路径/关联ID) + */ + private String attachment; + + /** + * 编码 + */ + private String code; + + /** + * 合同名称(带*,必填) + */ + @NotBlank(message = "合同名称(带*,必填)不能为空", groups = { AddGroup.class, EditGroup.class }) + private String contractName; + + /** + * 报销单号 + */ + private String bidNo; + + /** + * 计算单位(带*,必填) + */ + @NotBlank(message = "计算单位(带*,必填)不能为空", groups = { AddGroup.class, EditGroup.class }) + private String calculateUnit; + + /** + * 原数值 + */ + private BigDecimal originalValue; + + /** + * 变更后数值 + */ + private BigDecimal afterChangeValue; + + /** + * 原含税单价 + */ + private BigDecimal originalTaxInclUnitPrice; + + /** + * 变更后含税单价 + */ + private BigDecimal afterChangeTaxInclUnitPrice; + + /** + * 原含税金额 + */ + private BigDecimal originalTaxInclAmount; + + /** + * 变更后含税金额 + */ + private BigDecimal afterChangeTaxInclAmount; + + /** + * 原税率 + */ + private BigDecimal originalTaxRate; + + /** + * 变更后税率 + */ + private BigDecimal afterChangeTaxRate; + + /** + * 原WBS + */ + private String originalWbs; + + /** + * 变更后WBS + */ + private String afterChangeWbs; + + /** + * 原CBS + */ + private String originalCbs; + + /** + * 变更后CBS + */ + private String afterChangeCbs; + + /** + * 成本预算金额 + */ + private BigDecimal costBudgetAmount; + + /** + * 成本预算来源 + */ + private String costBudgetSource; + + /** + * 备注 + */ + private String remark; + + /** + * 已结价税合计 + */ + private Long settledPriceTotal; + + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/vo/XzdHtglHtbgqdVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/vo/XzdHtglHtbgqdVo.java new file mode 100644 index 00000000..81b16e46 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/domain/vo/XzdHtglHtbgqdVo.java @@ -0,0 +1,175 @@ +package org.dromara.xzd.comprehensive.domain.vo; + +import java.math.BigDecimal; +import org.dromara.xzd.comprehensive.domain.XzdHtglHtbgqd; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + + +/** + * 合同管理-合同变更清单视图对象 xzd_htgl_htbgqd + * + * @author Lion Li + * @date 2025-10-17 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = XzdHtglHtbgqd.class) +public class XzdHtglHtbgqdVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ExcelProperty(value = "主键ID") + private Long id; + + /** + * 立项(1、承包合同信息,2、承包合同变更,3分包合同信息,4、分包合同变更,5、采购合同信息,6、采购合同变更,7、综合服务信息,8、综合服务变更) + */ + @ExcelProperty(value = "立项", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "1=、承包合同信息,2、承包合同变更,3分包合同信息,4、分包合同变更,5、采购合同信息,6、采购合同变更,7、综合服务信息,8、综合服务变更") + private Long type; + + /** + * 附件(路径/关联ID) + */ + @ExcelProperty(value = "附件", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "路=径/关联ID") + private String attachment; + + /** + * 编码 + */ + @ExcelProperty(value = "编码") + private String code; + + /** + * 合同名称(带*,必填) + */ + @ExcelProperty(value = "合同名称", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "带=*,必填") + private String contractName; + + /** + * 报销单号 + */ + @ExcelProperty(value = "报销单号") + private String bidNo; + + /** + * 计算单位(带*,必填) + */ + @ExcelProperty(value = "计算单位", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "带=*,必填") + private String calculateUnit; + + /** + * 原数值 + */ + @ExcelProperty(value = "原数值") + private BigDecimal originalValue; + + /** + * 变更后数值 + */ + @ExcelProperty(value = "变更后数值") + private BigDecimal afterChangeValue; + + /** + * 原含税单价 + */ + @ExcelProperty(value = "原含税单价") + private BigDecimal originalTaxInclUnitPrice; + + /** + * 变更后含税单价 + */ + @ExcelProperty(value = "变更后含税单价") + private BigDecimal afterChangeTaxInclUnitPrice; + + /** + * 原含税金额 + */ + @ExcelProperty(value = "原含税金额") + private BigDecimal originalTaxInclAmount; + + /** + * 变更后含税金额 + */ + @ExcelProperty(value = "变更后含税金额") + private BigDecimal afterChangeTaxInclAmount; + + /** + * 原税率 + */ + @ExcelProperty(value = "原税率") + private BigDecimal originalTaxRate; + + /** + * 变更后税率 + */ + @ExcelProperty(value = "变更后税率") + private BigDecimal afterChangeTaxRate; + + /** + * 原WBS + */ + @ExcelProperty(value = "原WBS") + private String originalWbs; + + /** + * 变更后WBS + */ + @ExcelProperty(value = "变更后WBS") + private String afterChangeWbs; + + /** + * 原CBS + */ + @ExcelProperty(value = "原CBS") + private String originalCbs; + + /** + * 变更后CBS + */ + @ExcelProperty(value = "变更后CBS") + private String afterChangeCbs; + + /** + * 成本预算金额 + */ + @ExcelProperty(value = "成本预算金额") + private BigDecimal costBudgetAmount; + + /** + * 成本预算来源 + */ + @ExcelProperty(value = "成本预算来源") + private String costBudgetSource; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 已结价税合计 + */ + @ExcelProperty(value = "已结价税合计") + private Long settledPriceTotal; + + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/mapper/XzdHtglHtbgqdMapper.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/mapper/XzdHtglHtbgqdMapper.java new file mode 100644 index 00000000..91231805 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/mapper/XzdHtglHtbgqdMapper.java @@ -0,0 +1,15 @@ +package org.dromara.xzd.comprehensive.mapper; + +import org.dromara.xzd.comprehensive.domain.XzdHtglHtbgqd; +import org.dromara.xzd.comprehensive.domain.vo.XzdHtglHtbgqdVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 合同管理-合同变更清单Mapper接口 + * + * @author Lion Li + * @date 2025-10-17 + */ +public interface XzdHtglHtbgqdMapper extends BaseMapperPlus { + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/service/IXzdHtglHtbgqdService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/service/IXzdHtglHtbgqdService.java new file mode 100644 index 00000000..faf80e6b --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/service/IXzdHtglHtbgqdService.java @@ -0,0 +1,70 @@ +package org.dromara.xzd.comprehensive.service; + +import org.dromara.xzd.comprehensive.domain.vo.XzdHtglHtbgqdVo; +import org.dromara.xzd.comprehensive.domain.bo.XzdHtglHtbgqdBo; +import org.dromara.xzd.comprehensive.domain.XzdHtglHtbgqd; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; + +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.Collection; +import java.util.List; + +/** + * 合同管理-合同变更清单Service接口 + * + * @author Lion Li + * @date 2025-10-17 + */ +public interface IXzdHtglHtbgqdService extends IService{ + + /** + * 查询合同管理-合同变更清单 + * + * @param id 主键 + * @return 合同管理-合同变更清单 + */ + XzdHtglHtbgqdVo queryById(Long id); + + /** + * 分页查询合同管理-合同变更清单列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 合同管理-合同变更清单分页列表 + */ + TableDataInfo queryPageList(XzdHtglHtbgqdBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的合同管理-合同变更清单列表 + * + * @param bo 查询条件 + * @return 合同管理-合同变更清单列表 + */ + List queryList(XzdHtglHtbgqdBo bo); + + /** + * 新增合同管理-合同变更清单 + * + * @param bo 合同管理-合同变更清单 + * @return 是否新增成功 + */ + Boolean insertByBo(XzdHtglHtbgqdBo bo); + + /** + * 修改合同管理-合同变更清单 + * + * @param bo 合同管理-合同变更清单 + * @return 是否修改成功 + */ + Boolean updateByBo(XzdHtglHtbgqdBo bo); + + /** + * 校验并批量删除合同管理-合同变更清单信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/service/impl/XzdHtglHtbgqdServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/service/impl/XzdHtglHtbgqdServiceImpl.java new file mode 100644 index 00000000..60fce849 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/service/impl/XzdHtglHtbgqdServiceImpl.java @@ -0,0 +1,151 @@ +package org.dromara.xzd.comprehensive.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.dromara.xzd.comprehensive.domain.bo.XzdHtglHtbgqdBo; +import org.dromara.xzd.comprehensive.domain.vo.XzdHtglHtbgqdVo; +import org.dromara.xzd.comprehensive.domain.XzdHtglHtbgqd; +import org.dromara.xzd.comprehensive.mapper.XzdHtglHtbgqdMapper; +import org.dromara.xzd.comprehensive.service.IXzdHtglHtbgqdService; + +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 合同管理-合同变更清单Service业务层处理 + * + * @author Lion Li + * @date 2025-10-17 + */ +@RequiredArgsConstructor +@Service +public class XzdHtglHtbgqdServiceImpl extends ServiceImpl implements IXzdHtglHtbgqdService { + + private final XzdHtglHtbgqdMapper baseMapper; + + /** + * 查询合同管理-合同变更清单 + * + * @param id 主键 + * @return 合同管理-合同变更清单 + */ + @Override + public XzdHtglHtbgqdVo queryById(Long id){ + return baseMapper.selectVoById(id); + } + + /** + * 分页查询合同管理-合同变更清单列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 合同管理-合同变更清单分页列表 + */ + @Override + public TableDataInfo queryPageList(XzdHtglHtbgqdBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的合同管理-合同变更清单列表 + * + * @param bo 查询条件 + * @return 合同管理-合同变更清单列表 + */ + @Override + public List queryList(XzdHtglHtbgqdBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(XzdHtglHtbgqdBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByDesc(XzdHtglHtbgqd::getId); + lqw.eq(bo.getType() != null, XzdHtglHtbgqd::getType, bo.getType()); + lqw.eq(StringUtils.isNotBlank(bo.getAttachment()), XzdHtglHtbgqd::getAttachment, bo.getAttachment()); + lqw.eq(StringUtils.isNotBlank(bo.getCode()), XzdHtglHtbgqd::getCode, bo.getCode()); + lqw.like(StringUtils.isNotBlank(bo.getContractName()), XzdHtglHtbgqd::getContractName, bo.getContractName()); + lqw.eq(StringUtils.isNotBlank(bo.getBidNo()), XzdHtglHtbgqd::getBidNo, bo.getBidNo()); + lqw.eq(StringUtils.isNotBlank(bo.getCalculateUnit()), XzdHtglHtbgqd::getCalculateUnit, bo.getCalculateUnit()); + lqw.eq(bo.getOriginalValue() != null, XzdHtglHtbgqd::getOriginalValue, bo.getOriginalValue()); + lqw.eq(bo.getAfterChangeValue() != null, XzdHtglHtbgqd::getAfterChangeValue, bo.getAfterChangeValue()); + lqw.eq(bo.getOriginalTaxInclUnitPrice() != null, XzdHtglHtbgqd::getOriginalTaxInclUnitPrice, bo.getOriginalTaxInclUnitPrice()); + lqw.eq(bo.getAfterChangeTaxInclUnitPrice() != null, XzdHtglHtbgqd::getAfterChangeTaxInclUnitPrice, bo.getAfterChangeTaxInclUnitPrice()); + lqw.eq(bo.getOriginalTaxInclAmount() != null, XzdHtglHtbgqd::getOriginalTaxInclAmount, bo.getOriginalTaxInclAmount()); + lqw.eq(bo.getAfterChangeTaxInclAmount() != null, XzdHtglHtbgqd::getAfterChangeTaxInclAmount, bo.getAfterChangeTaxInclAmount()); + lqw.eq(bo.getOriginalTaxRate() != null, XzdHtglHtbgqd::getOriginalTaxRate, bo.getOriginalTaxRate()); + lqw.eq(bo.getAfterChangeTaxRate() != null, XzdHtglHtbgqd::getAfterChangeTaxRate, bo.getAfterChangeTaxRate()); + lqw.eq(StringUtils.isNotBlank(bo.getOriginalWbs()), XzdHtglHtbgqd::getOriginalWbs, bo.getOriginalWbs()); + lqw.eq(StringUtils.isNotBlank(bo.getAfterChangeWbs()), XzdHtglHtbgqd::getAfterChangeWbs, bo.getAfterChangeWbs()); + lqw.eq(StringUtils.isNotBlank(bo.getOriginalCbs()), XzdHtglHtbgqd::getOriginalCbs, bo.getOriginalCbs()); + lqw.eq(StringUtils.isNotBlank(bo.getAfterChangeCbs()), XzdHtglHtbgqd::getAfterChangeCbs, bo.getAfterChangeCbs()); + lqw.eq(bo.getCostBudgetAmount() != null, XzdHtglHtbgqd::getCostBudgetAmount, bo.getCostBudgetAmount()); + lqw.eq(StringUtils.isNotBlank(bo.getCostBudgetSource()), XzdHtglHtbgqd::getCostBudgetSource, bo.getCostBudgetSource()); + lqw.eq(bo.getSettledPriceTotal() != null, XzdHtglHtbgqd::getSettledPriceTotal, bo.getSettledPriceTotal()); + return lqw; + } + + /** + * 新增合同管理-合同变更清单 + * + * @param bo 合同管理-合同变更清单 + * @return 是否新增成功 + */ + @Override + public Boolean insertByBo(XzdHtglHtbgqdBo bo) { + XzdHtglHtbgqd add = MapstructUtils.convert(bo, XzdHtglHtbgqd.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改合同管理-合同变更清单 + * + * @param bo 合同管理-合同变更清单 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(XzdHtglHtbgqdBo bo) { + XzdHtglHtbgqd update = MapstructUtils.convert(bo, XzdHtglHtbgqd.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(XzdHtglHtbgqd entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 校验并批量删除合同管理-合同变更清单信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/xzd/comprehensive/XzdHtglHtbgqdMapper.xml b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/xzd/comprehensive/XzdHtglHtbgqdMapper.xml new file mode 100644 index 00000000..f0d3af70 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/xzd/comprehensive/XzdHtglHtbgqdMapper.xml @@ -0,0 +1,7 @@ + + + + +