[프로젝트] 웹 siCloud - day12

_bean_·2023년 8월 3일
0

[팀 프로젝트] siCloud

목록 보기
13/21
post-thumbnail

오류 및 문제점

1. cannot deserialize from Object value

  • 문제점: Entity 클래스를 반환하는 중 JSON Serialize 과정에서 에러가 발생했다.
  • 해결방안: DTO에 @NoArgsConstructor을 추가한다.
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ShoppingDTO {

}

2. 외부 API 호출

  • 문제점: Service 내부에서 api를 호출해야 한다.
  • 해결방안: WebClient를 이용해 요청을 생성한다.
implementation 'org.springframework.boot:spring-boot-starter-webflux'

진행 상황

1. History 트리거를 위한 시퀀스 생성

-- 시퀀스 저장할 테이블
create TABLE SEQUENCES(
    name varchar(32) primary key,
    currval BIGINT unsigned
);

-- 시퀀스 생성하는 프로시저 
DELIMITER //
    create procedure `create_sequence` (IN seq_name text, IN start_val int)
    modifies sql data
    deterministic
    begin
        delete from SEQUENCES where name = seq_name;
        insert into SEQUENCES values(seq_name, start_val);
    END //
DELIMITER ;

-- 다음 값으로 증가시키는 함수
DELIMITER //
    create function `seq_nextval` (seq_name VARCHAR(32))
    RETURNS BIGINT unsigned
    MODIFIES SQL DATA
    Deterministic
    begin
        declare ret BIGINT unsigned;
        update SEQUENCES set currval = currval +1 where name = seq_name;
        select currval into ret from SEQUENCES where name = seq_name limit 1;
        return ret;
    END //
DELIMITER ;

-- 시퀀스 생성
CALL create_sequence('seq_history', 0);

2. 트리거를 이용해 ExportProductHistory에 추가

  • 출고 완료, 주문 취소로 상태가 변경되면 히스토리에 추가
DELIMITER //
CREATE TRIGGER trigger_history_export_product
AFTER UPDATE ON export_product
FOR EACH ROW
BEGIN
	INSERT INTO export_product_history(history_export_product_no, updated_date, updated_type, amount, export_date, export_no, export_product_no, invoice_no, order_status, product_no, selling_price)
	VALUES(seq_nextval('seq_history'), CURRENT_TIMESTAMP(), 'UPDATE', OLD.amount, OLD.export_date, OLD.export_no, OLD.export_product_no, OLD.invoice_no, OLD.order_status, OLD.product_no, OLD.selling_price);
END //
DELIMITER ;

3. 송장 출력

  • 트리거
    • 쇼핑몰 상품 상태: 배송준비중 -> 배송중
    • 쇼핑몰 상품 송장 번호, 출고 일자 추가
    • 상품 재고 감소
DELIMITER //
CREATE TRIGGER print_invoice
AFTER UPDATE ON export_product
FOR EACH ROW
BEGIN
	UPDATE shopping_product SET order_status = '배송중', export_date=NEW.export_date, invoice_no=NEW.invoice_no
	WHERE export_no = NEW.export_no AND product_no = NEW.product_no;
	UPDATE product SET current_stock = current_stock - NEW.amount
	WHERE product_no = NEW.product_no;
END //
DELIMITER ;
  • 서비스 코드
@Transactional	
public List<ExportInvoiceDTO> printInvoice(String exportNo, List<ExportInvoiceDTO> invoiceProducts) {
	List<ExportInvoiceDTO> exportInvoiceDTOs = new ArrayList<>();
	List<ExportProduct> exportProducts = new ArrayList<>();
	String invoiceNo = String.valueOf(new Date().getTime());
		
	// 송장 출력
	for(ExportInvoiceDTO invoiceProduct : invoiceProducts) {
		int amount = invoiceProduct.getAmount();
		String productNo = invoiceProduct.getProductNo();
		ExportInvoiceDTO exportInvoiceDTO = ExportInvoiceDTO
				.builder()
				.amount(amount)
				.invoiceNo(isAvailableForExport(productNo, amount) ? invoiceNo : null)
				.productNo(invoiceProduct.getProductNo())
				.build();
			
		// 재고가 남은 경우에만 ExportProduct 업데이트 
		if(exportInvoiceDTO.getInvoiceNo() != null) {
			ExportProduct exportProduct = exportProductRepository.findByExports_ExportNoAndProduct_ProductNo(exportNo, productNo);
			ExportProductHistory exportProductHistory = exportProduct.toExportProductHistory();
				
			exportProduct.updateExportProductByExportInvoiceDTO(exportInvoiceDTO);
			exportProducts.add(exportProduct);
		}
		exportInvoiceDTOs.add(exportInvoiceDTO);
	}
		
	exportProductRepository.saveAll(exportProducts);
		
	return exportInvoiceDTOs;
}

private boolean isAvailableForExport (String productNo, int amount) {
	Product product = productService.findByProductNo(productNo);
		
	return amount <= product.getCurrentStock();
}

4. 상품 현재 재고 히스토리 테이블 생성

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class CurrentStockHistory {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long currentStockHistoryNo;
	
	@NotNull
	private String productNo;
	
	@CreationTimestamp
	private Timestamp updatedDate;
	
	@NotNull
	private int preStock;
	
	@NotNull
	private int currentStock;
	
	@NotNull
	private int updatedCount;
}

5. 출고 주문건 수집 쇼핑몰 요청으로 수정중

  • 변경전: shoppingService를 이용해 직접 shopping 테이블에서 주문건 수집
  • 변경후: WebClient를 이용해 쇼핑몰로 주문 수집 요청 전달
// ShoppingController.java
@GetMapping("/shop/order/send/{sellerNo}")
public List<ShoppingDTO> sendOrderToWMS(@PathVariable Long sellerNo) {
	return shoppingService.sendOrderToWMS(sellerNo);
}

// ExportsService.java
@Transactional
public List<ExportsDTO> register(Long sellerNo, int pageNum, int countPerPage) {
	Seller seller = sellerService.findById(sellerNo);
    // 현재 해당 라인에서 java.lang.ClassNotFoundException 에러 발생
	WebClient webClient = WebClient.builder().baseUrl("http://localhost:4885").build();
	List<ShoppingDTO> shoppingDTOs = webClient
			.get()
			.uri(UriBuilder -> UriBuilder.path("/shop/order/send/" + sellerNo).build())
			.retrieve()
			.bodyToMono(List.class)
			.block();
		
	for(ShoppingDTO shoppingDTO: shoppingDTOs) {
		List<ExportProduct> exportProducts = new ArrayList<>();
		Exports exports = shoppingDTO.toExports(seller);
			
		Exports savedExports = exportsRepository.save(exports);
			
		for(ShoppingProductDTO shoppingProductDTO : shoppingDTO.getOrderedProducts()) {
			Product product = productService.findByProductNo(shoppingProductDTO.getProductNo());
			ExportProduct exportProduct = shoppingProductDTO.toExportProduct(savedExports, product);
				
			exportProducts.add(exportProduct);
		}
			
		List<ExportProduct> savedExportProducts = exportProductRepository.saveAll(exportProducts);
		if(savedExports == null || savedExportProducts == null) findExports(sellerNo, 0, countPerPage);
			
	}
		
	return findExports(sellerNo, 0, countPerPage);
}

6. 컨트롤러 테스트

  • collectExports 진행중


참고 자료

profile
어쩌다 풀스택 :3

0개의 댓글