-
Notifications
You must be signed in to change notification settings - Fork 0
Fix/357 brand sponsor list #360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
deaa812
07f2f65
c212989
425f027
77e42ff
1419bcd
d30b559
7fe4e0c
4a9dad8
c83e4a0
7785aa3
ede3b9d
4ca2047
63d111c
a227c32
308cfbe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| ALTER TABLE brand_available_sponsor | ||
| ADD COLUMN shipping_type VARCHAR(50) NULL; | ||
|
|
||
| ALTER TABLE brand_sponsor_item | ||
| ADD COLUMN sponsor_id BIGINT NULL; | ||
|
|
||
| UPDATE brand_available_sponsor bas | ||
| JOIN brand_sponsor_info bsi ON bas.id = bsi.sponsor_id | ||
| SET bas.shipping_type = bsi.shipping_type; | ||
|
|
||
| UPDATE brand_sponsor_item bsi_item | ||
| JOIN brand_sponsor_info bsi ON bsi_item.sponsor_info_id = bsi.id | ||
| SET bsi_item.sponsor_id = bsi.sponsor_id; | ||
|
|
||
| ALTER TABLE brand_sponsor_item | ||
| DROP FOREIGN KEY FKet9dtmuqr2ba3moigtsxiabq2, | ||
| DROP COLUMN sponsor_info_id, | ||
| MODIFY sponsor_id BIGINT NOT NULL, | ||
| ADD CONSTRAINT fk_brand_sponsor_item_sponsor | ||
| FOREIGN KEY (sponsor_id) REFERENCES brand_available_sponsor(id); | ||
|
|
||
| DROP TABLE brand_sponsor_info; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ | |
| import com.example.RealMatch.brand.domain.entity.BrandDescribeTag; | ||
| import com.example.RealMatch.brand.domain.entity.BrandImage; | ||
| import com.example.RealMatch.brand.domain.entity.BrandLike; | ||
| import com.example.RealMatch.brand.domain.entity.BrandSponsorImage; | ||
| import com.example.RealMatch.brand.domain.entity.enums.IndustryType; | ||
| import com.example.RealMatch.brand.domain.repository.BrandAvailableSponsorRepository; | ||
| import com.example.RealMatch.brand.domain.repository.BrandCategoryRepository; | ||
|
|
@@ -31,7 +32,6 @@ | |
| import com.example.RealMatch.brand.presentation.dto.request.BrandBeautyUpdateRequestDto; | ||
| import com.example.RealMatch.brand.presentation.dto.request.BrandFashionCreateRequestDto; | ||
| import com.example.RealMatch.brand.presentation.dto.request.BrandFashionUpdateRequestDto; | ||
| import com.example.RealMatch.brand.presentation.dto.response.ActionDto; | ||
| import com.example.RealMatch.brand.presentation.dto.response.BeautyFilterDto; | ||
| import com.example.RealMatch.brand.presentation.dto.response.BrandCreateResponseDto; | ||
| import com.example.RealMatch.brand.presentation.dto.response.BrandDetailResponseDto; | ||
|
|
@@ -56,12 +56,9 @@ | |
| import com.example.RealMatch.user.domain.repository.UserRepository; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| @Transactional(readOnly = true) | ||
| @Slf4j | ||
| public class BrandService { | ||
|
|
||
| private final BrandRepository brandRepository; | ||
|
|
@@ -78,7 +75,6 @@ public class BrandService { | |
| private final TagRepository tagRepository; | ||
|
|
||
| private final UserRepository userRepository; | ||
|
|
||
| private static final Pattern URL_PATTERN = Pattern.compile("^https?://([\\da-z.-]+)\\.([a-z.]{2,6})[/\\w .-]*/?$"); | ||
|
|
||
| // ******** // | ||
|
|
@@ -222,54 +218,100 @@ public SponsorProductDetailResponseDto getSponsorProductDetail(Long brandId, Lon | |
| throw new IllegalArgumentException("해당 브랜드의 제품이 아닙니다."); | ||
| } | ||
|
|
||
| List<String> mockImageUrls = List.of( | ||
| "https://cdn.example.com/products/100/1.png", | ||
| "https://cdn.example.com/products/100/2.png", | ||
| "https://cdn.example.com/products/100/3.png" | ||
| ); | ||
| return buildSponsorProductDetailResponse(brand, product); | ||
| } | ||
|
|
||
| List<String> mockCategories = List.of("스킨케어", "메이크업"); | ||
| @Transactional(readOnly = true) | ||
| public List<SponsorProductListResponseDto> getSponsorProducts(Long brandId) { | ||
| Brand brand = brandRepository.findById(brandId) | ||
| .orElseThrow(() -> new ResourceNotFoundException("브랜드 정보를 찾을 수 없습니다.")); | ||
|
|
||
| List<SponsorItemDto> mockItems = List.of( | ||
| SponsorItemDto.builder().itemId(1L).availableType("SAMPLE").availableQuantity(1).availableSize(50).sizeUnit("ml").build(), | ||
| SponsorItemDto.builder().itemId(2L).availableType("FULL").availableQuantity(1).availableSize(100).sizeUnit("ml").build() | ||
| ); | ||
| List<BrandAvailableSponsor> products = brandAvailableSponsorRepository.findByBrandIdWithImages(brandId); | ||
| List<String> categories = buildCategories(brand); | ||
|
|
||
| SponsorInfoDto sponsorInfo = SponsorInfoDto.builder() | ||
| .items(mockItems) | ||
| .shippingType("CREATOR_PAY") | ||
| .build(); | ||
| return products.stream() | ||
| .map(product -> buildSponsorProductListResponse(brand, product, categories)) | ||
| .collect(Collectors.toList()); | ||
|
Comment on lines
232
to
234
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
예를 들어, @Query("SELECT s FROM BrandAvailableSponsor s LEFT JOIN FETCH s.campaign LEFT JOIN FETCH s.images WHERE s.brand.id = :brandId")
List<BrandAvailableSponsor> findByBrandIdWithCampaignAndImages(@Param("brandId") Long brandId);References
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반영하겠습니다. |
||
| } | ||
|
|
||
| ActionDto action = ActionDto.builder() | ||
| .canProposeCampaign(true) | ||
| .proposeCampaignCtaText("캠페인 제안하기") | ||
| .build(); | ||
| private SponsorProductDetailResponseDto buildSponsorProductDetailResponse( | ||
| Brand brand, | ||
| BrandAvailableSponsor product | ||
| ) { | ||
| List<String> imageUrls = buildProductImageUrls(product); | ||
| List<String> categories = buildCategories(brand); | ||
| SponsorInfoDto sponsorInfoDto = buildSponsorInfo(brand, product); | ||
|
|
||
| return SponsorProductDetailResponseDto.builder() | ||
| .brandId(brand.getId()) | ||
| .brandName(brand.getBrandName()) | ||
| .productId(product.getId()) | ||
| .productName(product.getName()) | ||
| .productDescription(product.getCampaign().getDescription()) | ||
| .productImageUrls(mockImageUrls) | ||
| .categories(mockCategories) | ||
| .sponsorInfo(sponsorInfo) | ||
| .action(action) | ||
| .productImageUrls(imageUrls) | ||
| .categories(categories) | ||
| .sponsorInfo(sponsorInfoDto) | ||
| .build(); | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| public List<SponsorProductListResponseDto> getSponsorProducts(Long brandId) { | ||
| brandRepository.findById(brandId) | ||
| .orElseThrow(() -> new ResourceNotFoundException("브랜드 정보를 찾을 수 없습니다.")); | ||
| private SponsorProductListResponseDto buildSponsorProductListResponse( | ||
| Brand brand, | ||
| BrandAvailableSponsor product, | ||
| List<String> categories | ||
| ) { | ||
| List<String> imageUrls = buildProductImageUrls(product); | ||
| SponsorInfoDto sponsorInfoDto = buildSponsorInfo(brand, product); | ||
|
|
||
| List<BrandAvailableSponsor> products = brandAvailableSponsorRepository.findByBrandIdWithImages(brandId); | ||
| return SponsorProductListResponseDto.from(brand, product, imageUrls, categories, sponsorInfoDto); | ||
| } | ||
|
|
||
| return products.stream() | ||
| .map(SponsorProductListResponseDto::from) | ||
| private List<String> buildProductImageUrls(BrandAvailableSponsor product) { | ||
| List<BrandSponsorImage> images = product.getImages(); | ||
| if (images == null || images.isEmpty()) { | ||
| return List.of(); | ||
| } | ||
| return images.stream() | ||
| .map(BrandSponsorImage::getImageUrl) | ||
| .collect(Collectors.toList()); | ||
| } | ||
|
|
||
| private List<String> buildCategories(Brand brand) { | ||
| if (brand.getIndustryType() == null) { | ||
| return List.of(); | ||
| } | ||
| if (brand.getIndustryType() == IndustryType.BEAUTY) { | ||
| return tagBrandRepository.findTagNamesByBrandIdAndTagCategory( | ||
| brand.getId(), TagCategory.BEAUTY_INTEREST_STYLE.getDescription()); | ||
| } | ||
| if (brand.getIndustryType() == IndustryType.FASHION) { | ||
|
Comment on lines
+284
to
+285
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| return tagBrandRepository.findTagNamesByBrandIdAndTagCategory( | ||
| brand.getId(), TagCategory.FASHION_INTEREST_ITEM.getDescription()); | ||
| } | ||
|
Comment on lines
+281
to
+288
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 두 개의 독립적인 if (brand.getIndustryType() == IndustryType.BEAUTY) {
return tagBrandRepository.findTagNamesByBrandIdAndTagCategory(
brand.getId(), TagCategory.BEAUTY_INTEREST_STYLE.getDescription());
} else if (brand.getIndustryType() == IndustryType.FASHION) {
return tagBrandRepository.findTagNamesByBrandIdAndTagCategory(
brand.getId(), TagCategory.FASHION_INTEREST_ITEM.getDescription());
} |
||
| return List.of(); | ||
| } | ||
|
Comment on lines
277
to
290
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 수정완료 상세 카테고리를 반환해야 하는게 맞습니다. |
||
|
|
||
| private SponsorInfoDto buildSponsorInfo(Brand brand, BrandAvailableSponsor sponsor) { | ||
| if (sponsor.getItems().isEmpty()) { | ||
| return null; | ||
| } | ||
| List<SponsorItemDto> items = sponsor.getItems().stream() | ||
| .map(item -> { | ||
| SponsorItemDto.SponsorItemDtoBuilder builder = SponsorItemDto.builder() | ||
| .availableQuantity(item.getAvailableQuantity()); | ||
| if (brand.getIndustryType() == IndustryType.BEAUTY) { | ||
| builder.itemId(item.getId()) | ||
| .availableType(item.getAvailableType()) | ||
| .availableSize(item.getAvailableSize()) | ||
| .shippingType(item.getShippingType()); | ||
| } | ||
| return builder.build(); | ||
| }) | ||
| .collect(Collectors.toList()); | ||
|
|
||
| return SponsorInfoDto.builder() | ||
| .items(items) | ||
| .build(); | ||
| } | ||
|
Comment on lines
+292
to
+313
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the |
||
|
|
||
| // ******** // | ||
| // 브랜드 생성 // | ||
| // ******** // | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,6 @@ | |
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| import com.example.RealMatch.campaign.domain.entity.Campaign; | ||
| import com.example.RealMatch.global.common.DeleteBaseEntity; | ||
|
|
||
| import jakarta.persistence.CascadeType; | ||
|
|
@@ -32,10 +31,6 @@ public class BrandAvailableSponsor extends DeleteBaseEntity { | |
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "campaign_id", nullable = false) | ||
| private Campaign campaign; | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "brand_id", nullable = false) | ||
| private Brand brand; | ||
|
|
@@ -46,25 +41,20 @@ public class BrandAvailableSponsor extends DeleteBaseEntity { | |
| @Column(length = 1000) | ||
| private String content; | ||
|
|
||
| // 1. 총 모집 인원 필드 추가 | ||
| @Column(name = "total_count", nullable = false) | ||
| private Integer totalCount; | ||
|
|
||
| // 2. 현재 모집된 인원 필드 추가 (기본값 0) | ||
| @Column(name = "current_count", nullable = false) | ||
| private Integer currentCount = 0; | ||
| @OneToMany(mappedBy = "sponsor", fetch = FetchType.LAZY, cascade = CascadeType.ALL) | ||
| private List<BrandSponsorItem> items = new ArrayList<>(); | ||
|
Comment on lines
+44
to
+45
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The migration script |
||
|
|
||
| // 3. 이미지 리스트 (1:N 관계) 필드 추가 | ||
| // mappedBy는 BrandSponsorImage 엔티티에 있는 변수명과 일치해야 합니다. | ||
| @OneToMany(mappedBy = "sponsor", fetch = FetchType.LAZY, cascade = CascadeType.ALL) | ||
| private List<BrandSponsorImage> images = new ArrayList<>(); | ||
|
|
||
| @Builder | ||
| public BrandAvailableSponsor(Campaign campaign, Brand brand, String name, String content, Integer totalCount) { | ||
| this.campaign = campaign; | ||
| public BrandAvailableSponsor( | ||
| Brand brand, | ||
| String name, | ||
| String content | ||
| ) { | ||
| this.brand = brand; | ||
| this.name = name; | ||
| this.content = content; | ||
| this.totalCount = totalCount; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| package com.example.RealMatch.brand.domain.entity; | ||
|
|
||
| import com.example.RealMatch.global.common.DeleteBaseEntity; | ||
|
|
||
| import jakarta.persistence.Column; | ||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.FetchType; | ||
| import jakarta.persistence.GeneratedValue; | ||
| import jakarta.persistence.GenerationType; | ||
| import jakarta.persistence.Id; | ||
| import jakarta.persistence.JoinColumn; | ||
| import jakarta.persistence.ManyToOne; | ||
| import jakarta.persistence.Table; | ||
| import lombok.AccessLevel; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Entity | ||
| @Table(name = "brand_sponsor_item") | ||
| @Getter | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| public class BrandSponsorItem extends DeleteBaseEntity { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "sponsor_id", nullable = false) | ||
| private BrandAvailableSponsor sponsor; | ||
|
|
||
| @Column(name = "available_type", length = 30) | ||
| private String availableType; | ||
|
|
||
| @Column(name = "available_quantity") | ||
| private Integer availableQuantity; | ||
|
|
||
| @Column(name = "available_size") | ||
| private Integer availableSize; | ||
|
|
||
| @Column(name = "shipping_type", length = 30) | ||
| private String shippingType; | ||
|
|
||
| @Builder | ||
| public BrandSponsorItem( | ||
| BrandAvailableSponsor sponsor, | ||
| String availableType, | ||
| Integer availableQuantity, | ||
| Integer availableSize, | ||
| String shippingType | ||
| ) { | ||
| this.sponsor = sponsor; | ||
| this.availableType = availableType; | ||
| this.availableQuantity = availableQuantity; | ||
| this.availableSize = availableSize; | ||
| this.shippingType = shippingType; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration script adds a
shipping_typecolumn to thebrand_available_sponsortable. However, theBrandAvailableSponsorJPA entity (src/main/java/com/example/RealMatch/brand/domain/entity/BrandAvailableSponsor.java) does not include this field. This inconsistency will lead to a mismatch between the database schema and the application's entity model, potentially causing runtime errors or unexpected behavior during data persistence or retrieval. Given thatBrandSponsorItemalready has ashippingType, it's likely thatshippingTypeis intended to be item-specific, not at theBrandAvailableSponsorlevel.