Repository: ministryofjustice/laa-landing-page
Pull request #57: STB-1570: Initial Version of Data Model for LAA
Author: login: sureshkavali-moj
Created: 2025-05-15T14:39:30Z | Merged: 2025-05-21T09:46:56Z

Initial Version of Data Model for LAA


The table creation queries generated by Hibernate are


```
create table entra_app_registration (entra_app_registration_id uuid not null, app_registration_name varchar(255) not null, primary key (entra_app_registration_id))
create table entra_user (is_active boolean not null, end_date timestamp(6), start_date timestamp(6), entra_user_id uuid not null, email varchar(255) not null unique, first_name varchar(255) not null, last_name varchar(255) not null, user_type varchar(255) check (user_type in ('USER','ADMIN')), primary key (entra_user_id))
create table entra_user_app_registration (entra_app_registration_id uuid not null, entra_user_id uuid not null, primary key (entra_app_registration_id, entra_user_id))
create table firm (firm_id uuid not null, firm_name varchar(255) not null, firm_type varchar(255) not null check (firm_type in ('ADVOCATE','CHAMBERS','INDIVIDUAL','LEGAL_SERVICES_PROVIDER','QM_PROVIDER')), primary key (firm_id))
create table laa_app (entra_app_registration_id uuid not null unique, laa_app_id uuid not null, app_name varchar(255) not null, primary key (laa_app_id))
create table laa_app_role (app_role_id uuid not null, laa_app_id uuid not null, role_name varchar(255) not null, primary key (app_role_id))
create table laa_user_profile (is_admin boolean not null, is_multi_firm boolean not null, firm_id uuid, user_profile_id uuid not null, primary key (user_profile_id))
create table office (firm_id uuid not null, office_id uuid not null, office_address varchar(500), office_name varchar(255) not null, office_phone varchar(255), primary key (office_id))
create table user_profile_app_role (app_role_id uuid not null, user_profile_id uuid not null, primary key (app_role_id, user_profile_id))
create table user_profile_office (office_id uuid not null, user_profile_id uuid not null, primary key (office_id, user_profile_id))
create table users (uid integer generated by default as identity, email varchar(255) not null unique, fullName varchar(255) not null, id varchar(255), lastLoggedIn varchar(255), password varchar(255) not null, primary key (uid))
create index UserEmailIdx on entra_user (email)
create index FirmNameIdx on firm (firm_name)
alter table if exists entra_user_app_registration add constraint FK_entra_user_app_registration_entra_app_registration_id foreign key (entra_app_registration_id) references entra_app_registration
alter table if exists entra_user_app_registration add constraint FK_entra_user_app_registration_entra_user_id foreign key (entra_user_id) references entra_user
alter table if exists laa_app add constraint FK_laa_app_entra_app_registration_id foreign key (entra_app_registration_id) references entra_app_registration
alter table if exists laa_app_role add constraint FK_laa_app_role_laa_app_id foreign key (laa_app_id) references laa_app
alter table if exists laa_user_profile add constraint FK_laa_user_profile_firm_id foreign key (firm_id) references firm
alter table if exists office add constraint FK_office_firm_id foreign key (firm_id) references firm
alter table if exists user_profile_app_role add constraint FK_laa_app_role_user_profile_id foreign key (user_profile_id) references laa_user_profile
alter table if exists user_profile_app_role add constraint FK_laa_app_role_app_role_id foreign key (app_role_id) references laa_app_role
alter table if exists user_profile_office add constraint FK_laa_user_profile_office_office_id foreign key (office_id) references office
alter table if exists user_profile_office add constraint FK_laa_user_profile_office_user_profile_id foreign key (user_profile_id) references laa_user_profile


```

The Data Model generated from the tables created

