Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Branch Performance Aggregation and Therapist Performance View Features

Tech 1

Aggregate Real Monthly and Annual Branch Performance

Implementation approach: Sum the performance of all therapists assigned to the branch to get total branch performance.

No frontend changes required.

Backend Implementation

// Accumulate therapist performance points to the branch's monthly and annual total performance
// Query the branch associated with the assigned therapist
String branchId = therapistService.getBranchByTherapistId(regularAppointment.getAssignedTherapistId());
// Update cumulative performance in branch monthly and annual statistics tables
int monthlyUpdateResult = monthlyBranchStatsService.updateMonthlyPerformance(branchId, Integer.parseInt(projectPoints));
int annualUpdateResult = annualBranchStatsService.updateAnnualPerformance(branchId, Integer.parseInt(projectPoints));

System.out.println("Annual update result: " + annualUpdateResult);
System.out.println("Monthly update result: " + monthlyUpdateResult);
System.out.println("Target branch ID: " + branchId);
// Repeat logic for member appointment records
// Accumulate therapist performance points to the branch's monthly and annual total performance
// Query the branch associated with the assigned therapist
String branchId = therapistService.getBranchByTherapistId(memberAppointment.getAssignedTherapistId());
System.out.println("Target branch ID: " + branchId);
// Update cumulative performance in branch monthly and annual statistics tables
int monthlyUpdateResult = monthlyBranchStatsService.updateMonthlyPerformance(branchId, Integer.parseInt(projectPoints));
int annualUpdateResult = annualBranchStatsService.updateAnnualPerformance(branchId, Integer.parseInt(projectPoints));

System.out.println("Annual update result: " + annualUpdateResult);
System.out.println("Monthly update result: " + monthlyUpdateResult);

Update Monthly and Annual Therapy Project Booking & Revenue Statistics

Implementation approach: After an admin approves an appointment, increment the project's booking count by 1, and add the project price to the cumulative sales revenue, for both monthly and annual statistics.

No frontend changes required.

Backend Implementation

// Update monthly and annual booking count and revenue for the reserved therapy project
// First check if a statistical record already exists for the project
int monthlyExistingCount = projectMonthlyStatsService.checkProjectExists(regularAppointment.getProjectName());
int annualExistingCount = projectAnnualStatsService.checkProjectExists(regularAppointment.getProjectName());

System.out.println("Annual existing record count: " + annualExistingCount);
System.out.println("Monthly existing record count: " + monthlyExistingCount);

// Update existing record, insert new if not exists
if (monthlyExistingCount != 0) {
    // Update monthly booking count and total revenue
    projectMonthlyStatsService.incrementMonthlyStats(regularAppointment.getProjectName(), projectPrice);
} else {
    TherapyProjectMonthlyStat monthlyStat = new TherapyProjectMonthlyStat();
    monthlyStat.setId(System.currentTimeMillis() + (long) (Math.random() * 1000));
    monthlyStat.setCreateTime(new DateTime());
    monthlyStat.setStatDate(new DateTime());
    monthlyStat.setProjectName(regularAppointment.getProjectName());
    monthlyStat.setProjectCover(projectImageUrl);
    monthlyStat.setMonthlyBookingCount(1);
    monthlyStat.setMonthlyRevenue(Integer.parseInt(projectPoints));
    projectMonthlyStatsService.insert(monthlyStat);
}

// Process annual statistics
if (annualExistingCount != 0) {
    // Update annual booking count and total revenue
    projectAnnualStatsService.incrementAnnualStats(regularAppointment.getProjectName(), projectPrice);
} else {
    TherapyProjectAnnualStat annualStat = new TherapyProjectAnnualStat();
    annualStat.setId(System.currentTimeMillis() + (long) (Math.random() * 1000));
    annualStat.setCreateTime(new DateTime());
    annualStat.setStatDate(new DateTime());
    annualStat.setProjectName(regularAppointment.getProjectName());
    annualStat.setProjectCover(projectImageUrl);
    annualStat.setAnnualBookingCount(1);
    annualStat.setAnnualRevenue(Integer.parseInt(projectPoints));
    projectAnnualStatsService.insert(annualStat);
}
// Get project cover image for member appointment records
String projectImageUrl = therapyProjectService.getProjectCover(memberAppointment.getProjectName());

System.out.println("Member annual existing count: " + annualExistingCount);
System.out.println("Member monthly existing count: " + monthlyExistingCount);

if (monthlyExistingCount != 0) {
    projectMonthlyStatsService.incrementMonthlyStats(memberAppointment.getProjectName(), projectPrice);
} else {
    TherapyProjectMonthlyStat monthlyStat = new TherapyProjectMonthlyStat();
    monthlyStat.setId(System.currentTimeMillis() + (long) (Math.random() * 1000));
    monthlyStat.setCreateTime(new DateTime());
    monthlyStat.setStatDate(new DateTime());
    monthlyStat.setProjectName(memberAppointment.getProjectName());
    monthlyStat.setProjectCover(projectImageUrl);
    monthlyStat.setMonthlyBookingCount(1);
    monthlyStat.setMonthlyRevenue(Integer.parseInt(projectPoints));
    projectMonthlyStatsService.insert(monthlyStat);
}

