Skip to content

Dev into Main (fix db lost on deployment)#14

Merged
anh-tus merged 13 commits intomainfrom
dev
Mar 28, 2026
Merged

Dev into Main (fix db lost on deployment)#14
anh-tus merged 13 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:14
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 primarily standardizes frontend-to-backend connectivity around a relative /api base (with dev/prod proxying) and expands backend auth/workforce logic (refresh tokens, shift overlap validation, attendance status handling), along with several related UI/service adjustments.

Changes:

  • Frontend: switch hard-coded backend URLs to VITE_API_BASE_URL (default /api), add Vite/Nginx proxy rules, and centralize image URL resolution.
  • Backend: introduce refresh tokens (JWT tokenType + refresh endpoint) and extend workforce/shift assignment logic (overlap validation, attendance status rules), plus inventory stock deduction refinements.
  • Add/update tests and production configuration files supporting the above.

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 local dev proxies for /api and /uploads to match relative API usage.
frontend/src/utils/inventory.js Adds helpers to derive API origin and resolve image URLs consistently.
frontend/src/services/inventory/inventoryService.js Updates inventory API base to be derived from VITE_API_BASE_URL.
frontend/src/services/inventory/disposalService.js Updates disposal API base to be derived from VITE_API_BASE_URL.
frontend/src/services/aiChatService.js Switches AI endpoints to use /api-relative base paths.
frontend/src/pages/Products/ProductManager/ProductList.jsx Updates default API base to /api for image URL resolution.
frontend/src/pages/Products/ProductManager/ProductDetail.jsx Uses shared resolveImageUrl and restricts unit-conversion UI to base units.
frontend/src/pages/Products/ProductManager/EditVariantModal.jsx Uses shared image URL resolver + strips configurable API origin before persisting image paths.
frontend/src/pages/Products/ProductManager/EditProductModal.jsx Uses shared image URL resolver for previews.
frontend/src/pages/Products/ProductManager/EditComboModal.jsx Uses shared image URL resolver for previews.
frontend/src/pages/Products/ProductManager/ComboManage.jsx Uses shared image URL resolver for combo thumbnails.
frontend/src/pages/Products/ProductManager/ComboDetail.jsx Uses shared image URL resolver for combo image rendering.
frontend/src/pages/Pos/CartArea.jsx Removes the CartArea component file.
frontend/src/pages/CRM/homepage.jsx Uses shared image URL resolver for combo image rendering.
frontend/src/hooks/product_variants.js Maps backend isBaseUnit to frontend is_base_unit for UI gating.
frontend/src/config/axiosConfig.js Changes default axios baseURL to /api and adjusts validate URL accordingly.
frontend/nginx/default.conf Adds Nginx proxy routes for /api/ and /uploads/ in production.
frontend/.env.production Adds production Vite env defaults (notably VITE_API_BASE_URL=/api).
backend/src/test/java/com/smalltrend/util/JwtUtilTest.java Adds tests for refresh-token validation behavior.
backend/src/test/java/com/smalltrend/service/WorkShiftAssignmentServiceTest.java Adds tests for overlapping shift assignment prevention.
backend/src/test/java/com/smalltrend/service/ShiftWorkforceServiceTest.java Adds tests for missing clock-out status and invalid clock-out timeline.
backend/src/main/resources/data.sql Updates seed data (and modifies file header encoding/contents).
backend/src/main/resources/application.properties Adds jwt.refresh-expiration configuration.
backend/src/main/java/com/smalltrend/util/JwtUtil.java Adds refresh token generation + validation and tokenType claim.
backend/src/main/java/com/smalltrend/service/products/UnitConversionService.java Blocks adding unit conversions from conversion-derived variants; adjusts variant creation fields.
backend/src/main/java/com/smalltrend/service/products/ProductVariantService.java Computes and exposes isBaseUnit in variant response.
backend/src/main/java/com/smalltrend/service/inventory/shared/InventoryStockService.java Refactors/extends stock deduction to support derived vs base-unit handling.
backend/src/main/java/com/smalltrend/service/WorkShiftAssignmentService.java Adds overlap prevention for create/update/swap flows and supporting overlap utilities.
backend/src/main/java/com/smalltrend/service/UserService.java Adds refresh token issuance on register/login and implements refresh flow.
backend/src/main/java/com/smalltrend/service/ShiftWorkforceService.java Splits attendance status resolution by context and adds timeline validation.
backend/src/main/java/com/smalltrend/repository/WorkShiftAssignmentRepository.java Adds repository method for same-day assignment lookups used by overlap validation.
backend/src/main/java/com/smalltrend/dto/products/ProductVariantRespone.java Adds isBaseUnit to variant DTO.
backend/src/main/java/com/smalltrend/dto/auth/RefreshTokenRequest.java Adds request DTO for refresh token endpoint.
backend/src/main/java/com/smalltrend/dto/auth/AuthResponse.java Adds refreshToken field to auth response.
backend/src/main/java/com/smalltrend/controller/AuthController.java Adds /api/auth/refresh endpoint returning a new access+refresh token pair.

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

Comment on lines +19 to +21
# Key để lưu JWT token trong localStorage
VITE_TOKEN_KEY=smalltrend_token
VITE_REFRESH_TOKEN_KEY=smalltrend_refresh_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.

This production env file defines VITE_TOKEN_KEY / VITE_REFRESH_TOKEN_KEY, but the frontend code appears to read/write a hard-coded localStorage key (token) instead (e.g. axiosConfig and services). Either update the code to use these env vars, or remove these entries to avoid operational confusion.

Suggested change
# Key để lưu JWT token trong localStorage
VITE_TOKEN_KEY=smalltrend_token
VITE_REFRESH_TOKEN_KEY=smalltrend_refresh_token
# (Lưu ý: hiện tại frontend sử dụng key cố định `token` trong localStorage)

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 now appears to include a UTF-8 BOM (invisible character before --). Depending on the DB/import tooling, this can cause parsing issues. Consider removing the BOM / ensuring the file is saved as UTF-8 without BOM.

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

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
# ===================================
# SMALLTREND POS - PRODUCTION CONFIGURATION
# ===================================
# Dùng relative path /api để Nginx proxy forward tới backend

# ===================================
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.

PR title mentions fixing DB loss on deployment, but this PR includes broader changes (JWT refresh tokens, shift overlap rules, inventory image URL handling, nginx proxy updates). If the DB-loss fix is elsewhere, consider updating the title/description or splitting unrelated changes to reduce deployment risk and ease review.

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 + expiration. Since refresh tokens are now long-lived and include the same subject, a valid refresh token could be accepted anywhere an access token is expected. Consider asserting tokenType is access (and optionally treating missing tokenType as access for backward compatibility) in validateToken().

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

Copilot uses AI. Check for mistakes.
Comment on lines +321 to +332
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. For overnight shifts (end <= start), this can miss overlaps with assignments on the previous/next day (e.g. 22:00–06:00 vs next-day 05:00–10:00). Consider expanding the query window to include adjacent dates when either shift is overnight, or normalize assignments into date-time ranges and check across shiftDate ± 1.

Copilot uses AI. Check for mistakes.
Comment on lines +24 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-related lines here set request headers (via proxy_set_header), which won’t add CORS headers to the response and can be misleading. If you need CORS at the proxy layer, use add_header ... always; (and handle OPTIONS) or rely on backend CORS config; otherwise consider removing these lines.

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 at proxy layer
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 3600;
return 204;
}

Copilot uses AI. Check for mistakes.
@anh-tus anh-tus merged commit 6f8ecdd into main Mar 28, 2026
4 checks passed
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.

5 participants