![Screenshot 2025-05-15 at 15 58 33](https://github.com/user-attachments/assets/d54701b6-784c-4170-9101-460a0d9a2052)




Diff:
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/BaseEntity.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/BaseEntity.java
new file mode 100644
index 000000000..61223ad44
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/BaseEntity.java
@@ -0,0 +1,59 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.MappedSuperclass;
+import jakarta.validation.constraints.Size;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+@Getter
+@Setter
+@ToString
+@SuperBuilder(toBuilder = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@MappedSuperclass
+public abstract class BaseEntity implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "id", nullable = false)
+    private UUID id;
+
+    @Column(name = "created_date", nullable = false)
+    @CreatedDate
+    @NonNull
+    private LocalDateTime createdDate;
+
+    @Column(name = "created_by", nullable = false, length = 255)
+    @NonNull
+    @Size(min = 1, max = 255)
+    @CreatedBy
+    private String createdBy;
+
+    @Column(name = "last_modified_date", nullable = true)
+    @LastModifiedDate
+    private LocalDateTime lastModified;
+
+    @Column(name = "last_modified_by", nullable = true, length = 255)
+    @Size(min = 1, max = 255)
+    @LastModifiedBy
+    private String lastModifiedBy;
+
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraAppRegistration.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraAppRegistration.java
new file mode 100644
index 000000000..f774beaf0
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraAppRegistration.java
@@ -0,0 +1,52 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Index;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.OneToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "entra_app_registration", indexes = {
+    @Index(name = "EntraAppRegistrationCreatedByIdx", columnList = "created_by"),
+    @Index(name = "EntraAppRegistrationCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "EntraAppRegistrationLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "EntraAppRegistrationLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "EntraAppRegistrationNameIdx", columnList = "name")
+    }
+)
+@Getter
+@Setter
+@SuperBuilder
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class EntraAppRegistration extends BaseEntity {
+
+    @Column(name = "name", nullable = false, length = 255, unique = true)
+    @Size(min = 1, max = 255)
+    private String name;
+
+    @ManyToMany(mappedBy = "userAppRegistrations", fetch = FetchType.LAZY)
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<EntraUser> entraUsers;
+
+    @OneToOne(mappedBy = "entraAppRegistration")
+    @ToString.Exclude
+    @JsonIgnore
+    private LaaApp laaApp;
+
+}
\ No newline at end of file
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraUser.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraUser.java
new file mode 100644
index 000000000..7a57d8699
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraUser.java
@@ -0,0 +1,87 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+
+import java.time.LocalDateTime;
+import java.util.Set;
+
+@Entity
+@Table(name = "entra_user", indexes = {
+    @Index(name = "EntraUserCreatedByIdx", columnList = "created_by"),
+    @Index(name = "EntraUserCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "EntraUserLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "EntraUserLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "EntraUserNameIdx", columnList = "first_name"),
+    @Index(name = "EntraUserNameIdx", columnList = "last_name"),
+    @Index(name = "EntraUserEmailIdx", columnList = "email"),
+})
+@Getter
+@Setter
+@SuperBuilder
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class EntraUser extends BaseEntity {
+
+    @Column(name = "first_name", nullable = false, length = 255)
+    @Size(min = 1, max = 255)
+    private String firstName;
+
+    @Column(name = "last_name", nullable = false, length = 255)
+    @Size(min = 1, max = 255)
+    private String lastName;
+
+    @Column(name = "email", nullable = false, length = 255, unique = true)
+    @Email
+    private String email;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "user_type", nullable = false, length = 255)
+    private UserType userType;
+
+    @Column(name = "is_active", nullable = false)
+    private boolean active;
+
+    @Column(name = "start_date")
+    private LocalDateTime startDate;
+
+    @Column(name = "end_date")
+    private LocalDateTime endDate;
+
+    @ManyToMany(fetch = FetchType.LAZY)
+    @JoinTable(
+            name = "entra_user_app_registration",
+            joinColumns = @JoinColumn(name = "entra_user_id"),
+            foreignKey = @ForeignKey(name = "FK_entra_user_app_registration_entra_user_id"),
+            inverseJoinColumns = @JoinColumn(name = "entra_app_registration_id"),
+            inverseForeignKey = @ForeignKey(name = "FK_entra_user_app_registration_entra_app_registration_id")
+    )
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<EntraAppRegistration> userAppRegistrations;
+
+    @OneToMany(mappedBy = "entraUser", fetch = FetchType.LAZY)
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<LaaUserProfile> laaUserProfiles;
+
+}
\ No newline at end of file
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java
new file mode 100644
index 000000000..b251cfc77
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java
@@ -0,0 +1,56 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Index;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+
+import java.util.Set;
+
+@Entity
+@Table(name = "firm", indexes = {
+    @Index(name = "FirmCreatedByIdx", columnList = "created_by"),
+    @Index(name = "FirmCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "FirmLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "FirmLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "FirmNameIdx", columnList = "name"),
+})
+@SuperBuilder
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Firm extends BaseEntity {
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "type", nullable = false, length = 255)
+    private FirmType type;
+
+    @Column(name = "name", nullable = false, length = 255, unique = true)
+    @Size(min = 1, max = 255)
+    private String name;
+
+    @OneToMany(mappedBy = "firm", fetch = FetchType.LAZY)
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<Office> offices;
+
+    @OneToMany(mappedBy = "firm", fetch = FetchType.LAZY)
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<LaaUserProfile> userProfiles;
+
+}
\ No newline at end of file
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/FirmType.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/FirmType.java
new file mode 100644
index 000000000..2d3287449
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/FirmType.java
@@ -0,0 +1,20 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import lombok.Getter;
+
+@Getter
+public enum FirmType {
+
+    ADVOCATE("Advocate"),
+    CHAMBERS("Chambers"),
+    INDIVIDUAL("Individual"),
+    LEGAL_SERVICES_PROVIDER("Legal Services Provider"),
+    QM_PROVIDER("QM Provider");
+
+    private final String value;
+
+    FirmType(String value) {
+        this.value = value;
+    }
+
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaApp.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaApp.java
new file mode 100644
index 000000000..c7759828a
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaApp.java
@@ -0,0 +1,51 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.OneToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.Set;
+
+@Entity
+@Table(name = "laa_app", indexes = {
+    @Index(name = "LaaAppCreatedByIdx", columnList = "created_by"),
+    @Index(name = "LaaAppCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "LaaAppLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "LaaAppLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "LaaAppNameIdx", columnList = "name"),
+})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class LaaApp extends BaseEntity {
+
+    @Column(name = "name", nullable = false, length = 255, unique = true)
+    @Size(min = 1, max = 255)
+    private String name;
+
+    @OneToOne
+    @JoinColumn(name = "entra_app_registration_id", nullable = false,
+            foreignKey = @ForeignKey(name = "FK_laa_app_entra_app_registration_id"))
+    @ToString.Exclude
+    @JsonIgnore
+    private EntraAppRegistration entraAppRegistration;
+
+    @OneToMany(mappedBy = "laaApp")
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<LaaAppRole> appRoles;
+
+}
\ No newline at end of file
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaAppRole.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaAppRole.java
new file mode 100644
index 000000000..ee9377b26
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaAppRole.java
@@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "laa_app_role", indexes = {
+    @Index(name = "LaaAppRoleCreatedByIdx", columnList = "created_by"),
+    @Index(name = "LaaAppRoleCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "LaaAppRoleLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "LaaAppRoleLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "LaaAppRoleNameIdx", columnList = "name"),
+})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class LaaAppRole extends BaseEntity {
+
+    @Column(name = "name", nullable = false, length = 255, unique = true)
+    @Size(min = 1, max = 255)
+    private String name;
+
+    @ManyToOne
+    @JoinColumn(name = "laa_app_id", nullable = false, foreignKey = @ForeignKey(name = "FK_laa_app_role_laa_app_id"))
+    @ToString.Exclude
+    @JsonIgnore
+    private LaaApp laaApp;
+
+    @ManyToMany(fetch = FetchType.LAZY)
+    @JoinTable(
+            name = "user_profile_app_role",
+            joinColumns = @JoinColumn(name = "laa_app_role_id"),
+            foreignKey = @ForeignKey(name = "FK_laa_app_role_app_role_id"),
+            inverseJoinColumns = @JoinColumn(name = "laa_user_profile_id"),
+            inverseForeignKey = @ForeignKey(name = "FK_laa_app_role_user_profile_id")
+    )
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<LaaUserProfile> userProfiles = new HashSet<>();
+
+}
\ No newline at end of file
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaUserProfile.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaUserProfile.java
new file mode 100644
index 000000000..bbc0a2b8b
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaUserProfile.java
@@ -0,0 +1,73 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+
+import java.util.Set;
+
+@Entity
+@Table(name = "laa_user_profile", indexes = {
+    @Index(name = "LaaUserProfileCreatedByIdx", columnList = "created_by"),
+    @Index(name = "LaaUserProfileCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "LaaUserProfileLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "LaaUserProfileLastModifiedByIdx", columnList = "last_modified_by"),
+})
+@Getter
+@Setter
+@SuperBuilder
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class LaaUserProfile extends BaseEntity {
+
+    @Column(name = "is_multi_firm", nullable = false)
+    private boolean multiFirm;
+
+    @Column(name = "is_admin", nullable = false)
+    private boolean admin;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "entra_user_id", foreignKey = @ForeignKey(name = "FK_laa_user_profile_entra_user_id"))
+    @ToString.Exclude
+    @JsonIgnore
+    private EntraUser entraUser;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "firm_id", foreignKey = @ForeignKey(name = "FK_laa_user_profile_firm_id"))
+    @ToString.Exclude
+    @JsonIgnore
+    private Firm firm;
+
+    @ManyToMany(fetch = FetchType.LAZY)
+    @JoinTable(
+        name = "laa_user_profile_office",
+            joinColumns = @JoinColumn(name = "laa_user_profile_id"),
+            foreignKey = @ForeignKey(name = "FK_laa_user_profile_office_user_profile_id"),
+            inverseJoinColumns = @JoinColumn(name = "office_id"),
+            inverseForeignKey = @ForeignKey(name = "FK_laa_user_profile_office_office_id")
+    )
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<Office> offices;
+
+
+    @ManyToMany(mappedBy = "userProfiles", fetch = FetchType.LAZY)
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<LaaAppRole> appRoles;
+
+}
\ No newline at end of file
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Office.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Office.java
new file mode 100644
index 000000000..d8eb3ba4c
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Office.java
@@ -0,0 +1,61 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+
+import java.util.Set;
+
+@Entity
+@Table(name = "office", indexes = {
+    @Index(name = "OfficeCreatedByIdx", columnList = "created_by"),
+    @Index(name = "OfficeCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "OfficeLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "OfficeLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "OfficeNameIdx", columnList = "name"),
+})
+@Getter
+@Setter
+@SuperBuilder
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Office extends BaseEntity {
+
+    @Column(name = "name", nullable = false, length = 255, unique = true)
+    @Size(min = 1, max = 255)
+    private String name;
+
+    @Column(name = "address", nullable = false, length = 500)
+    @Size(min = 1, max = 500)
+    private String address;
+
+    @Column(name = "phone", nullable = false, length = 255)
+    @Size(min = 1, max = 255)
+    private String phone;
+
+    @ManyToOne
+    @JoinColumn(name = "firm_id", nullable = false, foreignKey = @ForeignKey(name = "FK_office_firm_id"))
+    @ToString.Exclude
+    @JsonIgnore
+    private Firm firm;
+
+    @ManyToMany(mappedBy = "offices", fetch = FetchType.LAZY)
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<LaaUserProfile> userProfiles;
+
+}
\ No newline at end of file
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/UserType.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/UserType.java
new file mode 100644
index 000000000..35ae9c542
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/entity/UserType.java
@@ -0,0 +1,5 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+public enum UserType {
+    INTERNAL, EXTERNAL
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/EntraAppRegistrationRepository.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/EntraAppRegistrationRepository.java
new file mode 100644
index 000000000..dc905db18
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/EntraAppRegistrationRepository.java
@@ -0,0 +1,11 @@
+package uk.gov.justice.laa.portal.landingpage.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import uk.gov.justice.laa.portal.landingpage.entity.EntraAppRegistration;
+
+import java.util.UUID;
+
+@Repository
+public interface EntraAppRegistrationRepository extends JpaRepository<EntraAppRegistration, UUID> {
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/EntraUserRepository.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/EntraUserRepository.java
new file mode 100644
index 000000000..dc3e9eb0f
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/EntraUserRepository.java
@@ -0,0 +1,12 @@
+package uk.gov.justice.laa.portal.landingpage.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import uk.gov.justice.laa.portal.landingpage.entity.EntraUser;
+
+import java.util.UUID;
+
+@Repository
+public interface EntraUserRepository  extends JpaRepository<EntraUser, UUID> {
+
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/FirmRepository.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/FirmRepository.java
new file mode 100644
index 000000000..e1c00f796
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/FirmRepository.java
@@ -0,0 +1,11 @@
+package uk.gov.justice.laa.portal.landingpage.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import uk.gov.justice.laa.portal.landingpage.entity.Firm;
+
+import java.util.UUID;
+
+@Repository
+public interface FirmRepository extends JpaRepository<Firm, UUID> {
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaAppRepository.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaAppRepository.java
new file mode 100644
index 000000000..363527fb5
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaAppRepository.java
@@ -0,0 +1,11 @@
+package uk.gov.justice.laa.portal.landingpage.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import uk.gov.justice.laa.portal.landingpage.entity.LaaApp;
+
+import java.util.UUID;
+
+@Repository
+public interface LaaAppRepository extends JpaRepository<LaaApp, UUID> {
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaAppRoleRepository.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaAppRoleRepository.java
new file mode 100644
index 000000000..3c04aeb64
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaAppRoleRepository.java
@@ -0,0 +1,11 @@
+package uk.gov.justice.laa.portal.landingpage.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import uk.gov.justice.laa.portal.landingpage.entity.LaaAppRole;
+
+import java.util.UUID;
+
+@Repository
+public interface LaaAppRoleRepository extends JpaRepository<LaaAppRole, UUID> {
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaUserProfileRepository.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaUserProfileRepository.java
new file mode 100644
index 000000000..cb5cb1a77
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/LaaUserProfileRepository.java
@@ -0,0 +1,11 @@
+package uk.gov.justice.laa.portal.landingpage.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import uk.gov.justice.laa.portal.landingpage.entity.LaaUserProfile;
+
+import java.util.UUID;
+
+@Repository
+public interface LaaUserProfileRepository extends JpaRepository<LaaUserProfile, UUID> {
+}
diff --git a/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/OfficeRepository.java b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/OfficeRepository.java
new file mode 100644
index 000000000..85326f268
--- /dev/null
+++ b/src/main/java/uk/gov/justice/laa/portal/landingpage/repository/OfficeRepository.java
@@ -0,0 +1,11 @@
+package uk.gov.justice.laa.portal.landingpage.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import uk.gov.justice.laa.portal.landingpage.entity.Office;
+
+import java.util.UUID;
+
+@Repository
+public interface OfficeRepository extends JpaRepository<Office, UUID> {
+}


Reviews:
user: login: nsnape
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T20:28:24Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:10:47Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:11:29Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:12:23Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:12:46Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:13:31Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:14:51Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:17:54Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:18:12Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T09:19:00Z
user: login: nsnape
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T14:57:56Z
user: login: sureshkavali-moj
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-20T14:59:53Z
user: login: nsnape
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T08:42:57Z
user: login: niallmcmahon-moj
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:13:39Z

Review comments:
diff_hunk: @@ -0,0 +1,73 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Users
+ */
+@Entity
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaUserProfile.java
user: login: nsnape
body: This also needs joining to EntraUser (Many to one, so FK in this table)
created_at: 2025-05-15T19:23:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,83 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Email;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraUser.java
user: login: nsnape
body: should we be using java.time.LocalDate here instead? 

https://medium.com/@rpoddar05/why-java-time-localdate-and-localdatetime-are-better-than-java-util-date-f7a444c95d59
created_at: 2025-05-15T19:36:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,51 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.OneToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for Entra Application Registrations
+ */
+@Entity
+@Table(name = "entra_app_registration")
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class EntraAppRegistration implements Serializable {
+
+    @Id
+    @Column(name = "entra_app_registration_id", nullable = false)
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraAppRegistration.java
user: login: nsnape
body: not sure if this is necassary, but I think I read somewhere when reading about Hibernate that we should add @NotNull annotations from jakarta.validation.constraints for validation consistency.
created_at: 2025-05-15T19:39:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,83 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Email;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for Entra Users
+ */
+@Entity
+@Table(name = "entra_user", indexes = {@Index(columnList = "email", name = "UserEmailIdx")})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class EntraUser implements Serializable {
+
+    @Id
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraUser.java
user: login: nsnape
body: I know it's not mentioned in the DM, but maybe we should add a created datetimestamp for these records? And also a last modified datetime? I assume these are different from "start_date" and "end_date" which I'm guessing are actually more business domain related
created_at: 2025-05-15T19:46:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Firms
+ */
+@Entity
+@Table(name = "firm", indexes = {@Index(columnList = "firm_name", name = "FirmNameIdx")})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Firm implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "firm_id", nullable = false)
+    @JsonIgnore
+    private UUID firmId;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "firm_type", nullable = false)
+    private FirmType firmType;
+
+    @Column(name = "firm_name", nullable = false)
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java
user: login: nsnape
body: we can check, but presumably firm names should be unique?
created_at: 2025-05-15T19:49:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Firms
+ */
+@Entity
+@Table(name = "firm", indexes = {@Index(columnList = "firm_name", name = "FirmNameIdx")})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Firm implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "firm_id", nullable = false)
+    @JsonIgnore
+    private UUID firmId;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "firm_type", nullable = false)
+    private FirmType firmType;
+
+    @Column(name = "firm_name", nullable = false)
+    private String firmName;
+
+    @OneToMany(mappedBy = "firm", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java
user: login: nsnape
body: Is this cascade related to the database level ON DELETE CASCADE ? I think from a quick read that it's separate, do we need to consider our cascade behaviours? Maybe set it to RESTRICT to prevent acciental CASCADE deletions of whole DB structures.
created_at: 2025-05-15T19:56:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Firms
+ */
+@Entity
+@Table(name = "firm", indexes = {@Index(columnList = "firm_name", name = "FirmNameIdx")})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Firm implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "firm_id", nullable = false)
+    @JsonIgnore
+    private UUID firmId;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "firm_type", nullable = false)
+    private FirmType firmType;
+
+    @Column(name = "firm_name", nullable = false)
+    private String firmName;
+
+    @OneToMany(mappedBy = "firm", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<Office> offices;
+
+    @OneToMany(mappedBy = "firm", fetch = FetchType.LAZY)
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java
user: login: nsnape
body: is not having cascade behviour here going to cause inconsistency issues as the other relationship to firm does, and they are cyclically referential? Can't quite get my head round this one..
created_at: 2025-05-15T20:02:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,51 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.OneToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for Entra Application Registrations
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraAppRegistration.java
user: login: nsnape
body: these comments are a bit simple and can just be easily implied from the code itself - do we need them? If so we coudl add some context (I can suggest for these if you need me to)
created_at: 2025-05-15T20:15:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,73 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Users
+ */
+@Entity
+@Table(name = "laa_user_profile")
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class LaaUserProfile implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "user_profile_id", nullable = false)
+    private UUID userProfileId;
+
+    @Column(name = "is_multi_firm", nullable = false)
+    private boolean isMultiFirm;
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaUserProfile.java
user: login: nsnape
body: maybe we should remove the "is.." prefix from these fields, so just "MultiFirm" or "Admin"?
created_at: 2025-05-15T20:21:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,63 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Office
+ */
+@Entity
+@Table(name = "office")
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Office implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "office_id", nullable = false)
+    @JsonIgnore
+    private UUID officeId;
+
+    @Column(name = "office_name", nullable = false)
+    private String officeName;
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Office.java
user: login: nsnape
body: we might want to index this in case of lookups/filtering on office name (seems likely)
created_at: 2025-05-15T20:26:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,73 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Users
+ */
+@Entity
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaUserProfile.java
user: login: sureshkavali-moj
body: Added the missing link.
created_at: 2025-05-20T09:10:47Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,51 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.OneToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for Entra Application Registrations
+ */
+@Entity
+@Table(name = "entra_app_registration")
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class EntraAppRegistration implements Serializable {
+
+    @Id
+    @Column(name = "entra_app_registration_id", nullable = false)
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraAppRegistration.java
user: login: sureshkavali-moj
body: Added field validations
created_at: 2025-05-20T09:11:29Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,83 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Email;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for Entra Users
+ */
+@Entity
+@Table(name = "entra_user", indexes = {@Index(columnList = "email", name = "UserEmailIdx")})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class EntraUser implements Serializable {
+
+    @Id
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraUser.java
user: login: sureshkavali-moj
body: Added audit fields created by, created date, last updated by and last updated date

created_at: 2025-05-20T09:12:23Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Firms
+ */
+@Entity
+@Table(name = "firm", indexes = {@Index(columnList = "firm_name", name = "FirmNameIdx")})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Firm implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "firm_id", nullable = false)
+    @JsonIgnore
+    private UUID firmId;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "firm_type", nullable = false)
+    private FirmType firmType;
+
+    @Column(name = "firm_name", nullable = false)
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java
user: login: sureshkavali-moj
body: Added unique constraints for most name fields
created_at: 2025-05-20T09:12:46Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Firms
+ */
+@Entity
+@Table(name = "firm", indexes = {@Index(columnList = "firm_name", name = "FirmNameIdx")})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Firm implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "firm_id", nullable = false)
+    @JsonIgnore
+    private UUID firmId;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "firm_type", nullable = false)
+    private FirmType firmType;
+
+    @Column(name = "firm_name", nullable = false)
+    private String firmName;
+
+    @OneToMany(mappedBy = "firm", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java
user: login: sureshkavali-moj
body: Removed CASCADE allowing hibernate to apply default behaviour
created_at: 2025-05-20T09:13:31Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Firms
+ */
+@Entity
+@Table(name = "firm", indexes = {@Index(columnList = "firm_name", name = "FirmNameIdx")})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Firm implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "firm_id", nullable = false)
+    @JsonIgnore
+    private UUID firmId;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "firm_type", nullable = false)
+    private FirmType firmType;
+
+    @Column(name = "firm_name", nullable = false)
+    private String firmName;
+
+    @OneToMany(mappedBy = "firm", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+    @ToString.Exclude
+    @JsonIgnore
+    private Set<Office> offices;
+
+    @OneToMany(mappedBy = "firm", fetch = FetchType.LAZY)
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Firm.java
user: login: sureshkavali-moj
body: removed the cascades, it enforces code to explicitly do the db operations adhering to db constraints present.
created_at: 2025-05-20T09:14:51Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,51 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.OneToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for Entra Application Registrations
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/EntraAppRegistration.java
user: login: sureshkavali-moj
body: Removed the javadoc
created_at: 2025-05-20T09:17:54Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,73 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Users
+ */
+@Entity
+@Table(name = "laa_user_profile")
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class LaaUserProfile implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "user_profile_id", nullable = false)
+    private UUID userProfileId;
+
+    @Column(name = "is_multi_firm", nullable = false)
+    private boolean isMultiFirm;
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaUserProfile.java
user: login: sureshkavali-moj
body: updated field names
created_at: 2025-05-20T09:18:12Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,63 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Entity class for LAA Office
+ */
+@Entity
+@Table(name = "office")
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class Office implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.UUID)
+    @Column(name = "office_id", nullable = false)
+    @JsonIgnore
+    private UUID officeId;
+
+    @Column(name = "office_name", nullable = false)
+    private String officeName;
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/Office.java
user: login: sureshkavali-moj
body: Added indexes for more fields, this may be superfluous but happy discuss and adjust.
created_at: 2025-05-20T09:19:00Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "laa_app_role", indexes = {
+    @Index(name = "LaaAppRoleCreatedByIdx", columnList = "created_by"),
+    @Index(name = "LaaAppRoleCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "LaaAppRoleLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "LaaAppRoleLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "LaaAppRoleNameIdx", columnList = "name"),
+})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class LaaAppRole extends BaseEntity {
+
+    @Column(name = "name", nullable = false, length = 255, unique = true)
+    @Size(min = 1, max = 255)
+    private String name;
+
+    @ManyToOne
+    @JoinColumn(name = "laa_app_id", nullable = false, foreignKey = @ForeignKey(name = "FK_laa_app_role_laa_app_id"))
+    @ToString.Exclude
+    @JsonIgnore
+    private LaaApp laaApp;
+
+    @ManyToMany(fetch = FetchType.LAZY)
+    @JoinTable(
+            name = "user_profile_app_role",
+            joinColumns = @JoinColumn(name = "app_role_id"),
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaAppRole.java
user: login: nsnape
body: should this be `laa_app_role_id` just to be verbosely clear? or do you match the local column name, which is now just `id`?
created_at: 2025-05-20T14:57:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "laa_app_role", indexes = {
+    @Index(name = "LaaAppRoleCreatedByIdx", columnList = "created_by"),
+    @Index(name = "LaaAppRoleCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "LaaAppRoleLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "LaaAppRoleLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "LaaAppRoleNameIdx", columnList = "name"),
+})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class LaaAppRole extends BaseEntity {
+
+    @Column(name = "name", nullable = false, length = 255, unique = true)
+    @Size(min = 1, max = 255)
+    private String name;
+
+    @ManyToOne
+    @JoinColumn(name = "laa_app_id", nullable = false, foreignKey = @ForeignKey(name = "FK_laa_app_role_laa_app_id"))
+    @ToString.Exclude
+    @JsonIgnore
+    private LaaApp laaApp;
+
+    @ManyToMany(fetch = FetchType.LAZY)
+    @JoinTable(
+            name = "user_profile_app_role",
+            joinColumns = @JoinColumn(name = "app_role_id"),
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaAppRole.java
user: login: nsnape
body: same for all the other m2m table definitions, are these still referencing id columns that have now been renamed?
created_at: 2025-05-20T14:57:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,60 @@
+package uk.gov.justice.laa.portal.landingpage.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "laa_app_role", indexes = {
+    @Index(name = "LaaAppRoleCreatedByIdx", columnList = "created_by"),
+    @Index(name = "LaaAppRoleCreatedDateIdx", columnList = "created_date"),
+    @Index(name = "LaaAppRoleLastModifiedDateIdx", columnList = "last_modified_date"),
+    @Index(name = "LaaAppRoleLastModifiedByIdx", columnList = "last_modified_by"),
+    @Index(name = "LaaAppRoleNameIdx", columnList = "name"),
+})
+@Getter
+@Setter
+@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
+@ToString(doNotUseGetters = true)
+public class LaaAppRole extends BaseEntity {
+
+    @Column(name = "name", nullable = false, length = 255, unique = true)
+    @Size(min = 1, max = 255)
+    private String name;
+
+    @ManyToOne
+    @JoinColumn(name = "laa_app_id", nullable = false, foreignKey = @ForeignKey(name = "FK_laa_app_role_laa_app_id"))
+    @ToString.Exclude
+    @JsonIgnore
+    private LaaApp laaApp;
+
+    @ManyToMany(fetch = FetchType.LAZY)
+    @JoinTable(
+            name = "user_profile_app_role",
+            joinColumns = @JoinColumn(name = "app_role_id"),
path: src/main/java/uk/gov/justice/laa/portal/landingpage/entity/LaaAppRole.java
user: login: sureshkavali-moj
body: These are the columns created in the link table `user_profile_app_role`, so we need them to be verbose and unique and easily identifiable.
created_at: 2025-05-20T14:59:53Z
author_association: COLLABORATOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-15T14:41:11Z
body: ### Code Coverage
|Overall Project|65.97%|:x:|
|:-|:-|:-:|
|Files changed|100%|:green_apple:|
<br>

|File|Coverage||
|:-|:-|:-:|
|[FirmType.java](https://github.com/ministryofjustice/laa-landing-page/blob/414bcc61065fa293e9bf55997847ad9450a21e43/src%2Fmain%2Fjava%2Fuk%2Fgov%2Fjustice%2Flaa%2Fportal%2Flandingpage%2Fentity%2FFirmType.java)|100%|:green_apple:|
|[UserType.java](https://github.com/ministryofjustice/laa-landing-page/blob/414bcc61065fa293e9bf55997847ad9450a21e43/src%2Fmain%2Fjava%2Fuk%2Fgov%2Fjustice%2Flaa%2Fportal%2Flandingpage%2Fentity%2FUserType.java)|100%|:green_apple:|
author_association: CONTRIBUTOR
user: login: sureshkavali-moj
created_at: 2025-05-20T08:42:08Z
body: The SQL generated following the updates

```
create table entra_app_registration (created_date timestamp(6) not null, last_modified_date timestamp(6), id uuid not null, created_by varchar(255) not null, last_modified_by varchar(255), name varchar(255) not null unique, primary key (id))
create table entra_user (is_active boolean not null, created_date timestamp(6) not null, end_date timestamp(6), last_modified_date timestamp(6), start_date timestamp(6), id uuid not null, created_by varchar(255) not null, email varchar(255) not null unique, first_name varchar(255) not null, last_modified_by varchar(255), last_name varchar(255) not null, user_type varchar(255) not null check (user_type in ('INTERNAL','EXTERNAL')), primary key (id))
create table entra_user_app_registration (entra_app_registration_id uuid not null, entra_user_id uuid not null, primary key (entra_app_registration_id, entra_user_id))
create table firm (created_date timestamp(6) not null, last_modified_date timestamp(6), id uuid not null, created_by varchar(255) not null, last_modified_by varchar(255), name varchar(255) not null unique, type varchar(255) not null check (type in ('ADVOCATE','CHAMBERS','INDIVIDUAL','LEGAL_SERVICES_PROVIDER','QM_PROVIDER')), primary key (id))
create table laa_app (created_date timestamp(6) not null, last_modified_date timestamp(6), entra_app_registration_id uuid not null unique, id uuid not null, created_by varchar(255) not null, last_modified_by varchar(255), name varchar(255) not null unique, primary key (id))
create table laa_app_role (created_date timestamp(6) not null, last_modified_date timestamp(6), id uuid not null, laa_app_id uuid not null, created_by varchar(255) not null, last_modified_by varchar(255), name varchar(255) not null unique, primary key (id))
create table laa_user_profile (is_admin boolean not null, is_multi_firm boolean not null, created_date timestamp(6) not null, last_modified_date timestamp(6), entra_user_id uuid, firm_id uuid, id uuid not null, created_by varchar(255) not null, last_modified_by varchar(255), primary key (id))
create table office (created_date timestamp(6) not null, last_modified_date timestamp(6), firm_id uuid not null, id uuid not null, address varchar(500) not null, created_by varchar(255) not null, last_modified_by varchar(255), name varchar(255) not null unique, phone varchar(255) not null, primary key (id))
create table user_profile_app_role (app_role_id uuid not null, user_profile_id uuid not null, primary key (app_role_id, user_profile_id))
create table user_profile_office (office_id uuid not null, user_profile_id uuid not null, primary key (office_id, user_profile_id))
create table users (uid integer generated by default as identity, email varchar(255) not null unique, fullName varchar(255) not null, id varchar(255), lastLoggedIn varchar(255), password varchar(255) not null, primary key (uid))
create index EntraAppRegistrationCreatedByIdx on entra_app_registration (created_by)
create index EntraAppRegistrationCreatedDateIdx on entra_app_registration (created_date)
create index EntraAppRegistrationLastModifiedDateIdx on entra_app_registration (last_modified_date)
create index EntraAppRegistrationLastModifiedByIdx on entra_app_registration (last_modified_by)
create index EntraAppRegistrationNameIdx on entra_app_registration (name)
create index EntraUserCreatedByIdx on entra_user (created_by)
create index EntraUserCreatedDateIdx on entra_user (created_date)
create index EntraUserLastModifiedDateIdx on entra_user (last_modified_date)
create index EntraUserLastModifiedByIdx on entra_user (last_modified_by)
create index EntraUserNameIdx on entra_user (first_name, last_name)
create index EntraUserEmailIdx on entra_user (email)
create index FirmCreatedByIdx on firm (created_by)
create index FirmCreatedDateIdx on firm (created_date)
create index FirmLastModifiedDateIdx on firm (last_modified_date)
create index FirmLastModifiedByIdx on firm (last_modified_by)
create index FirmNameIdx on firm (name)
create index LaaAppCreatedByIdx on laa_app (created_by)
create index LaaAppCreatedDateIdx on laa_app (created_date)
create index LaaAppLastModifiedDateIdx on laa_app (last_modified_date)
create index LaaAppLastModifiedByIdx on laa_app (last_modified_by)
create index LaaAppNameIdx on laa_app (name)
create index LaaAppRoleCreatedByIdx on laa_app_role (created_by)
create index LaaAppRoleCreatedDateIdx on laa_app_role (created_date)
create index LaaAppRoleLastModifiedDateIdx on laa_app_role (last_modified_date)
create index LaaAppRoleLastModifiedByIdx on laa_app_role (last_modified_by)
create index LaaAppRoleNameIdx on laa_app_role (name)
create index LaaUserProfileCreatedByIdx on laa_user_profile (created_by)
create index LaaUserProfileCreatedDateIdx on laa_user_profile (created_date)
create index LaaUserProfileLastModifiedDateIdx on laa_user_profile (last_modified_date)
create index LaaUserProfileLastModifiedByIdx on laa_user_profile (last_modified_by)
create index OfficeCreatedByIdx on office (created_by)
create index OfficeCreatedDateIdx on office (created_date)
create index OfficeLastModifiedDateIdx on office (last_modified_date)
create index OfficeLastModifiedByIdx on office (last_modified_by)
create index OfficeNameIdx on office (name)
alter table if exists entra_user_app_registration add constraint FK_entra_user_app_registration_entra_app_registration_id foreign key (entra_app_registration_id) references entra_app_registration
alter table if exists entra_user_app_registration add constraint FK_entra_user_app_registration_entra_user_id foreign key (entra_user_id) references entra_user
alter table if exists laa_app add constraint FK_laa_app_entra_app_registration_id foreign key (entra_app_registration_id) references entra_app_registration
alter table if exists laa_app_role add constraint FK_laa_app_role_laa_app_id foreign key (laa_app_id) references laa_app
alter table if exists laa_user_profile add constraint FK_laa_user_profile_entra_user_id foreign key (entra_user_id) references entra_user
alter table if exists laa_user_profile add constraint FK_laa_user_profile_firm_id foreign key (firm_id) references firm
alter table if exists office add constraint FK_office_firm_id foreign key (firm_id) references firm
alter table if exists user_profile_app_role add constraint FK_laa_app_role_user_profile_id foreign key (user_profile_id) references laa_user_profile
alter table if exists user_profile_app_role add constraint FK_laa_app_role_app_role_id foreign key (app_role_id) references laa_app_role
alter table if exists user_profile_office add constraint FK_laa_user_profile_office_office_id foreign key (office_id) references office
alter table if exists user_profile_office add constraint FK_laa_user_profile_office_user_profile_id foreign key (user_profile_id) references laa_user_profile
```


And the updated data model diagram


![Screenshot 2025-05-20 at 09 41 01](https://github.com/user-attachments/assets/6b20cc6d-9fee-433f-93f4-4f271aee0a96)

author_association: COLLABORATOR
user: login: sureshkavali-moj
created_at: 2025-05-20T15:57:20Z
body: Updated ERD


![Screenshot 2025-05-21 at 09 07 48](https://github.com/user-attachments/assets/0fb1c013-36ea-47cd-a23c-9e4cfc27201b)


author_association: COLLABORATOR