22
33import com .smalltrend .dto .products .UnitConversionRequest ;
44import com .smalltrend .dto .products .UnitConversionResponse ;
5+ import com .smalltrend .entity .InventoryStock ;
56import com .smalltrend .entity .Product ;
6- import com .smalltrend .entity .ProductVariant ;
77import com .smalltrend .entity .ProductBatch ;
8- import com .smalltrend .entity .InventoryStock ;
8+ import com .smalltrend .entity .ProductVariant ;
99import com .smalltrend .entity .Unit ;
1010import com .smalltrend .entity .UnitConversion ;
1111import com .smalltrend .repository .InventoryStockRepository ;
1212import com .smalltrend .repository .ProductBatchRepository ;
1313import com .smalltrend .repository .ProductVariantRepository ;
1414import com .smalltrend .repository .UnitConversionRepository ;
1515import com .smalltrend .repository .UnitRepository ;
16-
1716import lombok .RequiredArgsConstructor ;
1817import org .springframework .stereotype .Service ;
1918import org .springframework .transaction .annotation .Transactional ;
2019
21- import java .time . LocalDate ;
20+ import java .math . BigDecimal ;
2221import java .math .RoundingMode ;
22+ import java .time .LocalDate ;
2323import java .util .Collections ;
2424import java .util .List ;
2525import java .util .Map ;
@@ -58,7 +58,7 @@ public List<UnitConversionResponse> getConversionsByVariantId(Integer variantId)
5858 public UnitConversionResponse addConversion (Integer variantId , UnitConversionRequest request ) {
5959 ProductVariant baseVariant = productVariantRepository .findById (variantId )
6060 .orElseThrow (() -> new RuntimeException (
61- "Không tìm thấy biến thể với ID: " + variantId ));
61+ "Không tìm thấy biến thể với ID: " + variantId ));
6262
6363 Integer productId = baseVariant .getProduct () != null ? baseVariant .getProduct ().getId () : null ;
6464 Integer unitId = baseVariant .getUnit () != null ? baseVariant .getUnit ().getId () : null ;
@@ -67,20 +67,19 @@ public UnitConversionResponse addConversion(Integer variantId, UnitConversionReq
6767 List <UnitConversion > conversionsToThisUnit = unitConversionRepository .findByProductIdAndToUnitId (productId , unitId );
6868 boolean isConversionDerivedVariant = conversionsToThisUnit .stream ()
6969 .filter (conversion -> conversion != null
70- && conversion .getVariant () != null
71- && conversion .getVariant ().getId () != null
72- && !conversion .getVariant ().getId ().equals (baseVariant .getId ()))
70+ && conversion .getVariant () != null
71+ && conversion .getVariant ().getId () != null
72+ && !conversion .getVariant ().getId ().equals (baseVariant .getId ()))
7373 .anyMatch (conversion -> hasSameAttributes (conversion .getVariant (), baseVariant ));
7474
7575 if (isConversionDerivedVariant ) {
7676 throw new RuntimeException ("Chỉ biến thể đơn vị gốc mới được phép thêm quy đổi đơn vị." );
7777 }
7878 }
7979
80-
8180 Unit toUnit = unitRepository .findById (request .getToUnitId ())
8281 .orElseThrow (() -> new RuntimeException (
83- "Không tìm thấy đơn vị với ID: " + request .getToUnitId ()));
82+ "Không tìm thấy đơn vị với ID: " + request .getToUnitId ()));
8483
8584 if (unitConversionRepository .existsByVariantIdAndToUnitId (variantId , request .getToUnitId ())) {
8685 throw new RuntimeException (
@@ -89,38 +88,41 @@ public UnitConversionResponse addConversion(Integer variantId, UnitConversionReq
8988
9089 Product product = baseVariant .getProduct ();
9190
91+ BigDecimal resolvedSellPrice = request .getSellPrice () != null
92+ ? request .getSellPrice ()
93+ : baseVariant .getSellPrice ();
94+ if (resolvedSellPrice == null ) {
95+ throw new RuntimeException ("Giá bán quy đổi không được để trống." );
96+ }
97+
9298 // ─── 1. Tạo quy đổi đơn vị ────────────────────────────────────────────
9399 UnitConversion conversion = UnitConversion .builder ()
94100 .variant (baseVariant )
95101 .toUnit (toUnit )
96102 .conversionFactor (request .getConversionFactor ())
97- .sellPrice (request . getSellPrice () )
103+ .sellPrice (resolvedSellPrice )
98104 .description (request .getDescription ())
99105 .isActive (request .getIsActive () != null ? request .getIsActive () : true )
100106 .build ();
101107
102108 UnitConversion savedConversion = unitConversionRepository .save (conversion );
103109
104110 // ─── 2. Tự động tạo Product Variant mới cho đơn vị đóng gói ───────────
105- // Sinh SKU: VD BEV-COCA-COLA-LOC6
106111 String autoSku = productVariantService .generateSkuForConversion (
107112 baseVariant , toUnit , request .getConversionFactor ());
108113
109- // Tạo variant mới với đơn vị đích.
110- // Copy attributes từ base variant (mỗi variant có variant_id riêng nên không xung đột key).
111114 ProductVariant packagingVariant = ProductVariant .builder ()
112115 .product (product )
113116 .sku (autoSku )
114117 .unit (toUnit )
115- .sellPrice (request . getSellPrice () )
118+ .sellPrice (resolvedSellPrice )
116119 .isActive (baseVariant .isActive ())
117120 .attributes (baseVariant .getAttributes () != null
118121 ? new java .util .HashMap <>(baseVariant .getAttributes ())
119122 : new java .util .HashMap <>())
120123 .build ();
121124
122- ProductVariant savedVariant = productVariantRepository .saveAndFlush (packagingVariant ); // cần id ngay để sinh barcode
123-
125+ ProductVariant savedVariant = productVariantRepository .saveAndFlush (packagingVariant );
124126
125127 // ─── 3. Sinh barcode nội bộ ──────
126128 String autoBarcode = productVariantService .generateInternalBarcodeForPackaging (
@@ -174,22 +176,28 @@ public UnitConversionResponse addConversion(Integer variantId, UnitConversionReq
174176 public UnitConversionResponse updateConversion (Integer conversionId , UnitConversionRequest request ) {
175177 UnitConversion conversion = unitConversionRepository .findById (conversionId )
176178 .orElseThrow (() -> new RuntimeException (
177- "Không tìm thấy quy đổi với ID: " + conversionId ));
179+ "Không tìm thấy quy đổi với ID: " + conversionId ));
178180
179181 Unit toUnit = unitRepository .findById (request .getToUnitId ())
180182 .orElseThrow (() -> new RuntimeException (
181- "Không tìm thấy đơn vị với ID: " + request .getToUnitId ()));
183+ "Không tìm thấy đơn vị với ID: " + request .getToUnitId ()));
182184
183- // Check duplicate (excluding current record)
184185 if (unitConversionRepository .existsByVariantIdAndToUnitIdAndIdNot (
185186 conversion .getVariant ().getId (), request .getToUnitId (), conversionId )) {
186187 throw new RuntimeException (
187188 "Quy đổi sang đơn vị '" + toUnit .getName () + "' đã tồn tại cho biến thể này!" );
188189 }
189190
191+ BigDecimal resolvedSellPrice = request .getSellPrice () != null
192+ ? request .getSellPrice ()
193+ : conversion .getSellPrice ();
194+ if (resolvedSellPrice == null ) {
195+ throw new RuntimeException ("Giá bán quy đổi không được để trống." );
196+ }
197+
190198 conversion .setToUnit (toUnit );
191199 conversion .setConversionFactor (request .getConversionFactor ());
192- conversion .setSellPrice (request . getSellPrice () );
200+ conversion .setSellPrice (resolvedSellPrice );
193201 conversion .setDescription (request .getDescription ());
194202 if (request .getIsActive () != null ) {
195203 conversion .setActive (request .getIsActive ());
@@ -209,7 +217,6 @@ public void deleteConversion(Integer conversionId) {
209217
210218 unitConversionRepository .deleteById (conversionId );
211219
212- // Xoá biến thể đóng gói được tạo tự động khi tạo quy đổi
213220 List <ProductVariant > autoVariants = productVariantRepository .findByProductIdAndUnitId (productId , toUnitId );
214221 if (autoVariants != null && !autoVariants .isEmpty ()) {
215222 for (ProductVariant v : autoVariants ) {
0 commit comments