diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000000..1c5ff5a72c
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,526 @@
+name: Run Tests
+
+on:
+ push:
+ branches: [ "main", "scenario/*", "eval/*", "feature/*" ]
+ pull_request:
+ branches: [ "main", "scenario/*", "eval/*", "feature/*" ]
+ issue_comment:
+ types: [created]
+
+jobs:
+ # ──────────── 1. collect and process tests ────────────
+ collect-process-tests:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ outputs:
+ fail_to_pass: ${{ steps.combine.outputs.fail_to_pass }}
+ pass_to_pass: ${{ steps.combine.outputs.pass_to_pass }}
+ tests: ${{ steps.combine.outputs.tests }}
+ comment_id: ${{ steps.combine.outputs.comment_id }}
+ if: ${{ github.event_name != 'issue_comment' || contains(github.event.comment.body, 'FAIL_TO_PASS') || contains(github.event.comment.body, 'PASS_TO_PASS') }}
+ steps:
+ - uses: actions/checkout@v4
+
+ # ─── 1.1 collect issue numbers based on event type ───
+ - name: Collect issue numbers based on event type
+ id: collect_issues
+ shell: bash
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ PR_NUMBER: ${{ github.event.pull_request.number }}
+ REPO: ${{ github.repository }}
+ run: |
+ # Initialize issue numbers variable
+ ISSUE_NUMBERS=""
+
+ # Handle different event types
+ if [[ "${{ github.event_name }}" == "pull_request" ]]; then
+ echo "Collecting issue numbers from commits in PR #$PR_NUMBER"
+
+ # Get all commits in the PR
+ COMMITS=$(gh api repos/$REPO/pulls/$PR_NUMBER/commits --jq '.[].sha')
+
+ # Initialize an empty array for issue numbers
+ ISSUE_NUMBERS_ARRAY=()
+
+ # For each commit, extract linked issue numbers
+ for COMMIT in $COMMITS; do
+ echo "Processing commit $COMMIT"
+
+ # Get commit message
+ COMMIT_MSG=$(gh api repos/$REPO/commits/$COMMIT --jq '.commit.message')
+
+ # Extract issue numbers using regex (e.g., #123, fixes #456, etc.)
+ ISSUES=$(echo "$COMMIT_MSG" | grep -o '#[0-9]\+' | sed 's/#//')
+
+ if [ -n "$ISSUES" ]; then
+ echo "Found issues in commit $COMMIT: $ISSUES"
+ # Add to our array
+ for ISSUE in $ISSUES; do
+ ISSUE_NUMBERS_ARRAY+=("$ISSUE")
+ done
+ fi
+ done
+
+ # Remove duplicates and create JSON array
+ UNIQUE_ISSUES=$(echo "${ISSUE_NUMBERS_ARRAY[@]}" | tr ' ' '\n' | sort -u)
+
+ if [ -z "$UNIQUE_ISSUES" ]; then
+ echo "No issue numbers found in commit messages, using PR number as fallback"
+ ISSUE_NUMBERS="[\"${{ github.event.pull_request.number }}\"]"
+ else
+ # Convert to JSON array
+ ISSUE_NUMBERS=$(echo "$UNIQUE_ISSUES" | jq -R . | jq -s .)
+ fi
+ elif [[ "${{ github.event_name }}" == "push" ]]; then
+ echo "Extracting issue numbers from commit message"
+
+ # Get commit message
+ COMMIT_MSG="${{ github.event.head_commit.message }}"
+
+ # Extract issue numbers using regex (e.g., #123, fixes #456, etc.)
+ ISSUES=$(echo "$COMMIT_MSG" | grep -o '#[0-9]\+' | sed 's/#//')
+
+ if [ -n "$ISSUES" ]; then
+ echo "Found issues in commit message: $ISSUES"
+
+ # Initialize an empty array for issue numbers
+ ISSUE_NUMBERS_ARRAY=()
+
+ # Add to our array
+ for ISSUE in $ISSUES; do
+ ISSUE_NUMBERS_ARRAY+=("$ISSUE")
+ done
+
+ # Remove duplicates and create JSON array
+ UNIQUE_ISSUES=$(echo "${ISSUE_NUMBERS_ARRAY[@]}" | tr ' ' '\n' | sort -u)
+
+ # Convert to JSON array
+ ISSUE_NUMBERS=$(echo "$UNIQUE_ISSUES" | jq -R . | jq -s .)
+ else
+ echo "No issue numbers found in commit message, using empty array as fallback"
+ ISSUE_NUMBERS="[\"\"]"
+ fi
+ elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
+ echo "Using issue number from comment event"
+ ISSUE_NUMBERS="[\"${{ github.event.issue.number }}\"]"
+ else
+ echo "Using fallback issue number from inputs"
+ ISSUE_NUMBERS="[\"\"]"
+ fi
+
+ echo "Found issue numbers: $ISSUE_NUMBERS"
+ # Escape the JSON string for GitHub Actions output
+ ESCAPED_ISSUE_NUMBERS=$(echo "$ISSUE_NUMBERS" | jq -c .)
+ echo "issue_numbers=$ESCAPED_ISSUE_NUMBERS" >> $GITHUB_OUTPUT
+
+ # ─── 1.2 extract test names from issues ───
+ - name: Extract test names for issues
+ id: extract_tests
+ shell: bash
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ ISSUE_NUMBERS: ${{ steps.collect_issues.outputs.issue_numbers }}
+ REPO: ${{ github.repository }}
+ run: |
+ # Initialize arrays for test results
+ FAIL_TO_PASS=()
+ PASS_TO_PASS=()
+ TESTS=()
+ COMMENT_ID=""
+
+ # Process each issue number
+ for ISSUE_NUMBER in $(echo $ISSUE_NUMBERS | jq -r '.[]'); do
+ if [[ -z "$ISSUE_NUMBER" || "$ISSUE_NUMBER" == "null" ]]; then
+ continue
+ fi
+
+ echo "Processing issue #$ISSUE_NUMBER"
+
+ # Function to extract FAIL_TO_PASS and PASS_TO_PASS from text
+ extract_test_fields() {
+ local text="$1"
+ local fail_to_pass=""
+ local pass_to_pass=""
+
+ if [[ -n "$text" ]]; then
+ # Find FAIL_TO_PASS pattern
+ if [[ "$text" =~ FAIL_TO_PASS:[[:space:]]*([^$'\n']+) ]]; then
+ fail_to_pass="${BASH_REMATCH[1]}"
+ fi
+
+ # Find PASS_TO_PASS pattern
+ if [[ "$text" =~ PASS_TO_PASS:[[:space:]]*([^$'\n']+) ]]; then
+ pass_to_pass="${BASH_REMATCH[1]}"
+ fi
+ fi
+
+ echo "$fail_to_pass|$pass_to_pass"
+ }
+
+ # First check issue comments
+ echo "Checking issue comments for test fields..."
+ COMMENTS=$(gh api repos/$REPO/issues/$ISSUE_NUMBER/comments --jq '.[] | {id: .id, body: .body, created_at: .created_at}')
+
+ if [[ -n "$COMMENTS" ]]; then
+ # Process all comments to find the latest one with FAIL_TO_PASS or PASS_TO_PASS
+ LATEST_COMMENT_WITH_VALUES=""
+ LATEST_COMMENT_ID=""
+ LATEST_FAIL_TO_PASS=""
+ LATEST_PASS_TO_PASS=""
+
+ while IFS= read -r COMMENT; do
+ COMMENT_BODY=$(echo "$COMMENT" | jq -r '.body')
+ CURRENT_COMMENT_ID=$(echo "$COMMENT" | jq -r '.id')
+
+ RESULT=$(extract_test_fields "$COMMENT_BODY")
+ IFS='|' read -r COMMENT_FAIL COMMENT_PASS <<< "$RESULT"
+
+ if [[ -n "$COMMENT_FAIL" || -n "$COMMENT_PASS" ]]; then
+ LATEST_COMMENT_WITH_VALUES="$COMMENT"
+ LATEST_COMMENT_ID="$CURRENT_COMMENT_ID"
+
+ if [[ -n "$COMMENT_FAIL" ]]; then
+ LATEST_FAIL_TO_PASS="$COMMENT_FAIL"
+ echo "Found FAIL_TO_PASS in issue comment $CURRENT_COMMENT_ID: $COMMENT_FAIL"
+ fi
+
+ if [[ -n "$COMMENT_PASS" ]]; then
+ LATEST_PASS_TO_PASS="$COMMENT_PASS"
+ echo "Found PASS_TO_PASS in issue comment $CURRENT_COMMENT_ID: $COMMENT_PASS"
+ fi
+ fi
+ done <<< "$COMMENTS"
+
+ # Use values from the latest comment
+ if [[ -n "$LATEST_COMMENT_WITH_VALUES" ]]; then
+ COMMENT_ID="$LATEST_COMMENT_ID"
+
+ if [[ -n "$LATEST_FAIL_TO_PASS" ]]; then
+ FAIL_TO_PASS=("$LATEST_FAIL_TO_PASS")
+ echo "Using FAIL_TO_PASS from latest comment $COMMENT_ID: $LATEST_FAIL_TO_PASS"
+ fi
+
+ if [[ -n "$LATEST_PASS_TO_PASS" ]]; then
+ PASS_TO_PASS=("$LATEST_PASS_TO_PASS")
+ echo "Using PASS_TO_PASS from latest comment $COMMENT_ID: $LATEST_PASS_TO_PASS"
+ fi
+ fi
+ fi
+
+ # If not found in comments, check commit messages
+ if [[ ${#FAIL_TO_PASS[@]} -eq 0 && ${#PASS_TO_PASS[@]} -eq 0 ]]; then
+ echo "Checking commit messages for test fields..."
+
+ # Get linked commit IDs
+ COMMIT_IDS=$(gh api repos/$REPO/issues/$ISSUE_NUMBER/timeline --jq '.[] | select(.event == "referenced" and .commit_id != null) | .commit_id')
+
+ if [[ -z "$COMMIT_IDS" ]]; then
+ echo "No directly linked commits found, checking PRs..."
+
+ # Try to get commits from PRs
+ PR_NUMBERS=$(gh api repos/$REPO/issues/$ISSUE_NUMBER/timeline --jq '.[] | select(.event == "cross-referenced" and .source.issue.pull_request != null) | .source.issue.number')
+
+ if [[ -n "$PR_NUMBERS" ]]; then
+ for PR in $PR_NUMBERS; do
+ echo "Fetching commits from PR #$PR..."
+ PR_COMMITS=$(gh api repos/$REPO/pulls/$PR/commits --jq '.[].sha')
+
+ if [[ -n "$PR_COMMITS" ]]; then
+ COMMIT_IDS="$COMMIT_IDS"$'\n'"$PR_COMMITS"
+ fi
+ done
+ fi
+ fi
+
+ # Process commit messages to find the latest one with FAIL_TO_PASS or PASS_TO_PASS
+ if [[ -n "$COMMIT_IDS" ]]; then
+ # Variables to track the latest commit with values
+ LATEST_COMMIT_ID=""
+ LATEST_COMMIT_DATE=""
+ LATEST_COMMIT_FAIL=""
+ LATEST_COMMIT_PASS=""
+
+ while IFS= read -r COMMIT_ID; do
+ if [[ -z "$COMMIT_ID" ]]; then
+ continue
+ fi
+
+ echo "Fetching message for commit: $COMMIT_ID"
+ COMMIT_DATA=$(gh api repos/$REPO/commits/$COMMIT_ID --jq '{message: .commit.message, date: .commit.author.date}')
+ COMMIT_MSG=$(echo "$COMMIT_DATA" | jq -r '.message')
+ COMMIT_DATE=$(echo "$COMMIT_DATA" | jq -r '.date')
+
+ if [[ -n "$COMMIT_MSG" ]]; then
+ RESULT=$(extract_test_fields "$COMMIT_MSG")
+ IFS='|' read -r COMMIT_FAIL COMMIT_PASS <<< "$RESULT"
+
+ if [[ -n "$COMMIT_FAIL" || -n "$COMMIT_PASS" ]]; then
+ # Check if this commit is newer than our current latest
+ if [[ -z "$LATEST_COMMIT_DATE" || "$COMMIT_DATE" > "$LATEST_COMMIT_DATE" ]]; then
+ LATEST_COMMIT_ID="$COMMIT_ID"
+ LATEST_COMMIT_DATE="$COMMIT_DATE"
+ LATEST_COMMIT_FAIL="$COMMIT_FAIL"
+ LATEST_COMMIT_PASS="$COMMIT_PASS"
+
+ if [[ -n "$COMMIT_FAIL" ]]; then
+ echo "Found FAIL_TO_PASS in commit $COMMIT_ID: $COMMIT_FAIL"
+ fi
+
+ if [[ -n "$COMMIT_PASS" ]]; then
+ echo "Found PASS_TO_PASS in commit $COMMIT_ID: $COMMIT_PASS"
+ fi
+ fi
+ fi
+ fi
+ done <<< "$COMMIT_IDS"
+
+ # Use values from the latest commit
+ if [[ -n "$LATEST_COMMIT_ID" ]]; then
+ if [[ -n "$LATEST_COMMIT_FAIL" ]]; then
+ FAIL_TO_PASS=("$LATEST_COMMIT_FAIL")
+ echo "Using FAIL_TO_PASS from latest commit $LATEST_COMMIT_ID: $LATEST_COMMIT_FAIL"
+ fi
+
+ if [[ -n "$LATEST_COMMIT_PASS" ]]; then
+ PASS_TO_PASS=("$LATEST_COMMIT_PASS")
+ echo "Using PASS_TO_PASS from latest commit $LATEST_COMMIT_ID: $LATEST_COMMIT_PASS"
+ fi
+ fi
+ fi
+ fi
+ done
+
+ # Convert arrays to comma-separated strings
+ FAIL_TO_PASS_STR=$(IFS=,; echo "${FAIL_TO_PASS[*]}")
+ PASS_TO_PASS_STR=$(IFS=,; echo "${PASS_TO_PASS[*]}")
+
+ # Convert to JSON arrays if not empty
+ if [[ -n "$FAIL_TO_PASS_STR" ]]; then
+ FAIL_TO_PASS_JSON=$(echo "$FAIL_TO_PASS_STR" | jq -R -c 'split(",") | map(select(length > 0))')
+ else
+ FAIL_TO_PASS_JSON="[]"
+ fi
+
+ if [[ -n "$PASS_TO_PASS_STR" ]]; then
+ PASS_TO_PASS_JSON=$(echo "$PASS_TO_PASS_STR" | jq -R -c 'split(",") | map(select(length > 0))')
+ else
+ PASS_TO_PASS_JSON="[]"
+ fi
+
+ # Combine tests
+ if [[ -n "$FAIL_TO_PASS_STR" || -n "$PASS_TO_PASS_STR" ]]; then
+ TESTS_STR="$FAIL_TO_PASS_STR,$PASS_TO_PASS_STR"
+ TESTS_STR=$(echo "$TESTS_STR" | sed 's/^,//;s/,$//')
+ fi
+
+ # Output results
+ echo "fail_to_pass=$FAIL_TO_PASS_JSON" >> $GITHUB_OUTPUT
+ echo "pass_to_pass=$PASS_TO_PASS_JSON" >> $GITHUB_OUTPUT
+ echo "tests=$TESTS_STR" >> $GITHUB_OUTPUT
+ echo "comment_id=$COMMENT_ID" >> $GITHUB_OUTPUT
+
+ # ─── 1.3 combine test results ───
+ - name: Combine test results
+ id: combine
+ shell: bash
+ run: |
+ # Just pass through the outputs from extract_tests
+ echo "fail_to_pass=${{ steps.extract_tests.outputs.fail_to_pass }}" >> $GITHUB_OUTPUT
+ echo "pass_to_pass=${{ steps.extract_tests.outputs.pass_to_pass }}" >> $GITHUB_OUTPUT
+ echo "tests=${{ steps.extract_tests.outputs.tests }}" >> $GITHUB_OUTPUT
+ echo "comment_id=${{ steps.extract_tests.outputs.comment_id }}" >> $GITHUB_OUTPUT
+
+ # ─── 1.4 check if FAIL_TO_PASS or PASS_TO_PASS found ───
+ - name: Check if FAIL_TO_PASS or PASS_TO_PASS found
+ if: ${{ github.event_name == 'pull_request' && steps.combine.outputs.fail_to_pass == '[]' && steps.combine.outputs.pass_to_pass == '[]' }}
+ shell: bash
+ run: |
+ echo "::error::FAIL_TO_PASS or PASS_TO_PASS not found in commit messages or issue comments, please add FAIL_TO_PASS or PASS_TO_PASS to issue comment"
+ exit 1
+
+ # ──────────── 2. Run tests and handle comments ────────────
+ run-tests-and-comments:
+ needs: collect-process-tests
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ issues: write
+ if: ${{ always() && (github.event_name != 'pull_request' || needs.collect-process-tests.outputs.fail_to_pass != '[]' || needs.collect-process-tests.outputs.pass_to_pass != '[]') }}
+ outputs:
+ comment_id: ${{ steps.create_comment.outputs.comment_id }}
+ status: ${{ job.status }}
+ steps:
+ - uses: actions/checkout@v4
+
+ # Step 1: Create placeholder comment
+ - name: Create placeholder issue comment
+ id: create_comment
+ if: ${{ github.event_name == 'push' || github.event_name == 'issue_comment' }}
+ uses: actions/github-script@v7
+ env:
+ RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ WORKFLOW_NAME: ${{ github.workflow }}
+ FAIL_TO_PASS: ${{ needs.collect-process-tests.outputs.fail_to_pass }}
+ PASS_TO_PASS: ${{ needs.collect-process-tests.outputs.pass_to_pass }}
+ COMMENT_ID: ${{ needs.collect-process-tests.outputs.comment_id }}
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ result-encoding: string
+ script: |
+ const issuePat = /#(\d+)/g;
+ let issueNum = null, m;
+
+ // • PR context
+ if (context.payload.pull_request) {
+ const whole = `${context.payload.pull_request.title}\n${context.payload.pull_request.body}`;
+ if ((m = issuePat.exec(whole)) !== null) issueNum = +m[1];
+ }
+
+ // • Push context
+ if (!issueNum && context.payload.commits) {
+ for (const c of context.payload.commits) {
+ if ((m = issuePat.exec(c.message)) !== null) { issueNum = +m[1]; break; }
+ }
+ }
+
+ // • Issue comment context
+ if (!issueNum && context.payload.issue) {
+ issueNum = context.payload.issue.number;
+ }
+
+ if (!issueNum) { core.info('No #issue reference found.'); return; }
+
+ let bodyContent = '';
+
+ if (!process.env.COMMENT_ID){
+ if (process.env.FAIL_TO_PASS && process.env.FAIL_TO_PASS !== '[]') {
+ // Parse JSON array and convert to comma-separated string
+ core.info('FAIL_TO_PASS: '+process.env.FAIL_TO_PASS);
+ const failToPassArray = JSON.parse(process.env.FAIL_TO_PASS);
+ const failToPassString = failToPassArray.join(', ');
+ bodyContent += `FAIL_TO_PASS: ${failToPassString}\n`;
+ }
+
+ if (process.env.PASS_TO_PASS && process.env.PASS_TO_PASS !== '[]') {
+ // Parse JSON array and convert to comma-separated string
+ const passToPassArray = JSON.parse(process.env.PASS_TO_PASS);
+ const passToPassString = passToPassArray.join(', ');
+ bodyContent += `PASS_TO_PASS: ${passToPassString}\n`;
+ }
+ }
+
+ bodyContent += `\n⏳ **[${process.env.WORKFLOW_NAME}](${process.env.RUN_URL})** has **started**…`;
+
+ // If we have an existing comment ID, update it instead of creating a new one
+ if (false && process.env.COMMENT_ID) {
+ try {
+ // Get existing comment body
+ const { data: existingComment } = await github.rest.issues.getComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: Number(process.env.COMMENT_ID)
+ });
+
+ // Append new content to existing body
+ const updatedBody = existingComment.body + '\n' + bodyContent;
+
+ await github.rest.issues.updateComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: Number(process.env.COMMENT_ID),
+ body: updatedBody
+ });
+ core.setOutput('comment_id', process.env.COMMENT_ID);
+ return;
+ } catch (error) {
+ core.warning(`Failed to update comment ${process.env.COMMENT_ID}: ${error.message}`);
+ // Fall through to create a new comment
+ }
+ }
+
+ // Create a new comment
+ const { data: comment } = await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: issueNum,
+ body: bodyContent
+ });
+ core.setOutput('comment_id', comment.id.toString());
+
+ # Step 2: Setup Java and Maven
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: '24'
+ distribution: 'temurin'
+ cache: 'maven'
+
+ # Step 3: Compile project
+ - name: Compile project
+ shell: bash
+ run: mvn -B compile --file pom.xml
+
+ # Step 4: Run tests
+ - name: Run selected tests
+ if: ${{ needs.collect-process-tests.outputs.tests != '' }}
+ shell: bash
+ run: mvn -B -Dtest="${{ needs.collect-process-tests.outputs.tests }}" test
+
+ - name: Run all tests
+ if: ${{ needs.collect-process-tests.outputs.tests == '' }}
+ shell: bash
+ run: mvn -B test --file pom.xml
+
+ # Step 5: Update comment with final status
+ - name: Update issue comment with final status
+ if: ${{ always() && (github.event_name == 'push' || github.event_name == 'issue_comment') }}
+ uses: actions/github-script@v7
+ env:
+ COMMENT_ID: ${{ steps.create_comment.outputs.comment_id }}
+ RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ WORKFLOW_NAME: ${{ github.workflow }}
+ JOB_STATUS: ${{ job.status }}
+ FAIL_TO_PASS: ${{ needs.collect-process-tests.outputs.fail_to_pass }}
+ PASS_TO_PASS: ${{ needs.collect-process-tests.outputs.pass_to_pass }}
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ if (!process.env.COMMENT_ID) {
+ core.info('No comment to update.'); return;
+ }
+ const statusEmoji = {
+ success: '✅',
+ failure: '❌',
+ cancelled: '🟡'
+ }[process.env.JOB_STATUS] || '🟡';
+
+ let bodyContent = '';
+ if (!process.env.COMMENT_ID){
+ if (process.env.FAIL_TO_PASS && process.env.FAIL_TO_PASS !== '[]') {
+ // Parse JSON array and convert to comma-separated string
+ const quoted = process.env.FAIL_TO_PASS.replace(/(\w+)/g, '"$1"');
+ const failToPassArray = JSON.parse(quoted);
+ const failToPassString = failToPassArray.join(', ');
+ bodyContent += `FAIL_TO_PASS: ${failToPassString}\n`;
+ }
+
+ if (process.env.PASS_TO_PASS && process.env.PASS_TO_PASS !== '[]') {
+ // Parse JSON array and convert to comma-separated string
+ const quoted = process.env.PASS_TO_PASS.replace(/(\w+)/g, '"$1"');
+ const passToPassArray = JSON.parse(quoted);
+ const passToPassString = passToPassArray.join(', ');
+ bodyContent += `PASS_TO_PASS: ${passToPassString}\n`;
+ }
+ }
+
+ bodyContent += `\n${statusEmoji} **[${process.env.WORKFLOW_NAME}](${process.env.RUN_URL})** finished with status **${process.env.JOB_STATUS.toUpperCase()}**.`;
+
+ await github.rest.issues.updateComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: Number(process.env.COMMENT_ID),
+ body: bodyContent
+ });
\ No newline at end of file
diff --git a/.github/workflows/pr-label-management.yml b/.github/workflows/pr-label-management.yml
new file mode 100644
index 0000000000..24773ffb81
--- /dev/null
+++ b/.github/workflows/pr-label-management.yml
@@ -0,0 +1,174 @@
+name: PR Label Management
+
+on:
+ pull_request:
+ types: [opened, reopened, synchronize]
+ pull_request_review:
+ types: [submitted]
+
+jobs:
+ manage-labels:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
+ issues: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Add Review label on PR creation
+ if: github.event_name == 'pull_request'
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ // Add Review label to the PR
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.payload.pull_request.number,
+ labels: ['Review']
+ });
+
+ console.log(`Added Review label to PR #${context.payload.pull_request.number}`);
+
+ // Extract related issue numbers from PR title and body
+ const prText = `${context.payload.pull_request.title} ${context.payload.pull_request.body || ''}`;
+ const issuePattern = /#(\d+)/g;
+ const relatedIssues = new Set();
+ let match;
+
+ while ((match = issuePattern.exec(prText)) !== null) {
+ relatedIssues.add(match[1]);
+ }
+
+ // Also check commit messages for issue references
+ const commits = await github.rest.pulls.listCommits({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: context.payload.pull_request.number
+ });
+
+ for (const commit of commits.data) {
+ const commitMessage = commit.commit.message;
+ while ((match = issuePattern.exec(commitMessage)) !== null) {
+ relatedIssues.add(match[1]);
+ }
+ }
+
+ // Add Review label to all related issues
+ for (const issueNumber of relatedIssues) {
+ try {
+ // Check if issue exists
+ await github.rest.issues.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: parseInt(issueNumber)
+ });
+
+ // Add Review label to the issue
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: parseInt(issueNumber),
+ labels: ['Review']
+ });
+
+ console.log(`Added Review label to related issue #${issueNumber}`);
+ } catch (error) {
+ console.log(`Error processing issue #${issueNumber}: ${error.message}`);
+ }
+ }
+
+ - name: Handle PR approval
+ if: github.event_name == 'pull_request_review' && github.event.review.state == 'approved'
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const prNumber = context.payload.pull_request.number;
+
+ // Remove Review label and add Verified label to the PR
+ try {
+ // First try to remove the Review label
+ await github.rest.issues.removeLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ name: 'Review'
+ });
+ console.log(`Removed Review label from PR #${prNumber}`);
+ } catch (error) {
+ console.log(`Note: Review label might not exist on PR #${prNumber}: ${error.message}`);
+ }
+
+ // Add Verified label to the PR
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ labels: ['Verified']
+ });
+ console.log(`Added Verified label to PR #${prNumber}`);
+
+ // Extract related issue numbers from PR title and body
+ const prText = `${context.payload.pull_request.title} ${context.payload.pull_request.body || ''}`;
+ const issuePattern = /#(\d+)/g;
+ const relatedIssues = new Set();
+ let match;
+
+ while ((match = issuePattern.exec(prText)) !== null) {
+ relatedIssues.add(match[1]);
+ }
+
+ // Also check commit messages for issue references
+ const commits = await github.rest.pulls.listCommits({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: prNumber
+ });
+
+ for (const commit of commits.data) {
+ const commitMessage = commit.commit.message;
+ while ((match = issuePattern.exec(commitMessage)) !== null) {
+ relatedIssues.add(match[1]);
+ }
+ }
+
+ // Update labels on all related issues
+ for (const issueNumber of relatedIssues) {
+ try {
+ // Check if issue exists
+ await github.rest.issues.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: parseInt(issueNumber)
+ });
+
+ // Try to remove Review label from the issue
+ try {
+ await github.rest.issues.removeLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: parseInt(issueNumber),
+ name: 'Review'
+ });
+ console.log(`Removed Review label from related issue #${issueNumber}`);
+ } catch (error) {
+ console.log(`Note: Review label might not exist on issue #${issueNumber}: ${error.message}`);
+ }
+
+ // Add Verified label to the issue
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: parseInt(issueNumber),
+ labels: ['Verified']
+ });
+ console.log(`Added Verified label to related issue #${issueNumber}`);
+ } catch (error) {
+ console.log(`Error processing issue #${issueNumber}: ${error.message}`);
+ }
+ }
\ No newline at end of file
diff --git a/ts-common/pom.xml b/ts-common/pom.xml
index ada2e02ac2..cec12a70e4 100644
--- a/ts-common/pom.xml
+++ b/ts-common/pom.xml
@@ -25,6 +25,12 @@
jakarta.validation
jakarta.validation-api
+
+
+ org.hibernate.validator
+ hibernate-validator
+ 6.2.5.Final
+
javax.persistence
javax.persistence-api
diff --git a/ts-common/src/main/java/edu/fudan/common/entity/Contacts.java b/ts-common/src/main/java/edu/fudan/common/entity/Contacts.java
index eb261bce0c..fa7ca37d1f 100644
--- a/ts-common/src/main/java/edu/fudan/common/entity/Contacts.java
+++ b/ts-common/src/main/java/edu/fudan/common/entity/Contacts.java
@@ -40,11 +40,11 @@ public boolean equals(Object obj) {
return false;
}
Contacts other = (Contacts) obj;
- return name.equals(other.getName())
- && accountId .equals( other.getAccountId() )
- && documentNumber.equals(other.getDocumentNumber())
- && phoneNumber.equals(other.getPhoneNumber())
- && documentType == other.getDocumentType();
+ return name.equals(other.name)
+ && accountId .equals( other.accountId )
+ && documentNumber.equals(other.documentNumber)
+ && phoneNumber.equals(other.phoneNumber)
+ && documentType == other.documentType;
}
@Override
diff --git a/ts-common/src/main/java/edu/fudan/common/entity/Food.java b/ts-common/src/main/java/edu/fudan/common/entity/Food.java
index 3882994e0a..b1598ddd7b 100644
--- a/ts-common/src/main/java/edu/fudan/common/entity/Food.java
+++ b/ts-common/src/main/java/edu/fudan/common/entity/Food.java
@@ -1,19 +1,51 @@
package edu.fudan.common.entity;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
import javax.persistence.Embeddable;
import java.io.Serializable;
+import java.util.Objects;
@Data
+@NoArgsConstructor
+@AllArgsConstructor
@Embeddable
public class Food implements Serializable{
private String foodName;
private double price;
- public Food(){
- //Default Constructor
+
+ // Getters and Setters
+ public String getFoodName() {
+ return foodName;
+ }
+
+ public void setFoodName(String foodName) {
+ this.foodName = foodName;
+ }
+
+ public double getPrice() {
+ return price;
}
+ public void setPrice(double price) {
+ this.price = price;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Food food = (Food) o;
+ return Double.compare(food.price, price) == 0 &&
+ Objects.equals(foodName, food.foodName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(foodName, price);
+ }
}
diff --git a/ts-common/src/main/java/edu/fudan/common/entity/FoodOrder.java b/ts-common/src/main/java/edu/fudan/common/entity/FoodOrder.java
index b888084a81..c790ae9518 100644
--- a/ts-common/src/main/java/edu/fudan/common/entity/FoodOrder.java
+++ b/ts-common/src/main/java/edu/fudan/common/entity/FoodOrder.java
@@ -1,13 +1,10 @@
package edu.fudan.common.entity;
-import lombok.Data;
-
import java.util.UUID;
/**
* @author fdse
*/
-@Data
public class FoodOrder {
private String id;
@@ -31,4 +28,71 @@ public FoodOrder(){
//Default Constructor
}
+ public FoodOrder(String id, String orderId, int foodType, String stationName,
+ String storeName, String foodName, double price) {
+ this.id = id;
+ this.orderId = orderId;
+ this.foodType = foodType;
+ this.stationName = stationName;
+ this.storeName = storeName;
+ this.foodName = foodName;
+ this.price = price;
+ }
+
+ // Getters and Setters
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public int getFoodType() {
+ return foodType;
+ }
+
+ public void setFoodType(int foodType) {
+ this.foodType = foodType;
+ }
+
+ public String getStationName() {
+ return stationName;
+ }
+
+ public void setStationName(String stationName) {
+ this.stationName = stationName;
+ }
+
+ public String getStoreName() {
+ return storeName;
+ }
+
+ public void setStoreName(String storeName) {
+ this.storeName = storeName;
+ }
+
+ public String getFoodName() {
+ return foodName;
+ }
+
+ public void setFoodName(String foodName) {
+ this.foodName = foodName;
+ }
+
+ public double getPrice() {
+ return price;
+ }
+
+ public void setPrice(double price) {
+ this.price = price;
+ }
}
diff --git a/ts-common/src/main/java/edu/fudan/common/entity/Order.java b/ts-common/src/main/java/edu/fudan/common/entity/Order.java
index cf8f1285fb..aab327f835 100644
--- a/ts-common/src/main/java/edu/fudan/common/entity/Order.java
+++ b/ts-common/src/main/java/edu/fudan/common/entity/Order.java
@@ -15,6 +15,7 @@
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
+@NoArgsConstructor
@AllArgsConstructor
public class Order {
@@ -58,7 +59,7 @@ public class Order {
private String differenceMoney;
- public Order(){
+ public void initOrder(){
boughtDate = StringUtils.Date2String(new Date(System.currentTimeMillis()));
travelDate = StringUtils.Date2String(new Date(123456789));
trainNumber = "G1235";
@@ -72,6 +73,7 @@ public Order(){
differenceMoney ="0.0";
}
+ @Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
@@ -83,20 +85,20 @@ public boolean equals(Object obj) {
return false;
}
Order other = (Order) obj;
- return getBoughtDate().equals(other.getBoughtDate())
- && getBoughtDate().equals(other.getTravelDate())
- && getTravelTime().equals(other.getTravelTime())
- && accountId .equals( other.getAccountId() )
- && contactsName.equals(other.getContactsName())
- && contactsDocumentNumber.equals(other.getContactsDocumentNumber())
- && documentType == other.getDocumentType()
- && trainNumber.equals(other.getTrainNumber())
- && coachNumber == other.getCoachNumber()
- && seatClass == other.getSeatClass()
- && seatNumber .equals(other.getSeatNumber())
- && from.equals(other.getFrom())
- && to.equals(other.getTo())
- && status == other.getStatus()
+ return boughtDate.equals(other.boughtDate)
+ && travelDate.equals(other.travelDate)
+ && travelTime.equals(other.travelTime)
+ && accountId .equals( other.accountId )
+ && contactsName.equals(other.contactsName)
+ && contactsDocumentNumber.equals(other.contactsDocumentNumber)
+ && documentType == other.documentType
+ && trainNumber.equals(other.trainNumber)
+ && coachNumber == other.coachNumber
+ && seatClass == other.seatClass
+ && seatNumber .equals(other.seatNumber)
+ && from.equals(other.from)
+ && to.equals(other.to)
+ && status == other.status
&& price.equals(other.price);
}
diff --git a/ts-common/src/main/java/edu/fudan/common/entity/OrderAlterInfo.java b/ts-common/src/main/java/edu/fudan/common/entity/OrderAlterInfo.java
index 812c87f7f7..24ffc4ab60 100644
--- a/ts-common/src/main/java/edu/fudan/common/entity/OrderAlterInfo.java
+++ b/ts-common/src/main/java/edu/fudan/common/entity/OrderAlterInfo.java
@@ -2,12 +2,14 @@
import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
/**
* @author fdse
*/
@Data
+@NoArgsConstructor
@AllArgsConstructor
public class OrderAlterInfo {
private String accountId;
@@ -18,7 +20,11 @@ public class OrderAlterInfo {
private Order newOrderInfo;
- public OrderAlterInfo(){
- newOrderInfo = new Order();
+ public OrderAlterInfo(String accountId, String previousOrderId, String loginToken){
+ this.accountId = accountId;
+ this.previousOrderId = previousOrderId;
+ this.loginToken = loginToken;
+ this.newOrderInfo = new Order();
+ this.newOrderInfo.initOrder();
}
}
diff --git a/ts-common/src/main/java/edu/fudan/common/entity/TripInfo.java b/ts-common/src/main/java/edu/fudan/common/entity/TripInfo.java
index d406402d7c..9412b331d3 100644
--- a/ts-common/src/main/java/edu/fudan/common/entity/TripInfo.java
+++ b/ts-common/src/main/java/edu/fudan/common/entity/TripInfo.java
@@ -1,8 +1,6 @@
package edu.fudan.common.entity;
import edu.fudan.common.util.StringUtils;
-import lombok.AllArgsConstructor;
-import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
@@ -11,8 +9,6 @@
/**
* @author fdse
*/
-@Data
-@AllArgsConstructor
public class TripInfo {
@Valid
@NotNull
@@ -33,14 +29,36 @@ public TripInfo(){
this.departureTime = "";
}
+ public TripInfo(String startPlace, String endPlace, String departureTime) {
+ this.startPlace = startPlace;
+ this.endPlace = endPlace;
+ this.departureTime = departureTime;
+ }
+
public String getStartPlace() {
return StringUtils.String2Lower(this.startPlace);
}
+ public void setStartPlace(String startPlace) {
+ this.startPlace = startPlace;
+ }
+
public String getEndPlace() {
return StringUtils.String2Lower(this.endPlace);
}
+ public void setEndPlace(String endPlace) {
+ this.endPlace = endPlace;
+ }
+
+ public String getDepartureTime() {
+ return departureTime;
+ }
+
+ public void setDepartureTime(String departureTime) {
+ this.departureTime = departureTime;
+ }
+
// public Date getDepartureTime(){
// return StringUtils.String2Date(this.departureTime);
// }
diff --git a/ts-common/src/main/java/edu/fudan/common/util/Response.java b/ts-common/src/main/java/edu/fudan/common/util/Response.java
index 3b2face56c..6448e8d882 100644
--- a/ts-common/src/main/java/edu/fudan/common/util/Response.java
+++ b/ts-common/src/main/java/edu/fudan/common/util/Response.java
@@ -5,12 +5,12 @@
import lombok.NoArgsConstructor;
import lombok.ToString;
+import java.util.Objects;
+
/**
* @author fdse
*/
@Data
-@AllArgsConstructor
-@NoArgsConstructor
@ToString
public class Response {
@@ -21,4 +21,84 @@ public class Response {
String msg;
T data;
+
+ /**
+ * Default constructor
+ */
+ public Response() {
+ }
+
+ /**
+ * Constructor with all parameters
+ * @param status the status (1 for true, 0 for false)
+ * @param msg the message
+ * @param data the data
+ */
+ public Response(Integer status, String msg, T data) {
+ this.status = status;
+ this.msg = msg;
+ this.data = data;
+ }
+
+ /**
+ * Constructor with status and message only
+ * @param status the status (1 for true, 0 for false)
+ * @param msg the message
+ */
+ public Response(Integer status, String msg) {
+ this.status = status;
+ this.msg = msg;
+ this.data = null;
+ }
+
+ /**
+ * Constructor with status and data only
+ * @param status the status (1 for true, 0 for false)
+ * @param data the data
+ */
+ public Response(Integer status, T data) {
+ this.status = status;
+ this.msg = null;
+ this.data = data;
+ }
+
+ // Getters and Setters
+ public Integer getStatus() {
+ return status;
+ }
+
+ public void setStatus(Integer status) {
+ this.status = status;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Response> response = (Response>) o;
+ return Objects.equals(status, response.status) &&
+ Objects.equals(msg, response.msg) &&
+ Objects.equals(data, response.data);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(status, msg, data);
+ }
}
diff --git a/ts-food-delivery-service/pom.xml b/ts-food-delivery-service/pom.xml
index 78bed3dd6f..c6df75991d 100644
--- a/ts-food-delivery-service/pom.xml
+++ b/ts-food-delivery-service/pom.xml
@@ -42,6 +42,18 @@
jakarta.validation-api
2.0.2
+
+
+ org.hibernate.validator
+ hibernate-validator
+ 6.2.5.Final
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
diff --git a/ts-food-delivery-service/src/main/java/food_delivery/entity/DeliveryInfo.java b/ts-food-delivery-service/src/main/java/food_delivery/entity/DeliveryInfo.java
index 2e2cb1815f..1aaef11fdd 100644
--- a/ts-food-delivery-service/src/main/java/food_delivery/entity/DeliveryInfo.java
+++ b/ts-food-delivery-service/src/main/java/food_delivery/entity/DeliveryInfo.java
@@ -4,10 +4,43 @@
import lombok.Data;
import lombok.NoArgsConstructor;
+import java.util.Objects;
+
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryInfo {
private String orderId;
private String deliveryTime;
+
+ // Getters and Setters
+ public String getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getDeliveryTime() {
+ return deliveryTime;
+ }
+
+ public void setDeliveryTime(String deliveryTime) {
+ this.deliveryTime = deliveryTime;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DeliveryInfo that = (DeliveryInfo) o;
+ return Objects.equals(orderId, that.orderId) &&
+ Objects.equals(deliveryTime, that.deliveryTime);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId, deliveryTime);
+ }
}
diff --git a/ts-food-delivery-service/src/main/java/food_delivery/entity/FoodDeliveryOrder.java b/ts-food-delivery-service/src/main/java/food_delivery/entity/FoodDeliveryOrder.java
index a27f5861d2..d6a654de95 100644
--- a/ts-food-delivery-service/src/main/java/food_delivery/entity/FoodDeliveryOrder.java
+++ b/ts-food-delivery-service/src/main/java/food_delivery/entity/FoodDeliveryOrder.java
@@ -1,21 +1,18 @@
package food_delivery.entity;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.util.List;
+import java.util.Objects;
import edu.fudan.common.entity.Food;
@Data
@Entity
@GenericGenerator(name = "jpa-uuid", strategy = "uuid")
@JsonIgnoreProperties(ignoreUnknown = true)
-@AllArgsConstructor
-@NoArgsConstructor
public class FoodDeliveryOrder {
@Id
@@ -37,4 +34,99 @@ public class FoodDeliveryOrder {
private String deliveryTime;
private double deliveryFee;
+
+ public FoodDeliveryOrder() {
+ // Default constructor
+ }
+
+ public FoodDeliveryOrder(String id, String stationFoodStoreId, List foodList,
+ String tripId, int seatNo, String createdTime,
+ String deliveryTime, double deliveryFee) {
+ this.id = id;
+ this.stationFoodStoreId = stationFoodStoreId;
+ this.foodList = foodList;
+ this.tripId = tripId;
+ this.seatNo = seatNo;
+ this.createdTime = createdTime;
+ this.deliveryTime = deliveryTime;
+ this.deliveryFee = deliveryFee;
+ }
+
+ // Getters and Setters
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getStationFoodStoreId() {
+ return stationFoodStoreId;
+ }
+
+ public void setStationFoodStoreId(String stationFoodStoreId) {
+ this.stationFoodStoreId = stationFoodStoreId;
+ }
+
+ public List getFoodList() {
+ return foodList;
+ }
+
+ public void setFoodList(List foodList) {
+ this.foodList = foodList;
+ }
+
+ public String getTripId() {
+ return tripId;
+ }
+
+ public void setTripId(String tripId) {
+ this.tripId = tripId;
+ }
+
+ public int getSeatNo() {
+ return seatNo;
+ }
+
+ public void setSeatNo(int seatNo) {
+ this.seatNo = seatNo;
+ }
+
+ public String getCreatedTime() {
+ return createdTime;
+ }
+
+ public void setCreatedTime(String createdTime) {
+ this.createdTime = createdTime;
+ }
+
+ public String getDeliveryTime() {
+ return deliveryTime;
+ }
+
+ public void setDeliveryTime(String deliveryTime) {
+ this.deliveryTime = deliveryTime;
+ }
+
+ public double getDeliveryFee() {
+ return deliveryFee;
+ }
+
+ public void setDeliveryFee(double deliveryFee) {
+ this.deliveryFee = deliveryFee;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ FoodDeliveryOrder that = (FoodDeliveryOrder) o;
+ return Objects.equals(id, that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
}
diff --git a/ts-food-delivery-service/src/main/java/food_delivery/entity/SeatInfo.java b/ts-food-delivery-service/src/main/java/food_delivery/entity/SeatInfo.java
index 615fccc523..02a072f8a2 100644
--- a/ts-food-delivery-service/src/main/java/food_delivery/entity/SeatInfo.java
+++ b/ts-food-delivery-service/src/main/java/food_delivery/entity/SeatInfo.java
@@ -4,10 +4,43 @@
import lombok.Data;
import lombok.NoArgsConstructor;
+import java.util.Objects;
+
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SeatInfo {
private String orderId;
private int seatNo;
+
+ // Getters and Setters
+ public String getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public int getSeatNo() {
+ return seatNo;
+ }
+
+ public void setSeatNo(int seatNo) {
+ this.seatNo = seatNo;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SeatInfo seatInfo = (SeatInfo) o;
+ return seatNo == seatInfo.seatNo &&
+ Objects.equals(orderId, seatInfo.orderId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId, seatNo);
+ }
}
\ No newline at end of file
diff --git a/ts-food-delivery-service/src/main/java/food_delivery/entity/StationFoodStoreInfo.java b/ts-food-delivery-service/src/main/java/food_delivery/entity/StationFoodStoreInfo.java
index 6138db4496..8a88cbc09f 100644
--- a/ts-food-delivery-service/src/main/java/food_delivery/entity/StationFoodStoreInfo.java
+++ b/ts-food-delivery-service/src/main/java/food_delivery/entity/StationFoodStoreInfo.java
@@ -6,6 +6,7 @@
import lombok.NoArgsConstructor;
import java.util.List;
+import java.util.Objects;
import edu.fudan.common.entity.Food;
@Data
@@ -15,17 +16,86 @@
public class StationFoodStoreInfo {
private String id;
-
private String stationId;
-
private String storeName;
-
private String telephone;
-
private String businessTime;
-
private double deliveryFee;
-
private List foodList;
+ // Getters and Setters
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getStationId() {
+ return stationId;
+ }
+
+ public void setStationId(String stationId) {
+ this.stationId = stationId;
+ }
+
+ public String getStoreName() {
+ return storeName;
+ }
+
+ public void setStoreName(String storeName) {
+ this.storeName = storeName;
+ }
+
+ public String getTelephone() {
+ return telephone;
+ }
+
+ public void setTelephone(String telephone) {
+ this.telephone = telephone;
+ }
+
+ public String getBusinessTime() {
+ return businessTime;
+ }
+
+ public void setBusinessTime(String businessTime) {
+ this.businessTime = businessTime;
+ }
+
+ public double getDeliveryFee() {
+ return deliveryFee;
+ }
+
+ public void setDeliveryFee(double deliveryFee) {
+ this.deliveryFee = deliveryFee;
+ }
+
+ public List getFoodList() {
+ return foodList;
+ }
+
+ public void setFoodList(List foodList) {
+ this.foodList = foodList;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ StationFoodStoreInfo that = (StationFoodStoreInfo) o;
+ return Double.compare(that.deliveryFee, deliveryFee) == 0 &&
+ Objects.equals(id, that.id) &&
+ Objects.equals(stationId, that.stationId) &&
+ Objects.equals(storeName, that.storeName) &&
+ Objects.equals(telephone, that.telephone) &&
+ Objects.equals(businessTime, that.businessTime) &&
+ Objects.equals(foodList, that.foodList);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, stationId, storeName, telephone, businessTime, deliveryFee, foodList);
+ }
}
diff --git a/ts-food-delivery-service/src/main/java/food_delivery/entity/TripOrderInfo.java b/ts-food-delivery-service/src/main/java/food_delivery/entity/TripOrderInfo.java
index eda0a58a5d..a1e48e2623 100644
--- a/ts-food-delivery-service/src/main/java/food_delivery/entity/TripOrderInfo.java
+++ b/ts-food-delivery-service/src/main/java/food_delivery/entity/TripOrderInfo.java
@@ -4,10 +4,43 @@
import lombok.Data;
import lombok.NoArgsConstructor;
+import java.util.Objects;
+
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TripOrderInfo {
private String orderId;
private String tripId;
+
+ // Getters and Setters
+ public String getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getTripId() {
+ return tripId;
+ }
+
+ public void setTripId(String tripId) {
+ this.tripId = tripId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ TripOrderInfo that = (TripOrderInfo) o;
+ return Objects.equals(orderId, that.orderId) &&
+ Objects.equals(tripId, that.tripId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId, tripId);
+ }
}
diff --git a/ts-route-service/src/test/java/route/service/RouteServiceImplTest.java b/ts-route-service/src/test/java/route/service/RouteServiceImplTest.java
index 572b13fdad..75249db8fc 100644
--- a/ts-route-service/src/test/java/route/service/RouteServiceImplTest.java
+++ b/ts-route-service/src/test/java/route/service/RouteServiceImplTest.java
@@ -17,6 +17,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import java.util.UUID;
@RunWith(JUnit4.class)
@@ -47,7 +48,7 @@ public void testCreateAndModify2() {
RouteInfo info = new RouteInfo("id", "start_station", "end_station", "shanghai", "5");
Mockito.when(routeRepository.save(Mockito.any(Route.class))).thenReturn(null);
Response result = routeServiceImpl.createAndModify(info, headers);
- Assert.assertEquals("Save Success", result.getMsg());
+ Assert.assertEquals("Save and Modify success", result.getMsg());
}
@Test
@@ -56,13 +57,13 @@ public void testCreateAndModify3() {
Mockito.when(routeRepository.findById(Mockito.anyString())).thenReturn(null);
Mockito.when(routeRepository.save(Mockito.any(Route.class))).thenReturn(null);
Response result = routeServiceImpl.createAndModify(info, headers);
- Assert.assertEquals("Modify success", result.getMsg());
+ Assert.assertEquals("Save and Modify success", result.getMsg());
}
@Test
public void testDeleteRoute1() {
Mockito.doNothing().doThrow(new RuntimeException()).when(routeRepository).removeRouteById(Mockito.anyString());
- Mockito.when(routeRepository.findById(Mockito.anyString())).thenReturn(null);
+ Mockito.when(routeRepository.findById(Mockito.anyString())).thenReturn(Optional.empty());
Response result = routeServiceImpl.deleteRoute("route_id", headers);
Assert.assertEquals(new Response<>(1, "Delete Success", "route_id"), result);
}
@@ -71,14 +72,14 @@ public void testDeleteRoute1() {
public void testDeleteRoute2() {
Route route = new Route();
Mockito.doNothing().doThrow(new RuntimeException()).when(routeRepository).removeRouteById(Mockito.anyString());
- Mockito.when(routeRepository.findById(Mockito.anyString()).get()).thenReturn(route);
+ Mockito.when(routeRepository.findById(Mockito.anyString())).thenReturn(Optional.of(route));
Response result = routeServiceImpl.deleteRoute("route_id", headers);
Assert.assertEquals(new Response<>(0, "Delete failed, Reason unKnown with this routeId", "route_id"), result);
}
@Test
public void testGetRouteById1() {
- Mockito.when(routeRepository.findById(Mockito.anyString())).thenReturn(null);
+ Mockito.when(routeRepository.findById(Mockito.anyString())).thenReturn(Optional.empty());
Response result = routeServiceImpl.getRouteById("route_id", headers);
Assert.assertEquals(new Response<>(0, "No content with the routeId", null), result);
}
@@ -86,9 +87,9 @@ public void testGetRouteById1() {
@Test
public void testGetRouteById2() {
Route route = new Route();
- Mockito.when(routeRepository.findById(Mockito.anyString()).get()).thenReturn(route);
+ Mockito.when(routeRepository.findById(Mockito.anyString())).thenReturn(Optional.of(route));
Response result = routeServiceImpl.getRouteById("route_id", headers);
- Assert.assertEquals(new Response<>(1, "Success", route), result);
+ Assert.assertEquals(new Response<>(1, "Success", Optional.of(route)), result);
}
@Test