1) Spring Boot (with REST & MySQL JPA)
Project type: Spring Boot (Maven).
Java version: 11+ recommended.
pom.xml (essential deps)
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>profitloss-service</artifactId>
<version>1.0.0</version>
<properties>
<java.version>11</java.version>
<spring.boot.version>3.1.0</spring.boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
src/main/resources/application.properties
Replace username/password/dbname with your MySQL values.
spring.datasource.url=jdbc:mysql://localhost:3306/profitlossdb?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
server.port=8080
Domain: com.example.profitloss.model.Calculation.java
package com.example.profitloss.model;
import jakarta.persistence.*;
import java.time.Instant;
@Entity
public class Calculation {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private double cp;
private double sp;
private double amount; // profit or loss magnitude
private double percent;
private boolean isProfit; // true -> profit, false -> loss (if equal, treat as neither)
private Instant createdAt = Instant.now();
// Constructors, getters, setters
public Calculation() {}
public Calculation(double cp, double sp, double amount, double percent, boolean isProfit) {
this.cp = cp; this.sp = sp; this.amount = amount; this.percent = percent; this.isProfit = isProfit;
}
// getters and setters omitted for brevity (generate in IDE)
// ...
public Long getId(){return id;}
public double getCp(){return cp;}
public void setCp(double cp){this.cp=cp;}
public double getSp(){return sp;}
public void setSp(double sp){this.sp=sp;}
public double getAmount(){return amount;}
public void setAmount(double amt){this.amount=amt;}
public double getPercent(){return percent;}
public void setPercent(double p){this.percent=p;}
public boolean isProfit(){return isProfit;}
public void setProfit(boolean profit){this.isProfit=profit;}
public Instant getCreatedAt(){return createdAt;}
public void setCreatedAt(Instant t){this.createdAt=t;}
}
Repository: CalculationRepository.java
package com.example.profitloss.repo;
import com.example.profitloss.model.Calculation;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CalculationRepository extends JpaRepository<Calculation, Long> {}
DTO: CalculateRequest.java
package com.example.profitloss.dto;
import jakarta.validation.constraints.Min;
public class CalculateRequest {
@Min(value = 0, message = "Cost price must be >= 0")
private double cp;
@Min(value = 0, message = "Selling price must be >= 0")
private double sp;
public double getCp(){return cp;}
public void setCp(double cp){this.cp=cp;}
public double getSp(){return sp;}
public void setSp(double sp){this.sp=sp;}
}
Response DTO: CalculateResponse.java
package com.example.profitloss.dto;
public class CalculateResponse {
private String type; // "profit","loss","no-profit-no-loss"
private double amount;
private double percent;
private long id; // persisted record id (if saved)
public CalculateResponse(String type, double amount, double percent, long id){
this.type = type; this.amount = amount; this.percent = percent; this.id = id;
}
// getters
public String getType(){return type;}
public double getAmount(){return amount;}
public double getPercent(){return percent;}
public long getId(){return id;}
}
Service: CalculationService.java
package com.example.profitloss.service;
import com.example.profitloss.dto.CalculateRequest;
import com.example.profitloss.model.Calculation;
import com.example.profitloss.repo.CalculationRepository;
import org.springframework.stereotype.Service;
@Service
public class CalculationService {
private final CalculationRepository repo;
public CalculationService(CalculationRepository repo){
this.repo = repo;
}
public Calculation calculateAndSave(double cp, double sp){
if (cp == sp) {
Calculation calc = new Calculation(cp, sp, 0.0, 0.0, false);
return repo.save(calc);
}
boolean isProfit = sp > cp;
double amount = Math.abs(sp - cp);
double percent = (amount / cp) * 100;
Calculation calc = new Calculation(cp, sp, amount, percent, isProfit);
return repo.save(calc);
}
}
Controller (REST): CalculationController.java
package com.example.profitloss.controller;
import com.example.profitloss.dto.CalculateRequest;
import com.example.profitloss.dto.CalculateResponse;
import com.example.profitloss.model.Calculation;
import com.example.profitloss.service.CalculationService;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class CalculationController {
private final CalculationService service;
public CalculationController(CalculationService service){
this.service = service;
}
// POST /api/calculate -> saves to DB and returns result
@PostMapping("/calculate")
public ResponseEntity<CalculateResponse> calculateAndSave(@Valid @RequestBody CalculateRequest req) {
Calculation saved = service.calculateAndSave(req.getCp(), req.getSp());
String type;
if (saved.getAmount() == 0.0) type = "no-profit-no-loss";
else type = saved.isProfit() ? "profit" : "loss";
CalculateResponse resp = new CalculateResponse(type, saved.getAmount(), saved.getPercent(), saved.getId());
return ResponseEntity.ok(resp);
}
// GET /api/calculation/{id} -> fetch saved calculation
@GetMapping("/calculation/{id}")
public ResponseEntity<Calculation> getById(@PathVariable Long id) {
return service.repo.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
}
Note: For brevity
service.repowas used in controller GET. In production extract via service method.
Application main
package com.example.profitloss;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProfitlossServiceApplication {
public static void main(String[] args){
SpringApplication.run(ProfitlossServiceApplication.class, args);
}
}
How to run
- Start MySQL and create DB
profitlossdb(or let JPA create; ensure user has privileges).
Example:CREATE DATABASE profitlossdb; - Update
application.propertiescredentials. mvn spring-boot:runor build jar.
Example REST call (curl)
curl -X POST http://localhost:8080/api/calculate \
-H "Content-Type: application/json" \
-d '{"cp":500,"sp":650}'
Response:
{"type":"profit","amount":150.0,"percent":30.0,"id":1}
2) MySQL Integration (already included above)
- JPA entity
Calculationpersists each calculation. spring.jpa.hibernate.ddl-auto=updatewill create the table automatically.- You can query results via JPA repository or exposed REST endpoint.
If you want explicit SQL schema:
CREATE TABLE calculation (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
cp DOUBLE,
sp DOUBLE,
amount DOUBLE,
percent DOUBLE,
is_profit BOOLEAN,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
3) REST API (standalone description)
The Spring Boot app provides:
POST /api/calculate— accepts JSON{ "cp": <number>, "sp": <number> }and returns{ type, amount, percent, id }. Saves to DB.GET /api/calculation/{id}— fetch saved record.
Validation: @Min(0) on input; add more error handling as needed.
4) Kotlin Android App (Android Studio)
Minimum: Android Gradle Plugin + Kotlin. Create new project (Empty Activity) and replace files.
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="24dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/etCP"
android:hint="Cost Price (CP)"
android:inputType="numberDecimal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/etSP"
android:hint="Selling Price (SP)"
android:inputType="numberDecimal"
android:layout_marginTop="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btnCalculate"
android:text="Calculate"
android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tvResult"
android:textSize="18sp"
android:layout_marginTop="18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.kt
package com.example.profitlossapp
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private lateinit var etCP: EditText
private lateinit var etSP: EditText
private lateinit var btnCalculate: Button
private lateinit var tvResult: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
etCP = findViewById(R.id.etCP)
etSP = findViewById(R.id.etSP)
btnCalculate = findViewById(R.id.btnCalculate)
tvResult = findViewById(R.id.tvResult)
btnCalculate.setOnClickListener {
val cpText = etCP.text.toString().trim()
val spText = etSP.text.toString().trim()
if (cpText.isEmpty() || spText.isEmpty()) {
tvResult.text = "Please enter both CP and SP."
return@setOnClickListener
}
val cp = cpText.toDoubleOrNull()
val sp = spText.toDoubleOrNull()
if (cp == null || sp == null) {
tvResult.text = "Invalid numbers."
return@setOnClickListener
}
if (cp == 0.0) {
tvResult.text = "CP cannot be zero for percentage calculation."
return@setOnClickListener
}
when {
sp > cp -> {
val profit = sp - cp
val percent = profit / cp * 100
tvResult.text = "Profit: %.2f\nProfit %%: %.2f".format(profit, percent)
}
cp > sp -> {
val loss = cp - sp
val percent = loss / cp * 100
tvResult.text = "Loss: %.2f\nLoss %%: %.2f".format(loss, percent)
}
else -> {
tvResult.text = "No Profit, No Loss."
}
}
}
}
}
Optional: Call Spring Boot REST from Android
- Add Retrofit or OkHttp to
build.gradleand POST to/api/calculateto persist results remotely.
Final notes & next steps
- The Spring Boot project already includes REST endpoints and MySQL JPA integration — that covers items (1)-(3).
- The Kotlin Android project is a simple UI app; it can be extended to call the REST API to persist calculations remotely.