diff --git a/components/estimates.vue b/components/estimates.vue
index d1de280..a2ed294 100644
--- a/components/estimates.vue
+++ b/components/estimates.vue
@@ -55,6 +55,7 @@ ${{(estimate.price / 100).toLocaleString()}}
 <label>Cash to close: ${{format(l.result.cashToClose)}}</label>
 </div>
 <button @click="() => download(estimate)">Generate PDF</button>
+<button @click="() => deleting = true">Delete</button>
 <button @click="() => estimate = null">Cancel</button>
 </div>
 
@@ -64,6 +65,11 @@ ${{(estimate.price / 100).toLocaleString()}}
 :fileName="`estimate-${estimate.id}.pdf`" :url="dlink">
 </DDialog>
 
+<Dialog v-if="deleting" @close="() => deleting = false">
+<h3>Are you sure you want to delete this estimate?</h3>
+<button @click="() => del(estimate)">Confirm</button>
+</Dialog>
+
 </div>
 </template>
 
@@ -71,6 +77,7 @@ ${{(estimate.price / 100).toLocaleString()}}
 import { ref, computed, onMounted } from 'vue'
 import FeeDialog from "./fee-dialog.vue"
 import DDialog from "./download-dialog.vue"
+import Dialog from "./dialog.vue"
 import { format } from "../helpers.js"
 
 const props = defineProps(['user', 'fees', 'token'])
@@ -79,6 +86,7 @@ let edit = ref(null)
 let estimates = ref([])
 let estimate = ref()
 let dlink = ref("")
+let deleting = ref()
 
 function newFee(fee, isDebit) {
     if (!isDebit) {
@@ -142,6 +150,23 @@ function getEstimates() {
 	})
 }
 