// Process annual statistics for member appointments
if (annualExistingCount != 0) {
    projectAnnualStatsService.incrementAnnualStats(memberAppointment.getProjectName(), projectPrice);
} else {
    TherapyProjectAnnualStat annualStat = new TherapyProjectAnnualStat();
    annualStat.setId(System.currentTimeMillis() + (long) (Math.random() * 1000));
    annualStat.setCreateTime(new DateTime());
    annualStat.setStatDate(new DateTime());
    annualStat.setProjectName(memberAppointment.getProjectName());
    annualStat.setProjectCover(projectImageUrl);
    annualStat.setAnnualBookingCount(1);
    annualStat.setAnnualRevenue(Integer.parseInt(projectPoints));
    projectAnnualStatsService.insert(annualStat);
}

Update Multiple Columns in Single SQL Udpate Statement

UPDATE target_table
SET column_one = target_value_1,
    column_two = target_value_2
WHERE match_condition;

Therapist Personal Performance View

Implementation approach: Create a new Vue page by copying an existing ECharts template. Backend queries all matching appointments (both regular user and member) assigned to the current logged in therapist, frontend aggregates and displays data grouped by project name, following the implementation pattern of existing appointment pages.

Get Current Logged In Username in Vue

Implementation approach: Retrieve the logged in account name from local storage, pass it as a parameter to the backend API.

Frontend Code

// Fetch therapist info by logged in account
getTherapistInfo(accountName) {
  this.$http({
    url: `therapist/name/${accountName}`,
    method: 'get'
  }).then(res => {
    console.log(res.data.data);
    this.therapistFullName = res.data.data;
    console.log("Therapist name query succeeded");
  })
}

Backend Code

/**
 * Query therapist full name by therapist account
 */
@GetMapping("/name/{accountName}")
public R getTherapistName(@PathVariable("accountName") String account) {
  String fullName = therapistService.queryTherapistNameByAccount(account);
  return R.ok().put("data", fullName);
}

MyBatis Mapper:

<select id="queryTherapistNameByAccount" resultType="java.lang.String">
  SELECT therapist_full_name
  FROM therapist
  WHERE therapist_work_number = #{account};
</select>

Therapist Management & Performance Page for Branch Admin

Implementation approach: Query the branch associated with the logged in branch admin account, pass the branch identifier as a parameter to fetch performance data for all therapists under that branch, then render the performance chart.

Frontend Code

console.log("Logged in branch admin account: ");
console.log(this.$storage.get('adminName'));
this.renderMonthlyChart();

let currentAccount = this.$storage.get('adminName');
if (!this.branchName) {
  this.$http({
    url: `branch/info/${currentAccount}`,
    method: 'get'
  }).then(res => {
    console.log(res.data.data);
    this.branchName = res.data.data;
    this.fetchTherapistPerformanceData();
    this.renderAnnualChart();
  }).catch(err => {
    console.log(err);
    console.log("Failed to fetch branch information");
  })
} else {
  this.fetchTherapistPerformanceData();
  this.renderAnnualChart();
}

function fetchTherapistPerformanceData() {
  this.$http({
    url: `therapist/annual/stats/branch/${this.branchName}`,
    method: 'get'
  }).then(res => {
    console.log(res.data);
    let therapistStats = res.data.therapistAnnualStats;
    let performanceData = [];

    for (let i = 0; i < therapistStats.length; i++) {
      let item = { name: '', value: 0 };
      item.name = therapistStats[i].therapistName;
      item.value = therapistStats[i].annualPerformance;
      performanceData.push(item);
    }

    // Sort descending by performance value
    performanceData.sort((a, b) => b.value - a.value);
    this.performanceData = performanceData;
    this.renderMonthlyChart();
  }).catch(err => {
    console.log(err);
    console.log("Failed to fetch therapist performance data");
  })
}

Backend Code

/**
 * Get annual performance data for all therapists under a branch for pie chart rendering
 */
@GetMapping("/branch/performance/{branchName}")
public Map<String, List<TherapistAnnualStatEntity>> getBranchTherapistPerformance(@PathVariable("branchName") String branchName) {
  HashMap<String, List<TherapistAnnualStatEntity>> resultMap = new HashMap<>();
  // Get all therapist names assigned to the target branch
  List<String> therapistList = therapistService.getTherapistNamesByBranch(branchName);

  for (int i = 0; i < therapistList.size(); i++) {
    System.out.println("Therapist " + i + ": " + therapistList.get(i));
  }

  // Query matching performance records from the annual statistics table
  resultMap.put("therapistAnnualStats", therapistAnnualStatsService.queryTherapistPerformanceByNames(therapistList));
  return resultMap;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.