diff --git a/3layerarch/.DS_Store b/3layerarch/.DS_Store
new file mode 100644
index 0000000..74054d4
Binary files /dev/null and b/3layerarch/.DS_Store differ
diff --git a/3layerarch/.idea/.gitignore b/3layerarch/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/3layerarch/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/3layerarch/.idea/3layerarch.iml b/3layerarch/.idea/3layerarch.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/3layerarch/.idea/3layerarch.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/3layerarch/.idea/modules.xml b/3layerarch/.idea/modules.xml
new file mode 100644
index 0000000..88952d1
--- /dev/null
+++ b/3layerarch/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/3layerarch/go.mod b/3layerarch/go.mod
new file mode 100644
index 0000000..b2aecc5
--- /dev/null
+++ b/3layerarch/go.mod
@@ -0,0 +1,7 @@
+module 3layerarch
+
+go 1.24
+
+require github.com/go-sql-driver/mysql v1.9.3
+
+require filippo.io/edwards25519 v1.1.0 // indirect
diff --git a/3layerarch/go.sum b/3layerarch/go.sum
new file mode 100644
index 0000000..4bcdcfa
--- /dev/null
+++ b/3layerarch/go.sum
@@ -0,0 +1,4 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
+github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
diff --git a/3layerarch/handler/.DS_Store b/3layerarch/handler/.DS_Store
new file mode 100644
index 0000000..2595feb
Binary files /dev/null and b/3layerarch/handler/.DS_Store differ
diff --git a/3layerarch/handler/task/handler.go b/3layerarch/handler/task/handler.go
new file mode 100644
index 0000000..9e8f435
--- /dev/null
+++ b/3layerarch/handler/task/handler.go
@@ -0,0 +1,115 @@
+package taskhandler
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "strconv"
+
+ "3layerarch/models"
+)
+
+type TaskService interface {
+ CreateTask(t models.Task) error
+ GetTask(id int) (models.Task, error)
+ ViewTasks() ([]models.Task, error)
+ UpdateTask(id int) error
+ DeleteTask(id int) error
+}
+
+type Handler struct {
+ Service TaskService
+}
+
+func New(service TaskService) *Handler {
+ return &Handler{Service: service}
+}
+
+func (h *Handler) CreateTask(w http.ResponseWriter, r *http.Request) {
+ body, err := io.ReadAll(r.Body)
+ if err != nil || len(body) == 0 {
+ http.Error(w, "Empty or unreadable body", http.StatusBadRequest)
+ return
+ }
+ var t models.Task
+ if err := json.Unmarshal(body, &t); err != nil {
+ http.Error(w, "Invalid JSON input", http.StatusBadRequest)
+ return
+ }
+ if err := h.Service.CreateTask(t); err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ w.WriteHeader(http.StatusCreated)
+}
+
+func (h *Handler) GetTask(w http.ResponseWriter, r *http.Request) {
+ idStr := r.PathValue("id")
+ if idStr == "" {
+ http.Error(w, "Missing ID", http.StatusBadRequest)
+ return
+ }
+ id, err := strconv.Atoi(idStr)
+ if err != nil {
+ http.Error(w, "Invalid ID format", http.StatusBadRequest)
+ return
+ }
+ t, err := h.Service.GetTask(id)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ b, _ := json.Marshal(t)
+ if _, err := w.Write(b); err != nil {
+ fmt.Printf("failed to write response: %v\n", err)
+ }
+}
+
+func (h *Handler) ViewTasks(w http.ResponseWriter, _ *http.Request) {
+ tasks, err := h.Service.ViewTasks()
+ if err != nil {
+ http.Error(w, "Failed to fetch tasks", http.StatusInternalServerError)
+ return
+ }
+ b, _ := json.Marshal(tasks)
+ if _, err := w.Write(b); err != nil {
+ fmt.Printf("failed to write response: %v\n", err)
+ }
+}
+
+func (h *Handler) UpdateTask(w http.ResponseWriter, r *http.Request) {
+ idStr := r.PathValue("id")
+ if idStr == "" {
+ http.Error(w, "Missing ID", http.StatusBadRequest)
+ return
+ }
+ id, err := strconv.Atoi(idStr)
+ if err != nil {
+ http.Error(w, "Invalid ID format", http.StatusBadRequest)
+ return
+ }
+ if err := h.Service.UpdateTask(id); err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ w.WriteHeader(http.StatusOK)
+}
+
+func (h *Handler) DeleteTask(w http.ResponseWriter, r *http.Request) {
+ idStr := r.PathValue("id")
+ if idStr == "" {
+ http.Error(w, "Missing ID", http.StatusBadRequest)
+ return
+ }
+ id, err := strconv.Atoi(idStr)
+ if err != nil {
+ http.Error(w, "Invalid ID format", http.StatusBadRequest)
+ return
+ }
+ if err := h.Service.DeleteTask(id); err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ w.WriteHeader(http.StatusOK)
+}
diff --git a/3layerarch/handler/user/handler.go b/3layerarch/handler/user/handler.go
new file mode 100644
index 0000000..14624ca
--- /dev/null
+++ b/3layerarch/handler/user/handler.go
@@ -0,0 +1,64 @@
+package userhandler
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "strconv"
+
+ "3layerarch/models"
+)
+
+type UserService interface {
+ CreateUser(u models.User) error
+ GetUser(id int) (models.User, error)
+}
+
+type Handler struct {
+ Service UserService
+}
+
+func New(service UserService) *Handler {
+ return &Handler{Service: service}
+}
+
+func (h *Handler) CreateUser(w http.ResponseWriter, r *http.Request) {
+ body, err := io.ReadAll(r.Body)
+ if err != nil || len(body) == 0 {
+ http.Error(w, "Empty or unreadable body", http.StatusBadRequest)
+ return
+ }
+ var u models.User
+ if err := json.Unmarshal(body, &u); err != nil {
+ http.Error(w, "Invalid JSON input", http.StatusBadRequest)
+ return
+ }
+ if err := h.Service.CreateUser(u); err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ w.WriteHeader(http.StatusCreated)
+}
+
+func (h *Handler) GetUser(w http.ResponseWriter, r *http.Request) {
+ idStr := r.PathValue("id")
+ if idStr == "" {
+ http.Error(w, "Missing ID", http.StatusBadRequest)
+ return
+ }
+ id, err := strconv.Atoi(idStr)
+ if err != nil {
+ http.Error(w, "Invalid ID format", http.StatusBadRequest)
+ return
+ }
+ u, err := h.Service.GetUser(id)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ b, _ := json.Marshal(u)
+ if _, err := w.Write(b); err != nil {
+ fmt.Printf("failed to write response: %v\n", err)
+ }
+}
diff --git a/3layerarch/main.go b/3layerarch/main.go
new file mode 100644
index 0000000..1f434a0
--- /dev/null
+++ b/3layerarch/main.go
@@ -0,0 +1,83 @@
+package main
+
+import (
+ "database/sql"
+ "log"
+ "net/http"
+ "time"
+
+ taskhandler "3layerarch/handler/task"
+ userhandler "3layerarch/handler/user"
+
+ taskservice "3layerarch/service/task"
+ userservice "3layerarch/service/user"
+
+ taskstore "3layerarch/store/task"
+ userstore "3layerarch/store/user"
+
+ _ "github.com/go-sql-driver/mysql"
+)
+
+func main() {
+ db, err := sql.Open("mysql", "root:root123@tcp(localhost:3306)/test_db")
+ if err != nil {
+ log.Fatal("DB connection error:", err)
+ }
+ defer func() {
+ if err := db.Close(); err != nil {
+ log.Println("Error closing DB:", err)
+ }
+ }()
+
+ // Ensure TASKS table exists
+ _, err = db.Exec(`CREATE TABLE IF NOT EXISTS TASKS (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ task TEXT,
+ completed BOOL DEFAULT FALSE,
+ user_id int
+ );`)
+ if err != nil {
+ log.Fatal("Failed to create TASKS table:", err)
+ }
+
+ // Ensure USERS table exists
+ _, err = db.Exec(`CREATE TABLE IF NOT EXISTS USERS (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ name VARCHAR(100)
+ );`)
+ if err != nil {
+ log.Fatal("Failed to create USERS table:", err)
+ }
+
+ // User dependency setup
+ userStore := userstore.New(db)
+ userService := userservice.New(userStore)
+ userHandler := userhandler.New(userService)
+
+ // Task dependency setup
+ taskStore := taskstore.New(db)
+ taskService := taskservice.New(taskStore, userService)
+ taskHandler := taskhandler.New(taskService)
+
+ // Task routes
+ http.HandleFunc("POST /task", taskHandler.CreateTask)
+ http.HandleFunc("GET /task", taskHandler.ViewTasks)
+ http.HandleFunc("GET /task/{id}", taskHandler.GetTask)
+ http.HandleFunc("PUT /task/{id}", taskHandler.UpdateTask)
+ http.HandleFunc("DELETE /task/{id}", taskHandler.DeleteTask)
+
+ // User routes
+ http.HandleFunc("POST /user", userHandler.CreateUser)
+ http.HandleFunc("GET /user/{id}", userHandler.GetUser)
+
+ // Server configuration
+ srv := &http.Server{
+ Addr: ":8080",
+ ReadTimeout: 5 * time.Second,
+ WriteTimeout: 10 * time.Second,
+ IdleTimeout: 120 * time.Second,
+ }
+
+ //log.Println("Server running on http://localhost:8080")
+ log.Fatal(srv.ListenAndServe())
+}
diff --git a/3layerarch/models/task.go b/3layerarch/models/task.go
new file mode 100644
index 0000000..e29c725
--- /dev/null
+++ b/3layerarch/models/task.go
@@ -0,0 +1,8 @@
+package models
+
+type Task struct {
+ ID int `json:"id"`
+ Task string `json:"task"`
+ Completed bool `json:"completed"`
+ UserID int `json:"user_id"`
+}
diff --git a/3layerarch/models/user.go b/3layerarch/models/user.go
new file mode 100644
index 0000000..7f6eacd
--- /dev/null
+++ b/3layerarch/models/user.go
@@ -0,0 +1,6 @@
+package models
+
+type User struct {
+ ID int `json:"id"`
+ Name string `json:"name"`
+}
diff --git a/3layerarch/service/.DS_Store b/3layerarch/service/.DS_Store
new file mode 100644
index 0000000..f69ce9e
Binary files /dev/null and b/3layerarch/service/.DS_Store differ
diff --git a/3layerarch/service/task/service.go b/3layerarch/service/task/service.go
new file mode 100644
index 0000000..31234fa
--- /dev/null
+++ b/3layerarch/service/task/service.go
@@ -0,0 +1,90 @@
+package taskservice
+
+import (
+ //"3layerarch/handler/userhandler"
+ "3layerarch/models"
+ "database/sql"
+ "errors"
+ "fmt"
+)
+
+type TaskStore interface {
+ CreateTask(t models.Task) error
+ GetTask(id int) (models.Task, error)
+ ViewTasks() ([]models.Task, error)
+ UpdateTask(id int) error
+ DeleteTask(id int) error
+}
+
+type UserService interface {
+ GetUser(id int) (models.User, error)
+}
+
+type Service struct {
+ TaskStore TaskStore
+ UserService UserService
+}
+
+func New(ts TaskStore, us UserService) *Service {
+ return &Service{TaskStore: ts, UserService: us}
+}
+
+func (s *Service) CreateTask(t models.Task) error {
+ fmt.Println("CreateTask received:", t)
+
+ if t.Task == "" {
+ return errors.New("task cannot be empty")
+ }
+ // Validate user existence before creating task
+ _, err := s.UserService.GetUser(t.UserID)
+ if err != nil {
+ return errors.New("user ID not found")
+ }
+ return s.TaskStore.CreateTask(t)
+}
+
+func (s *Service) GetTask(id int) (models.Task, error) {
+ if id <= 0 {
+ return models.Task{}, errors.New("invalid task ID")
+ }
+ task, err := s.TaskStore.GetTask(id)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ return models.Task{}, errors.New("task not found")
+ }
+ return models.Task{}, err
+ }
+ return task, nil
+}
+
+func (s *Service) ViewTasks() ([]models.Task, error) {
+ return s.TaskStore.ViewTasks()
+}
+
+func (s *Service) UpdateTask(id int) error {
+ if id <= 0 {
+ return errors.New("invalid task ID")
+ }
+ _, err := s.TaskStore.GetTask(id)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ return errors.New("task not found")
+ }
+ return err
+ }
+ return s.TaskStore.UpdateTask(id)
+}
+
+func (s *Service) DeleteTask(id int) error {
+ if id <= 0 {
+ return errors.New("invalid task ID")
+ }
+ _, err := s.TaskStore.GetTask(id)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ return errors.New("task not found")
+ }
+ return err
+ }
+ return s.TaskStore.DeleteTask(id)
+}
diff --git a/3layerarch/service/user/service.go b/3layerarch/service/user/service.go
new file mode 100644
index 0000000..fab65aa
--- /dev/null
+++ b/3layerarch/service/user/service.go
@@ -0,0 +1,41 @@
+package userservice
+
+import (
+ "3layerarch/models"
+ "database/sql"
+ "errors"
+)
+
+type UserStore interface {
+ CreateUser(u models.User) error
+ GetUser(id int) (models.User, error)
+}
+
+type Service struct {
+ Store UserStore
+}
+
+func New(store UserStore) *Service {
+ return &Service{Store: store}
+}
+
+func (s *Service) CreateUser(u models.User) error {
+ if u.Name == "" {
+ return errors.New("user name cannot be empty")
+ }
+ return s.Store.CreateUser(u)
+}
+
+func (s *Service) GetUser(id int) (models.User, error) {
+ if id <= 0 {
+ return models.User{}, errors.New("invalid user ID")
+ }
+ u, err := s.Store.GetUser(id)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ return models.User{}, errors.New("user not found")
+ }
+ return models.User{}, err
+ }
+ return u, nil
+}
diff --git a/3layerarch/store/.DS_Store b/3layerarch/store/.DS_Store
new file mode 100644
index 0000000..090e2e4
Binary files /dev/null and b/3layerarch/store/.DS_Store differ
diff --git a/3layerarch/store/task/store.go b/3layerarch/store/task/store.go
new file mode 100644
index 0000000..ca2bc15
--- /dev/null
+++ b/3layerarch/store/task/store.go
@@ -0,0 +1,59 @@
+package taskstore
+
+import (
+ "3layerarch/models"
+ "database/sql"
+ "log"
+)
+
+type Store struct {
+ db *sql.DB
+}
+
+func New(db *sql.DB) *Store {
+ return &Store{db: db}
+}
+
+func (s *Store) CreateTask(t models.Task) error {
+ _, err := s.db.Exec("INSERT INTO TASKS (task, completed, user_id) VALUES (?, ?, ?)", t.Task, t.Completed, t.UserID)
+ return err
+}
+
+func (s *Store) GetTask(id int) (models.Task, error) {
+ var t models.Task
+ err := s.db.QueryRow("SELECT id, task, completed, user_id FROM TASKS WHERE id = ?", id).
+ Scan(&t.ID, &t.Task, &t.Completed, &t.UserID)
+ return t, err
+}
+
+func (s *Store) ViewTasks() ([]models.Task, error) {
+ rows, err := s.db.Query("SELECT id, task, completed, user_id FROM TASKS")
+ if err != nil {
+ return nil, err
+ }
+ defer func() {
+ if err := rows.Close(); err != nil {
+ log.Println("Error closing rows:", err)
+ }
+ }()
+
+ var tasks []models.Task
+ for rows.Next() {
+ var t models.Task
+ if err := rows.Scan(&t.ID, &t.Task, &t.Completed, &t.UserID); err != nil {
+ return nil, err
+ }
+ tasks = append(tasks, t)
+ }
+ return tasks, nil
+}
+
+func (s *Store) UpdateTask(id int) error {
+ _, err := s.db.Exec("UPDATE TASKS SET completed = true WHERE id = ?", id)
+ return err
+}
+
+func (s *Store) DeleteTask(id int) error {
+ _, err := s.db.Exec("DELETE FROM TASKS WHERE id = ?", id)
+ return err
+}
diff --git a/3layerarch/store/user/store.go b/3layerarch/store/user/store.go
new file mode 100644
index 0000000..bb00c47
--- /dev/null
+++ b/3layerarch/store/user/store.go
@@ -0,0 +1,25 @@
+package userstore
+
+import (
+ "3layerarch/models"
+ "database/sql"
+)
+
+type Store struct {
+ db *sql.DB
+}
+
+func New(db *sql.DB) *Store {
+ return &Store{db: db}
+}
+
+func (s *Store) CreateUser(u models.User) error {
+ _, err := s.db.Exec("INSERT INTO USERS (name) VALUES (?)", u.Name)
+ return err
+}
+
+func (s *Store) GetUser(id int) (models.User, error) {
+ var u models.User
+ err := s.db.QueryRow("SELECT id, name FROM USERS WHERE id = ?", id).Scan(&u.ID, &u.Name)
+ return u, err
+}