Skip to content

Dev#13

Closed
xukki241 wants to merge 9 commits intomainfrom
dev
Closed

Dev#13
xukki241 wants to merge 9 commits intomainfrom
dev

Conversation

@xukki241
Copy link
Copy Markdown
Collaborator

No description provided.

huyhandsomeee and others added 9 commits March 27, 2026 22:39
- Added RefreshTokenRequest DTO for handling refresh token requests.
- Updated AuthResponse to include refresh token.
- Implemented refreshToken method in UserService to generate new access and refresh tokens.
- Enhanced JwtUtil to support refresh token generation and validation.
- Updated application.properties to include refresh token expiration configuration.
- Modified AuthController to handle refresh token endpoint.
- Added tests for refresh token validation and handling in JwtUtilTest.
- Updated WorkShiftAssignmentService to ensure no overlapping assignments.
- Added unit tests for WorkShiftAssignmentService to validate assignment creation logic.
…ions, refunds, and manual adjustments with unit conversion logic
@xukki241 xukki241 self-assigned this Mar 28, 2026
Copilot AI review requested due to automatic review settings March 28, 2026 11:05
@xukki241 xukki241 closed this Mar 28, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR standardizes frontend-to-backend connectivity around a relative /api base (supported by Vite + Nginx proxies), improves image URL resolution across the UI, and extends backend capabilities around authentication (refresh tokens) plus workforce/variant logic.