+function del(e) {
+	fetch(`/api/estimate`,
+		{method: 'DELETE',
+		    body: JSON.stringify(e),
+    		headers: {
+        	"Accept": "application/json",
+        	"Authorization": `Bearer ${props.token}`,
+    		},
+	}).then(response => {
+		if (response.ok) { 
+		  estimates.value = estimates.value.filter(e => e.id != estimate.value.id)
+		  estimate.value = null
+		  deleting.value = false
+		}
+	})
+}
+
 function download(estimate) {
   fetch(`/api/pdf`,
 		{method: 'POST',
diff --git a/migrations/0_29092022_setup_tables.sql b/migrations/0_29092022_setup_tables.sql
index 945a4a4..7009ba9 100644
--- a/migrations/0_29092022_setup_tables.sql
+++ b/migrations/0_29092022_setup_tables.sql
@@ -78,18 +78,9 @@ CREATE TABLE loan_type (
 	PRIMARY KEY (`id`)
 );
 
-CREATE TABLE borrower (
-	id 				INT AUTO_INCREMENT,
-	credit_score 	SMALLINT NOT NULL,
-	monthly_income 	INT NOT NULL,
-	num 			TINYINT NOT NULL, /* Number of people borrowing. */
-	PRIMARY KEY (`id`)
-);
-
 CREATE TABLE estimate (
 	id 			INT AUTO_INCREMENT,
 	user_id 		INT NOT NULL,
-	borrower_id 		INT NOT NULL,
 	transaction 		ENUM('Purchase', 'Refinance'),
 	price 			INT NOT NULL,
 	property 		ENUM('Single Detached',
@@ -99,10 +90,31 @@ CREATE TABLE estimate (
 	occupancy 		ENUM('Primary', 'Secondary', 'Investment'),
 	zip 			VARCHAR(10),
 	pud 			BOOLEAN, /* Property under development */
+	PRIMARY KEY (`id`)
+);
+
+CREATE TABLE borrower (
+	id	INT AUTO_INCREMENT,
+	credit_score 	SMALLINT NOT NULL,
+	monthly_income 	INT NOT NULL,
+	num 			TINYINT NOT NULL, /* Number of people borrowing. */
+	estimate_id 		INT UNIQUE NOT NULL,
 	PRIMARY KEY (`id`),
-	FOREIGN KEY (borrower_id) REFERENCES borrower(id)
+	FOREIGN KEY (estimate_id) REFERENCES estimate(id)
+	ON DELETE CASCADE
 );
 
+CREATE TABLE estimate_template (
+	id 			INT AUTO_INCREMENT,
+	estimate_id 		INT UNIQUE NOT NULL,
+	user_id 		INT NOT NULL, /* User who created the template */
+	branch_id 		INT NOT NULL DEFAULT 0,
+/* Specific branch allowed to use it. 0 is only user. */
+	PRIMARY KEY (`id`),
+	FOREIGN KEY (estimate_id) REFERENCES estimate(id)
+);
+
+
 CREATE TABLE loan (
 	id  	INT AUTO_INCREMENT,
 	estimate_id 		INT NOT NULL,
@@ -117,8 +129,9 @@ CREATE TABLE loan (
 	tax 			INT DEFAULT 0, /* Real estate taxes */
 	name 			VARCHAR(30) DEFAULT '',
 	PRIMARY KEY (`id`),
-	FOREIGN KEY (estimate_id) REFERENCES estimate(id),
+	FOREIGN KEY (estimate_id) REFERENCES estimate(id) ON DELETE CASCADE,
 	FOREIGN KEY (type_id) REFERENCES loan_type(id)
+	ON DELETE CASCADE
 	ON UPDATE RESTRICT
 );
 
@@ -137,6 +150,7 @@ CREATE TABLE mi (
 	initial_amount 	INT DEFAULT 0,
 	PRIMARY KEY (`id`),
 	FOREIGN KEY (loan_id) REFERENCES loan(id)
+	ON DELETE CASCADE
 );
 
 /* template = true fees are saved for users or branches. If template or default
@@ -153,6 +167,7 @@ CREATE TABLE fee (
 	category 		VARCHAR(60),
 	PRIMARY KEY (`id`),
 	FOREIGN KEY (loan_id) REFERENCES loan(id)
+	ON DELETE CASCADE
 );
 
 /* Templates to be reused by users or branches. Either user_id or branch_id must
@@ -185,5 +200,5 @@ CREATE TABLE estimate_result (
 	total_credits	INT NOT NULL,
 	cash_to_close	INT NOT NULL,
 	PRIMARY KEY (`id`),
-	FOREIGN KEY (loan_id) REFERENCES loan(id)
+	FOREIGN KEY (loan_id) REFERENCES loan(id) ON DELETE CASCADE
 );
diff --git a/migrations/reset.sql b/migrations/reset.sql
index 2d39b17..b268e1c 100644
--- a/migrations/reset.sql
+++ b/migrations/reset.sql
@@ -1,10 +1,11 @@
+DROP TABLE IF EXISTS estimate_template;
 DROP TABLE IF EXISTS estimate_result;
 DROP TABLE IF EXISTS mi;
 DROP TABLE IF EXISTS fee;
 DROP TABLE IF EXISTS fee_template;
 DROP TABLE IF EXISTS loan;
-DROP TABLE IF EXISTS estimate;
 DROP TABLE IF EXISTS borrower;
+DROP TABLE IF EXISTS estimate;
 DROP TABLE IF EXISTS loan_type;
 DROP TABLE IF EXISTS license;
 DROP TABLE IF EXISTS user;
diff --git a/skouter.go b/skouter.go
index 8f0ec03..b2bdf61 100644
--- a/skouter.go
+++ b/skouter.go
@@ -189,6 +189,13 @@ type Estimate struct {
 	Loans 	[]Loan 	`json:"loans"`
 }
 
+type ETemplate struct {
+	Id	int 	`json:"id"`
+	Estimate	Estimate 	`json:"estimate"`
+	UserId	int 	`json:"userId"`
+	BranchId	int	`json:"branchId"`
+}
+
 type Report struct {
 		Title string
 		Name string
@@ -574,6 +581,19 @@ func deleteFeeTemp(w http.ResponseWriter, db *sql.DB, r *http.Request) {
 	if err != nil { w.WriteHeader(500); return }
 }
 
+func deleteEstimate(w http.ResponseWriter, db *sql.DB, r *http.Request) {
+	var estimate Estimate
+	var err error
+	
+	err = json.NewDecoder(r.Body).Decode(&estimate)
+	if err != nil { w.WriteHeader(422); return }
+	
+	claims, err := getClaims(r)
+	err = estimate.del(db, claims.Id)
+	if err != nil { http.Error(w, err.Error(), 500); return }
+}
+
+
 func getMi(db *sql.DB, loan int) (MI, error) {
 	var mi MI
 
@@ -608,25 +628,23 @@ func getMi(db *sql.DB, loan int) (MI, error) {
 	return mi, nil
 }
 
-func getBorrower(db *sql.DB, id int) (Borrower, error) {
-	var borrower Borrower
+func (estimate *Estimate) getBorrower(db *sql.DB) error {
+	query := `SELECT id, credit_score, monthly_income, num FROM borrower
+		WHERE estimate_id = ? LIMIT 1`
 
-	row := db.QueryRow(
-		"SELECT * FROM borrower " +
-		"WHERE id = ? LIMIT 1",
-	id)
+	row := db.QueryRow(query, estimate.Id)
 
 	if err := row.Scan(
-		&borrower.Id,
-		&borrower.Credit,
-		&borrower.Income,
-		&borrower.Num,
+		&estimate.Borrower.Id,
+		&estimate.Borrower.Credit,
+		&estimate.Borrower.Income,
+		&estimate.Borrower.Num,
 		)
 	err != nil {
-		return borrower, fmt.Errorf("Borrower scanning error: %v", err)
+		return fmt.Errorf("Borrower scanning error: %v", err)
         }
 
-	return borrower, nil
+	return nil
 }
 
 // Query Lender APIs and parse responses into MI structs
@@ -1740,6 +1758,14 @@ func getLoans(db *sql.DB, e int, id int) ( []Loan, error ) {
 	return loans, nil
 }
 
+func getEstimate(db *sql.DB, id int) ( Estimate, error ) {
+	estimates, err := getEstimates(db, id, 0)
+	
+	if err != nil { return Estimate{}, err }
+	
+	return estimates[0], nil
+}
+
 func getEstimates(db *sql.DB, id int, user int) ( []Estimate, error ) {
 	var estimates []Estimate
 	var query string
@@ -1749,7 +1775,6 @@ func getEstimates(db *sql.DB, id int, user int) ( []Estimate, error ) {
 	query = `SELECT
 	id,
 	user_id,
-	borrower_id,
 	transaction,
 	price,
 	property,
@@ -1773,7 +1798,6 @@ func getEstimates(db *sql.DB, id int, user int) ( []Estimate, error ) {
 		if err := rows.Scan(
 			&estimate.Id,
 			&estimate.User,
-			&estimate.Borrower.Id,
 			&estimate.Transaction,
 			&estimate.Price,
 			&estimate.Property,
@@ -1785,11 +1809,10 @@ func getEstimates(db *sql.DB, id int, user int) ( []Estimate, error ) {
 			return estimates, err
         }
         
-		borrower, err := getBorrower(db, estimate.Borrower.Id)
+		err := estimate.getBorrower(db)
 		if err != nil {
 			return estimates, err
         }
-        estimate.Borrower = borrower
 		estimates = append(estimates, estimate)
 	}
 
@@ -1804,33 +1827,80 @@ func getEstimates(db *sql.DB, id int, user int) ( []Estimate, error ) {
 	return estimates, nil
 }
 
+func getETemplate(db *sql.DB, id int, user int) ( []ETemplate, error ) {
+	var eTemplates []ETemplate
+	var query string
+	var rows *sql.Rows
+	var err error
+
+	query = `SELECT
+	id,
+	estimate_id,
+	user_id,
+	branch_id,
+	FROM estimate_template WHERE id = CASE @e := ? WHEN 0 THEN id ELSE @e END AND
+	user_id = CASE @e := ? WHEN 0 THEN user_id ELSE @e END
+	`
+	rows, err = db.Query(query, id, user)
+
+	if err != nil {
+		return eTemplates, err
+	}
+
+	defer rows.Close()
+
+	for rows.Next() {
+		var e ETemplate
+
+		if err := rows.Scan(
+			&e.Id,
+			&e.Estimate.Id,
+			&e.UserId,
+			&e.BranchId,
+			)
+		err != nil {
+			return eTemplates, err
+        	}
+        
+		e.Estimate, err = getEstimate(db, e.Estimate.Id)
+		if err != nil {
+			return eTemplates, err
+        	}
+
+		eTemplates = append(eTemplates, e)
+	}
+	
+	return eTemplates, nil
+}
+
 // Accepts a borrower struct and returns the id of the inserted borrower and
 // any related error.
-func insertBorrower(db *sql.DB, borrower Borrower) (int, error) {
+func (estimate *Estimate) insertBorrower(db *sql.DB) error {
 	var query string
 	var row *sql.Row
 	var err error
-	var id int // Inserted loan's id
 
 	query = `INSERT INTO borrower
 	(
+		estimate_id,
 		credit_score,
 		monthly_income,
 		num
 	)
-	VALUES (?, ?, ?)
+	VALUES (?, ?, ?, ?)
 	RETURNING id
 	`
 	row = db.QueryRow(query,
-		borrower.Credit,
-		borrower.Income,
-		borrower.Num,
+		estimate.Id,
+		estimate.Borrower.Credit,
+		estimate.Borrower.Income,
+		estimate.Borrower.Num,
 	)
 
-	err = row.Scan(&id)
-	if err != nil { return 0, err }
+	err = row.Scan(&estimate.Borrower.Id)
+	if err != nil { return err }
 
-	return id, nil
+	return nil
 }
 
 func insertMi(db *sql.DB, mi MI) (int, error) {
@@ -1968,13 +2038,9 @@ func (estimate *Estimate) insertEstimate(db *sql.DB) (error){
 	var err error
 	// var id int // Inserted estimate's id
 	
-	estimate.Borrower.Id, err = insertBorrower(db, estimate.Borrower)
-	if err != nil { return err }
-
 	query = `INSERT INTO estimate
 	(
 		user_id,
-		borrower_id,
 		transaction,
 		price,
 		property,
@@ -1982,12 +2048,11 @@ func (estimate *Estimate) insertEstimate(db *sql.DB) (error){
 		zip,
 		pud
 	)
-	VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+	VALUES (?, ?, ?, ?, ?, ?, ?)
 	RETURNING id
 	`
 	row = db.QueryRow(query,
 		estimate.User,
-		estimate.Borrower.Id,
 		estimate.Transaction,
 		estimate.Price,
 		estimate.Property,
@@ -1998,6 +2063,9 @@ func (estimate *Estimate) insertEstimate(db *sql.DB) (error){
 
 	err = row.Scan(&estimate.Id)
 	if err != nil { return err }
+	
+	err = estimate.insertBorrower(db)
+	if err != nil { return err }
 
 	for i := range estimate.Loans {
 		estimate.Loans[i].EstimateId = estimate.Id
@@ -2008,6 +2076,44 @@ func (estimate *Estimate) insertEstimate(db *sql.DB) (error){
 	return nil
 }
 
+func (estimate *Estimate) del(db *sql.DB, user int) (error) {
+	var query string
+	var err error
+
+	query = `DELETE FROM estimate WHERE id = ? AND user_id = ?`
+	
+	_, err = db.Exec(query, estimate.Id, user)
+	if err != nil { return err }
+
+	return nil
+}
+
+func (eTemplate *ETemplate) insert(db *sql.DB) (error) {
+	var query string
+	var row *sql.Row
+	var err error
+	
+	query = `INSERT INTO estimate_template
+	(
+		user_id,
+		branch_id,
+		estimate_id,
+	)
+	VALUES (?, ?, ?)
+	RETURNING id
+	`
+	row = db.QueryRow(query,
+		eTemplate.UserId,
+		eTemplate.BranchId,
+		eTemplate.Estimate.Id,
+	)
+
+	err = row.Scan(&eTemplate.Id)
+	if err != nil { return err }
+
+	return nil
+}
+
 func createEstimate(w http.ResponseWriter, db *sql.DB, r *http.Request) {
 	var estimate Estimate
 	err := json.NewDecoder(r.Body).Decode(&estimate)
@@ -2383,6 +2489,10 @@ func api(w http.ResponseWriter, r *http.Request) {
 	r.Method == http.MethodPost &&
 	guard(r, 1):
 		createEstimate(w, db, r)
+	case match(p, "/api/estimate", &args) &&
+	r.Method == http.MethodDelete &&
+	guard(r, 1):
+		deleteEstimate(w, db, r)
 	case match(p, "/api/estimate/validate", &args) &&
 	r.Method == http.MethodPost &&
 	guard(r, 1):