diff --git a/src/main/java/cn/lihongjie/coal/invoice/controller/InvoiceController.java b/src/main/java/cn/lihongjie/coal/invoice/controller/InvoiceController.java new file mode 100644 index 00000000..d410b289 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoice/controller/InvoiceController.java @@ -0,0 +1,75 @@ +package cn.lihongjie.coal.invoice.controller; + +import cn.lihongjie.coal.annotation.OrgScope; +import cn.lihongjie.coal.annotation.SysLog; +import cn.lihongjie.coal.base.dto.CommonQuery; +import cn.lihongjie.coal.base.dto.IdRequest; +import cn.lihongjie.coal.invoice.dto.CreateInvoiceDto; +import cn.lihongjie.coal.invoice.dto.InvoiceDto; +import cn.lihongjie.coal.invoice.dto.UpdateInvoiceDto; +import cn.lihongjie.coal.invoice.service.InvoiceService; + +import io.swagger.v3.oas.annotations.Operation; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/invoice") +@SysLog(module = "发票管理") +@Slf4j +@OrgScope +public class InvoiceController { + @Autowired private InvoiceService service; + + @PostMapping("/create") + public InvoiceDto create(@RequestBody CreateInvoiceDto request) { + return this.service.create(request); + } + + @PostMapping("/update") + public InvoiceDto update(@RequestBody UpdateInvoiceDto request) { + return this.service.update(request); + } + + @PostMapping("/delete") + public Object delete(@RequestBody IdRequest request) { + this.service.delete(request); + return true; + } + + @PostMapping("/getById") + public InvoiceDto getById(@RequestBody IdRequest request) { + return this.service.getById(request.getId()); + } + + @PostMapping("/list") + public Page list(@RequestBody CommonQuery request) { + return this.service.list(request); + } + + @PostMapping("/archive") + public Object archive(@RequestBody IdRequest request) { + this.service.archive(request); + return true; + } + + @PostMapping("/unarchive") + public Object unarchive(@RequestBody IdRequest request) { + this.service.unarchive(request); + return true; + } + + @PostMapping("/uploadNew") + @Operation(summary = "上传新发票") + public Object uploadNew(@RequestBody IdRequest request) { + this.service.uploadNew(request); + return true; + } +} diff --git a/src/main/java/cn/lihongjie/coal/invoice/dto/CreateInvoiceDto.java b/src/main/java/cn/lihongjie/coal/invoice/dto/CreateInvoiceDto.java new file mode 100644 index 00000000..cfa7b798 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoice/dto/CreateInvoiceDto.java @@ -0,0 +1,8 @@ +package cn.lihongjie.coal.invoice.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; + +import lombok.Data; + +@Data +public class CreateInvoiceDto extends OrgCommonDto {} diff --git a/src/main/java/cn/lihongjie/coal/invoice/dto/InvoiceDto.java b/src/main/java/cn/lihongjie/coal/invoice/dto/InvoiceDto.java new file mode 100644 index 00000000..11aad2a0 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoice/dto/InvoiceDto.java @@ -0,0 +1,106 @@ +package cn.lihongjie.coal.invoice.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; +import cn.lihongjie.coal.common.DictCode; +import cn.lihongjie.coal.file.entity.FileEntity; +import cn.lihongjie.coal.invoiceDetail.dto.InvoiceDetailDto; +import cn.lihongjie.coal.pojoProcessor.DictTranslate; + +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import lombok.Data; + +import org.hibernate.annotations.Comment; + +import java.util.List; + +@Data +public class InvoiceDto extends OrgCommonDto { + + + + @Comment("发票代码") + private String invoiceCode; + @Comment("发票号码") + private String invoiceNumber; + @Comment("开票日期") + private String invoiceDate; + @Comment("机器编码") + private String machineCode; + @Comment("校验码") + private String checkCode; + + @Comment("受票方名称") + private String purchaserName; + + @Comment("密码区") + private String passwordArea; + @Comment("不含税金额") + private String invoiceAmountPreTax; + @Comment("发票税额") + private String invoiceTax; + @Comment("大写金额") + private String totalAmountInWords; + @Comment("发票金额") + private String totalAmount; + @Comment("销售方名称") + private String sellerName; + @Comment("销售方税号") + private String sellerTaxNumber; + @Comment("销售方地址、电话") + private String sellerContactInfo; + @Comment("销售方开户行、账号") + private String sellerBankAccountInfo; + @Comment("开票人") + private String drawer; + + @Comment("标题") + private String title; + + @Comment("发票类型") + private String invoiceType; + + @Comment("联次") + private String formType; + + @Comment("机打发票代码") + private String printedInvoiceCode; + @Comment("机打发票号码") + private String printedInvoiceNumber; + + @Comment("受票方开户行、账号") + private String purchaserBankAccountInfo; + + @Comment("受票方地址、电话") + private String purchaserContactInfo; + + @Comment("受票方税号") + private String purchaserTaxNumber; + + @Comment("收款人") + private String recipient; + @Comment("备注") + private String remarks; + + @Comment("复核人") + private String reviewer; + + @Comment("特殊标识信息") + private String specialTag; + + + @OneToMany + private List invoiceDetails; + + + @ManyToOne + private FileEntity file; + + + + private String archiveStatus; + + @DictTranslate(dictKey = DictCode.ARCHIVESTATUS) + private String archiveStatusName; +} diff --git a/src/main/java/cn/lihongjie/coal/invoice/dto/UpdateInvoiceDto.java b/src/main/java/cn/lihongjie/coal/invoice/dto/UpdateInvoiceDto.java new file mode 100644 index 00000000..257c1ae2 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoice/dto/UpdateInvoiceDto.java @@ -0,0 +1,8 @@ +package cn.lihongjie.coal.invoice.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; + +import lombok.Data; + +@Data +public class UpdateInvoiceDto extends OrgCommonDto {} diff --git a/src/main/java/cn/lihongjie/coal/invoice/entity/InvoiceEntity.java b/src/main/java/cn/lihongjie/coal/invoice/entity/InvoiceEntity.java new file mode 100644 index 00000000..21d6893c --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoice/entity/InvoiceEntity.java @@ -0,0 +1,129 @@ +package cn.lihongjie.coal.invoice.entity; + +import cn.lihongjie.coal.base.entity.OrgCommonEntity; +import cn.lihongjie.coal.file.entity.FileEntity; +import cn.lihongjie.coal.invoiceDetail.entity.InvoiceDetailEntity; + +import jakarta.persistence.*; + +import lombok.Data; + +import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.Comment; + +import java.util.List; + +/** + * invoiceCode string 发票代码。 invoiceNumber string 发票号码。 invoiceDate string 开票日期。 machineCode string + * 机器编码。 checkCode string 校验码。 purchaserName string 受票方名称。 passwordArea string 密码区。 + * invoiceAmountPreTax string 不含税金额。 invoiceTax string 发票税额。 totalAmountInWords string 大写金额。 + * totalAmount string 发票金额。 sellerName string 销售方名称。 sellerTaxNumber string 销售方税号。 sellerContactInfo + * string 销售方地址、电话。 sellerBankAccountInfo string 销售方开户行、账号。 drawer string 开票人。 title string 标题。 + * invoiceType string 发票类型(数电专用发票、数电普通发票、电子普通发票、电子专用发票、专用发票、普通发票、通用发票)。 formType string 联次。 + * printedInvoiceCode string 机打发票代码。 printedInvoiceNumber string 机打发票号码。 purchaserBankAccountInfo + * string 受票方开户行、账号。 purchaserContactInfo string 受票方地址、电话。 purchaserTaxNumber string 受票方税号。 + * recipient string 收款人。 remarks string 备注。 reviewer string 复核人。 specialTag string 特殊标识信息。 + * invoiceDetails list 发票详单。 + */ +@Data +@Entity +@Table( + indexes = + @jakarta.persistence.Index( + name = "idx_invoice_org_id", + columnList = "organization_id")) +public class InvoiceEntity extends OrgCommonEntity { + + @Comment("发票代码") + private String invoiceCode; + + @Comment("发票号码") + private String invoiceNumber; + + @Comment("开票日期") + private String invoiceDate; + + @Comment("机器编码") + private String machineCode; + + @Comment("校验码") + private String checkCode; + + @Comment("受票方名称") + private String purchaserName; + + @Comment("密码区") + private String passwordArea; + + @Comment("不含税金额") + private String invoiceAmountPreTax; + + @Comment("发票税额") + private String invoiceTax; + + @Comment("大写金额") + private String totalAmountInWords; + + @Comment("发票金额") + private String totalAmount; + + @Comment("销售方名称") + private String sellerName; + + @Comment("销售方税号") + private String sellerTaxNumber; + + @Comment("销售方地址、电话") + private String sellerContactInfo; + + @Comment("销售方开户行、账号") + private String sellerBankAccountInfo; + + @Comment("开票人") + private String drawer; + + @Comment("标题") + private String title; + + @Comment("发票类型") + private String invoiceType; + + @Comment("联次") + private String formType; + + @Comment("机打发票代码") + private String printedInvoiceCode; + + @Comment("机打发票号码") + private String printedInvoiceNumber; + + @Comment("受票方开户行、账号") + private String purchaserBankAccountInfo; + + @Comment("受票方地址、电话") + private String purchaserContactInfo; + + @Comment("受票方税号") + private String purchaserTaxNumber; + + @Comment("收款人") + private String recipient; + + @Comment("备注") + private String remarks; + + @Comment("复核人") + private String reviewer; + + @Comment("特殊标识信息") + private String specialTag; + + @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) + private List invoiceDetails; + + @ManyToOne private FileEntity file; + + @Comment("归档状态") + @ColumnDefault("'0'") + private String archiveStatus = "0"; +} diff --git a/src/main/java/cn/lihongjie/coal/invoice/mapper/InvoiceMapper.java b/src/main/java/cn/lihongjie/coal/invoice/mapper/InvoiceMapper.java new file mode 100644 index 00000000..d1f9425d --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoice/mapper/InvoiceMapper.java @@ -0,0 +1,19 @@ +package cn.lihongjie.coal.invoice.mapper; + +import cn.lihongjie.coal.base.mapper.BaseMapper; +import cn.lihongjie.coal.base.mapper.CommonEntityMapper; +import cn.lihongjie.coal.base.mapper.CommonMapper; +import cn.lihongjie.coal.invoice.dto.CreateInvoiceDto; +import cn.lihongjie.coal.invoice.dto.InvoiceDto; +import cn.lihongjie.coal.invoice.dto.UpdateInvoiceDto; +import cn.lihongjie.coal.invoice.entity.InvoiceEntity; + +import org.mapstruct.Mapper; +import org.mapstruct.control.DeepClone; + +@Mapper( + componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING, + uses = {CommonMapper.class, CommonEntityMapper.class}, + mappingControl = DeepClone.class) +public interface InvoiceMapper + extends BaseMapper {} diff --git a/src/main/java/cn/lihongjie/coal/invoice/repository/InvoiceRepository.java b/src/main/java/cn/lihongjie/coal/invoice/repository/InvoiceRepository.java new file mode 100644 index 00000000..1fabd385 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoice/repository/InvoiceRepository.java @@ -0,0 +1,15 @@ +package cn.lihongjie.coal.invoice.repository; + +import cn.lihongjie.coal.base.dao.BaseRepository; +import cn.lihongjie.coal.invoice.entity.InvoiceEntity; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface InvoiceRepository extends BaseRepository { + @Query("select false") + boolean isLinked(List ids); +} diff --git a/src/main/java/cn/lihongjie/coal/invoice/service/InvoiceService.java b/src/main/java/cn/lihongjie/coal/invoice/service/InvoiceService.java new file mode 100644 index 00000000..db0e1a9e --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoice/service/InvoiceService.java @@ -0,0 +1,189 @@ +package cn.lihongjie.coal.invoice.service; + +import cn.lihongjie.coal.base.dto.CommonQuery; +import cn.lihongjie.coal.base.dto.IdRequest; +import cn.lihongjie.coal.base.service.BaseService; +import cn.lihongjie.coal.common.Ctx; +import cn.lihongjie.coal.dbFunctions.DbFunctionService; +import cn.lihongjie.coal.exception.BizException; +import cn.lihongjie.coal.file.service.FileService; +import cn.lihongjie.coal.invoice.dto.CreateInvoiceDto; +import cn.lihongjie.coal.invoice.dto.InvoiceDto; +import cn.lihongjie.coal.invoice.dto.UpdateInvoiceDto; +import cn.lihongjie.coal.invoice.entity.InvoiceEntity; +import cn.lihongjie.coal.invoice.mapper.InvoiceMapper; +import cn.lihongjie.coal.invoice.repository.InvoiceRepository; + +import com.aliyun.ocr_api20210707.models.RecognizeInvoiceResponse; +import com.aliyun.ocr_api20210707.models.RecognizeInvoiceResponseBody; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; + +import lombok.Cleanup; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.convert.ConversionService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.InputStream; + +@Service +@Slf4j +@Transactional +public class InvoiceService extends BaseService { + @Autowired ObjectMapper objectMapper; + @Autowired FileService fileService; + @Autowired com.aliyun.ocr_api20210707.Client ocrClient; + @Autowired private InvoiceRepository repository; + @Autowired private InvoiceMapper mapper; + @Autowired private ConversionService conversionService; + @Autowired private DbFunctionService dbFunctionService; + + public InvoiceDto create(CreateInvoiceDto request) { + InvoiceEntity entity = mapper.toEntity(request); + + this.repository.save(entity); + return getById(entity.getId()); + } + + public InvoiceDto update(UpdateInvoiceDto request) { + InvoiceEntity entity = this.repository.get(request.getId()); + if (this.repository.containArchived(request.getId())) { + throw new BizException("部分数据已归档,无法编辑或删除"); + } + this.mapper.updateEntity(entity, request); + + this.repository.save(entity); + + return getById(entity.getId()); + } + + public void delete(IdRequest request) { + if (this.repository.containArchived(request)) { + throw new BizException("部分数据已归档,无法编辑或删除"); + } + boolean linked = this.repository.isLinked(request.getIds()); + + if (linked) { + throw new BizException("数据已被关联,无法删除"); + } + this.repository.deleteAllById(request.getIds()); + } + + public InvoiceDto getById(String id) { + InvoiceEntity entity = repository.get(id); + + return mapper.toDto(entity); + } + + public Page list(CommonQuery query) { + Page page = + repository.findAll( + query.specification(conversionService), + PageRequest.of( + query.getPageNo(), + query.getPageSize(), + Sort.by(query.getOrders()))); + + return page.map(this.mapper::toDto); + } + + public void archive(IdRequest dto) { + this.repository.archive(dto); + } + + public void unarchive(IdRequest dto) { + this.repository.unArchive(dto); + } + + @SneakyThrows + public Object uploadNew(IdRequest request) { + + @Cleanup InputStream download = fileService.download(request.getId()); + + InvoiceEntity invoice = ocr(download); + + if (exists(invoice)) { + throw new BizException("发票已经存在: 发票代码 " + invoice.getInvoiceCode()); + } + + if (CollectionUtils.isNotEmpty(invoice.getInvoiceDetails())) { + + invoice.getInvoiceDetails() + .forEach( + detail -> { + detail.setInvoice(invoice); + }); + } + + this.repository.save(invoice); + + return getById(invoice.getId()); + } + + private boolean exists(InvoiceEntity invoice) { + + return this.repository.count( + new Specification() { + @Override + public Predicate toPredicate( + Root root, + CriteriaQuery query, + CriteriaBuilder criteriaBuilder) { + + return criteriaBuilder.and( + criteriaBuilder.equal( + root.get("invoiceCode"), invoice.getInvoiceCode()), + criteriaBuilder.equal( + root.get("invoiceNumber"), + invoice.getInvoiceNumber()), + criteriaBuilder.equal( + root.get("organizationId"), + Ctx.currentUser().getOrganizationId())); + } + }) + > 0; + } + + private InvoiceEntity ocr(InputStream download) throws Exception { + com.aliyun.ocr_api20210707.models.RecognizeInvoiceRequest recognizeInvoiceRequest = + new com.aliyun.ocr_api20210707.models.RecognizeInvoiceRequest(); + recognizeInvoiceRequest.setBody(download); + com.aliyun.teautil.models.RuntimeOptions runtime = + new com.aliyun.teautil.models.RuntimeOptions(); + + RecognizeInvoiceResponse recognizeInvoiceResponse = + ocrClient.recognizeInvoiceWithOptions(recognizeInvoiceRequest, runtime); + + Integer statusCode = recognizeInvoiceResponse.getStatusCode(); + + if (statusCode != 200) { + + log.info("response {}", recognizeInvoiceResponse); + throw new BizException("发票识别失败"); + } + + RecognizeInvoiceResponseBody body = recognizeInvoiceResponse.getBody(); + + JsonNode jsonNode = objectMapper.readTree(body.getData()); + + JsonNode dataNode = jsonNode.get("data"); + + InvoiceEntity invoiceEntity = objectMapper.convertValue(dataNode, InvoiceEntity.class); + + return invoiceEntity; + } +} diff --git a/src/main/java/cn/lihongjie/coal/invoiceDetail/controller/InvoiceDetailController.java b/src/main/java/cn/lihongjie/coal/invoiceDetail/controller/InvoiceDetailController.java new file mode 100644 index 00000000..dbfc47ea --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoiceDetail/controller/InvoiceDetailController.java @@ -0,0 +1,66 @@ +package cn.lihongjie.coal.invoiceDetail.controller; + +import cn.lihongjie.coal.annotation.OrgScope; +import cn.lihongjie.coal.annotation.SysLog; +import cn.lihongjie.coal.base.dto.CommonQuery; +import cn.lihongjie.coal.base.dto.IdRequest; +import cn.lihongjie.coal.invoiceDetail.dto.CreateInvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.dto.InvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.dto.UpdateInvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.service.InvoiceDetailService; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/invoiceDetail") +@SysLog(module = "发票明细") +@Slf4j +@OrgScope +public class InvoiceDetailController { + @Autowired private InvoiceDetailService service; + + @PostMapping("/create") + public InvoiceDetailDto create(@RequestBody CreateInvoiceDetailDto request) { + return this.service.create(request); + } + + @PostMapping("/update") + public InvoiceDetailDto update(@RequestBody UpdateInvoiceDetailDto request) { + return this.service.update(request); + } + + @PostMapping("/delete") + public Object delete(@RequestBody IdRequest request) { + this.service.delete(request); + return true; + } + + @PostMapping("/getById") + public InvoiceDetailDto getById(@RequestBody IdRequest request) { + return this.service.getById(request.getId()); + } + + @PostMapping("/list") + public Page list(@RequestBody CommonQuery request) { + return this.service.list(request); + } + + @PostMapping("/archive") + public Object archive(@RequestBody IdRequest request) { + this.service.archive(request); + return true; + } + + @PostMapping("/unarchive") + public Object unarchive(@RequestBody IdRequest request) { + this.service.unarchive(request); + return true; + } +} diff --git a/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/CreateInvoiceDetailDto.java b/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/CreateInvoiceDetailDto.java new file mode 100644 index 00000000..f2739eec --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/CreateInvoiceDetailDto.java @@ -0,0 +1,8 @@ +package cn.lihongjie.coal.invoiceDetail.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; + +import lombok.Data; + +@Data +public class CreateInvoiceDetailDto extends OrgCommonDto {} diff --git a/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/InvoiceDetailDto.java b/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/InvoiceDetailDto.java new file mode 100644 index 00000000..5c20c9e8 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/InvoiceDetailDto.java @@ -0,0 +1,48 @@ +package cn.lihongjie.coal.invoiceDetail.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; +import cn.lihongjie.coal.base.dto.SimpleDto; +import cn.lihongjie.coal.common.DictCode; +import cn.lihongjie.coal.pojoProcessor.DictTranslate; + +import jakarta.persistence.ManyToOne; + +import lombok.Data; + +import org.hibernate.annotations.Comment; + +@Data +public class InvoiceDetailDto extends OrgCommonDto { + + @ManyToOne + private SimpleDto invoice; + + @Comment("名称") + private String itemName; + + @Comment("规格型号") + private String specification; + + @Comment("单位") + private String unit; + + @Comment("数量") + private String quantity; + + @Comment("单价") + private Double unitPrice; + + @Comment("金额") + private Double amount; + + @Comment("税率") + private Double taxRate; + + @Comment("税额") + private Double tax; + + private String archiveStatus; + + @DictTranslate(dictKey = DictCode.ARCHIVESTATUS) + private String archiveStatusName; +} diff --git a/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/UpdateInvoiceDetailDto.java b/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/UpdateInvoiceDetailDto.java new file mode 100644 index 00000000..dcc6e5a2 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoiceDetail/dto/UpdateInvoiceDetailDto.java @@ -0,0 +1,8 @@ +package cn.lihongjie.coal.invoiceDetail.dto; + +import cn.lihongjie.coal.base.dto.OrgCommonDto; + +import lombok.Data; + +@Data +public class UpdateInvoiceDetailDto extends OrgCommonDto {} diff --git a/src/main/java/cn/lihongjie/coal/invoiceDetail/entity/InvoiceDetailEntity.java b/src/main/java/cn/lihongjie/coal/invoiceDetail/entity/InvoiceDetailEntity.java new file mode 100644 index 00000000..9745e08e --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoiceDetail/entity/InvoiceDetailEntity.java @@ -0,0 +1,59 @@ +package cn.lihongjie.coal.invoiceDetail.entity; + +import cn.lihongjie.coal.base.entity.OrgCommonEntity; +import cn.lihongjie.coal.invoice.entity.InvoiceEntity; + +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + +import lombok.Data; + +import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.Comment; + +/** + * itemName string 货物或应税劳务、服务名称。 specification string 规格型号。 unit string 单位。 quantity string 数量。 + * unitPrice string 单价。 amount string 金额。 taxRate string 税率。 tax string 税额。 + */ +@Data +@Entity +@Table( + indexes = + @jakarta.persistence.Index( + name = "idx_invoiceDetail_org_id", + columnList = "organization_id")) +public class InvoiceDetailEntity extends OrgCommonEntity { + + + @ManyToOne + private InvoiceEntity invoice; + + @Comment("名称") + private String itemName; + + @Comment("规格型号") + private String specification; + + @Comment("单位") + private String unit; + + @Comment("数量") + private String quantity; + + @Comment("单价") + private Double unitPrice; + + @Comment("金额") + private Double amount; + + @Comment("税率") + private Double taxRate; + + @Comment("税额") + private Double tax; + + @Comment("归档状态") + @ColumnDefault("'0'") + private String archiveStatus = "0"; +} diff --git a/src/main/java/cn/lihongjie/coal/invoiceDetail/mapper/InvoiceDetailMapper.java b/src/main/java/cn/lihongjie/coal/invoiceDetail/mapper/InvoiceDetailMapper.java new file mode 100644 index 00000000..b8b28515 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoiceDetail/mapper/InvoiceDetailMapper.java @@ -0,0 +1,23 @@ +package cn.lihongjie.coal.invoiceDetail.mapper; + +import cn.lihongjie.coal.base.mapper.BaseMapper; +import cn.lihongjie.coal.base.mapper.CommonEntityMapper; +import cn.lihongjie.coal.base.mapper.CommonMapper; +import cn.lihongjie.coal.invoiceDetail.dto.CreateInvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.dto.InvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.dto.UpdateInvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.entity.InvoiceDetailEntity; + +import org.mapstruct.Mapper; +import org.mapstruct.control.DeepClone; + +@Mapper( + componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING, + uses = {CommonMapper.class, CommonEntityMapper.class}, + mappingControl = DeepClone.class) +public interface InvoiceDetailMapper + extends BaseMapper< + InvoiceDetailEntity, + InvoiceDetailDto, + CreateInvoiceDetailDto, + UpdateInvoiceDetailDto> {} diff --git a/src/main/java/cn/lihongjie/coal/invoiceDetail/repository/InvoiceDetailRepository.java b/src/main/java/cn/lihongjie/coal/invoiceDetail/repository/InvoiceDetailRepository.java new file mode 100644 index 00000000..aa03f45c --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoiceDetail/repository/InvoiceDetailRepository.java @@ -0,0 +1,15 @@ +package cn.lihongjie.coal.invoiceDetail.repository; + +import cn.lihongjie.coal.base.dao.BaseRepository; +import cn.lihongjie.coal.invoiceDetail.entity.InvoiceDetailEntity; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface InvoiceDetailRepository extends BaseRepository { + @Query("select false") + boolean isLinked(List ids); +} diff --git a/src/main/java/cn/lihongjie/coal/invoiceDetail/service/InvoiceDetailService.java b/src/main/java/cn/lihongjie/coal/invoiceDetail/service/InvoiceDetailService.java new file mode 100644 index 00000000..dc916c1e --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/invoiceDetail/service/InvoiceDetailService.java @@ -0,0 +1,94 @@ +package cn.lihongjie.coal.invoiceDetail.service; + +import cn.lihongjie.coal.base.dto.CommonQuery; +import cn.lihongjie.coal.base.dto.IdRequest; +import cn.lihongjie.coal.base.service.BaseService; +import cn.lihongjie.coal.dbFunctions.DbFunctionService; +import cn.lihongjie.coal.exception.BizException; +import cn.lihongjie.coal.invoiceDetail.dto.CreateInvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.dto.InvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.dto.UpdateInvoiceDetailDto; +import cn.lihongjie.coal.invoiceDetail.entity.InvoiceDetailEntity; +import cn.lihongjie.coal.invoiceDetail.mapper.InvoiceDetailMapper; +import cn.lihongjie.coal.invoiceDetail.repository.InvoiceDetailRepository; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.convert.ConversionService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Slf4j +@Transactional +public class InvoiceDetailService + extends BaseService { + @Autowired private InvoiceDetailRepository repository; + + @Autowired private InvoiceDetailMapper mapper; + + @Autowired private ConversionService conversionService; + + @Autowired private DbFunctionService dbFunctionService; + + public InvoiceDetailDto create(CreateInvoiceDetailDto request) { + InvoiceDetailEntity entity = mapper.toEntity(request); + + this.repository.save(entity); + return getById(entity.getId()); + } + + public InvoiceDetailDto update(UpdateInvoiceDetailDto request) { + InvoiceDetailEntity entity = this.repository.get(request.getId()); + if (this.repository.containArchived(request.getId())) { + throw new BizException("部分数据已归档,无法编辑或删除"); + } + this.mapper.updateEntity(entity, request); + + this.repository.save(entity); + + return getById(entity.getId()); + } + + public void delete(IdRequest request) { + if (this.repository.containArchived(request)) { + throw new BizException("部分数据已归档,无法编辑或删除"); + } + boolean linked = this.repository.isLinked(request.getIds()); + + if (linked) { + throw new BizException("数据已被关联,无法删除"); + } + this.repository.deleteAllById(request.getIds()); + } + + public InvoiceDetailDto getById(String id) { + InvoiceDetailEntity entity = repository.get(id); + + return mapper.toDto(entity); + } + + public Page list(CommonQuery query) { + Page page = + repository.findAll( + query.specification(conversionService), + PageRequest.of( + query.getPageNo(), + query.getPageSize(), + Sort.by(query.getOrders()))); + + return page.map(this.mapper::toDto); + } + + public void archive(IdRequest dto) { + this.repository.archive(dto); + } + + public void unarchive(IdRequest dto) { + this.repository.unArchive(dto); + } +} diff --git a/src/main/resources/scripts/dict/enum/invoiceDetailDict.groovy b/src/main/resources/scripts/dict/enum/invoiceDetailDict.groovy new file mode 100644 index 00000000..388654e7 --- /dev/null +++ b/src/main/resources/scripts/dict/enum/invoiceDetailDict.groovy @@ -0,0 +1,19 @@ + +package scripts.dict + +import cn.lihongjie.coal.base.dto.CommonQuery +import cn.lihongjie.coal.invoiceDetail.controller.InvoiceDetailController +import com.fasterxml.jackson.databind.ObjectMapper +import org.springframework.context.ApplicationContext + +ApplicationContext ioc = ioc + +def controller = ioc.getBean(InvoiceDetailController.class) +def objectMapper = ioc.getBean(ObjectMapper.class) as ObjectMapper + + + + +return controller.list(params!=null ? objectMapper.convertValue(params, CommonQuery.class ) : new CommonQuery()) + + diff --git a/src/main/resources/scripts/dict/enum/invoiceDict.groovy b/src/main/resources/scripts/dict/enum/invoiceDict.groovy new file mode 100644 index 00000000..fec7b2e8 --- /dev/null +++ b/src/main/resources/scripts/dict/enum/invoiceDict.groovy @@ -0,0 +1,19 @@ + +package scripts.dict + +import cn.lihongjie.coal.base.dto.CommonQuery +import cn.lihongjie.coal.invoice.controller.InvoiceController +import com.fasterxml.jackson.databind.ObjectMapper +import org.springframework.context.ApplicationContext + +ApplicationContext ioc = ioc + +def controller = ioc.getBean(InvoiceController.class) +def objectMapper = ioc.getBean(ObjectMapper.class) as ObjectMapper + + + + +return controller.list(params!=null ? objectMapper.convertValue(params, CommonQuery.class ) : new CommonQuery()) + +