Changes:

  • Frontend: switch API base defaults from hardcoded localhost to /api, add shared image URL resolver, and wire it into product/combo/CRM screens.
  • Backend: introduce refresh tokens (JWT tokenType, refresh expiry config, refresh endpoint) and add/extend tests.
  • Domain logic: refine unit-conversion “base unit” rules, inventory stock deduction behavior, and shift assignment/attendance status handling.

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
frontend/vite.config.js Adds dev proxy rules for /api and /uploads to the backend.
frontend/src/utils/inventory.js Adds getApiOrigin() + resolveImageUrl() and updates inventory image resolution.
frontend/src/services/inventory/inventoryService.js Uses /api-relative defaults for inventory endpoints.
frontend/src/services/inventory/disposalService.js Uses /api-relative defaults for disposal voucher endpoints.
frontend/src/services/aiChatService.js Updates AI endpoints to align with /api base.
frontend/src/pages/Products/ProductManager/ProductList.jsx Switches default API base to /api for image origin logic.
frontend/src/pages/Products/ProductManager/ProductDetail.jsx Uses shared image resolver; gates unit-conversion UI based on is_base_unit.
frontend/src/pages/Products/ProductManager/EditVariantModal.jsx Uses shared image resolver; strips configurable API origin when persisting image paths.
frontend/src/pages/Products/ProductManager/EditProductModal.jsx Uses shared image resolver for previews.
frontend/src/pages/Products/ProductManager/EditComboModal.jsx Uses shared image resolver for previews.
frontend/src/pages/Products/ProductManager/ComboManage.jsx Uses shared image resolver for combo thumbnails.
frontend/src/pages/Products/ProductManager/ComboDetail.jsx Uses shared image resolver for combo image.
frontend/src/pages/Pos/CartArea.jsx Removes unused cart component.
frontend/src/pages/CRM/homepage.jsx Uses shared image resolver for combo cards.
frontend/src/hooks/product_variants.js Maps backend isBaseUnit → frontend is_base_unit.
frontend/src/config/axiosConfig.js Defaults Axios baseURL + validate URL to /api.
frontend/nginx/default.conf Adds /api and /uploads reverse proxy locations.
frontend/.env.production Adds production environment defaults (notably VITE_API_BASE_URL=/api).
backend/src/test/java/com/smalltrend/util/JwtUtilTest.java Adds refresh-token validation tests.
backend/src/test/java/com/smalltrend/service/WorkShiftAssignmentServiceTest.java Adds overlap rejection test coverage.
backend/src/test/java/com/smalltrend/service/ShiftWorkforceServiceTest.java Adds monitoring/upsert behavior tests.
backend/src/main/resources/data.sql Updates seed data (but introduces BOM).
backend/src/main/resources/application.properties Adds jwt.refresh-expiration property.
backend/src/main/java/com/smalltrend/util/JwtUtil.java Adds refresh token generation/validation; adds tokenType claim.
backend/src/main/java/com/smalltrend/service/products/UnitConversionService.java Prevents adding conversions from non-base-unit variants; adjusts derived variant creation.
backend/src/main/java/com/smalltrend/service/products/ProductVariantService.java Computes and returns isBaseUnit flag for variants.
backend/src/main/java/com/smalltrend/service/inventory/shared/InventoryStockService.java Changes deduction flow to optionally deduct directly from derived variant stock.
backend/src/main/java/com/smalltrend/service/WorkShiftAssignmentService.java Adds same-day shift overlap prevention + helper methods.
backend/src/main/java/com/smalltrend/repository/WorkShiftAssignmentRepository.java Adds findByUserIdAndShiftDateAndDeletedFalse.
backend/src/main/java/com/smalltrend/dto/products/ProductVariantRespone.java Adds isBaseUnit field.
backend/src/main/java/com/smalltrend/dto/auth/RefreshTokenRequest.java Adds refresh-token request DTO.
backend/src/main/java/com/smalltrend/dto/auth/AuthResponse.java Adds refreshToken to auth responses.
backend/src/main/java/com/smalltrend/controller/AuthController.java Adds /refresh endpoint.
backend/src/main/java/com/smalltrend/service/UserService.java Issues refresh tokens on register/login; implements refresh flow.
backend/src/main/java/com/smalltrend/service/ShiftWorkforceService.java Splits attendance status resolution by use-case; adds timeline validation and monitoring status.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 109 to +118
public void deductStock(ProductVariant variant, int quantity, Long orderId, String notes) {
if (!variant.isBaseUnit()) {
var directVariantStocks = inventoryStockRepository.findByVariantId(variant.getId());
boolean hasDirectVariantStock = directVariantStocks.stream()
.anyMatch(stock -> stock.getQuantity() != null && stock.getQuantity() > 0);

if (hasDirectVariantStock) {
deductFromStocks(variant, quantity, directVariantStocks, orderId, notes);
return;
}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deductStock() returns early and attempts to deduct the full requested quantity from directVariantStocks as soon as it finds any positive stock on the non-base variant. If that direct stock is insufficient, deductFromStocks() will throw instead of falling back to deduct the remaining quantity from the base variant via unit conversion. Consider deducting from direct stocks up to available, then converting and deducting the remainder from the base variant (or explicitly document that partial fallback is not supported).

Copilot uses AI. Check for mistakes.
Comment on lines +321 to +331
private void ensureNoOverlappingAssignment(
Integer userId,
LocalDate shiftDate,
WorkShift candidateShift,
Set<Integer> excludedAssignmentIds) {
if (userId == null || shiftDate == null || candidateShift == null) {
return;
}

List<WorkShiftAssignment> sameDayAssignments = assignmentRepository
.findByUserIdAndShiftDateAndDeletedFalse(userId, shiftDate);
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensureNoOverlappingAssignment() only loads assignments for the same shiftDate. Because the overlap logic supports overnight shifts (end <= start), this can miss overlaps that span midnight (e.g., an assignment on day D from 22:00–06:00 overlapping with an assignment on day D+1 at 05:00). To correctly prevent overlaps, also check assignments on adjacent dates (D-1 and D+1) when either the candidate or existing shift is overnight.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +27
# Handle CORS headers if needed
proxy_set_header Origin $http_origin;
proxy_set_header Access-Control-Allow-Origin $http_origin;
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CORS handling here is incorrect: proxy_set_header Access-Control-Allow-Origin $http_origin; sets a request header to the upstream, not a response header to the browser. Also mirroring $http_origin without validation can unintentionally allow any Origin. If CORS must be handled at Nginx, use add_header ... always; on responses (and consider restricting allowed origins); otherwise remove these lines and let the backend handle CORS.

Suggested change
# Handle CORS headers if needed
proxy_set_header Origin $http_origin;
proxy_set_header Access-Control-Allow-Origin $http_origin;
# Handle CORS headers if needed (handled by backend or via add_header in Nginx)
proxy_set_header Origin $http_origin;

Copilot uses AI. Check for mistakes.
@@ -1,4 +1,4 @@
-- =============================================================================
-- =============================================================================
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first line contains a UTF-8 BOM character before the -- comment marker. This can cause some SQL runners/migration tools to fail parsing the script (especially if they don't expect BOM in the middle of a repository file). Please remove the BOM so the file starts directly with --.

Suggested change
-- =============================================================================
-- =============================================================================

Copilot uses AI. Check for mistakes.
# ===================================
# AUTHENTICATION
# ===================================
# Key để lưu JWT token trong localStorage
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file documents VITE_TOKEN_KEY / VITE_REFRESH_TOKEN_KEY as the keys used for storing tokens in localStorage, but the frontend code appears to read/write hardcoded keys (e.g., localStorage.getItem("token")) and does not reference these env vars. Either update the code to use these environment variables or adjust the comments/variables here to avoid misleading production configuration.

Suggested change
# Key để lưu JWT token trong localStorage
# (Hiện tại frontend đang dùng key hardcode như "token" / "refresh_token" trong localStorage.)
# Các biến dưới đây chỉ là cấu hình dự kiến, hiện CHƯA được code sử dụng.

Copilot uses AI. Check for mistakes.

public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateToken() currently only checks username match + expiry, so a refresh token (with the same subject and not expired) would also be accepted anywhere access tokens are validated. Since you now set a tokenType claim, please also enforce tokenType=access in validateToken() (or introduce a dedicated access-token validator) to prevent privilege escalation via refresh tokens.

Suggested change
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
final String tokenType = extractClaim(token, claims -> claims.get("tokenType", String.class));
return username.equals(userDetails.getUsername())
&& "access".equalsIgnoreCase(tokenType)
&& !isTokenExpired(token);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants