go-crm improvements

This commit is contained in:
2026-05-01 15:43:13 -03:00
parent ee6673265f
commit 31247a63f6
17 changed files with 416 additions and 63 deletions

View File

@@ -5,13 +5,14 @@ import (
)
type Client struct {
ClientID int64 `json:"client_id"`
Name string `json:"name"`
Phone string `json:"phone,omitempty"`
Email string `json:"email,omitempty"`
Address string `json:"address,omitempty"`
Notes string `json:"notes,omitempty"`
CreatedAt int64 `json:"created_at"`
ClientID int64 `json:"client_id"`
AccountID int64 `json:"account_id"`
Name string `json:"name"`
Phone string `json:"phone,omitempty"`
Email string `json:"email,omitempty"`
Address string `json:"address,omitempty"`
Notes string `json:"notes,omitempty"`
CreatedAt int64 `json:"created_at"`
}
type Customer struct {
@@ -59,8 +60,8 @@ type Payment struct {
func (c *Client) Create(db *sql.DB) error {
result, err := db.Exec(
"INSERT INTO clients (name, phone, email, address, notes, created_at) VALUES (?, ?, ?, ?, ?, ?)",
c.Name, c.Phone, c.Email, c.Address, c.Notes, c.CreatedAt,
"INSERT INTO clients (account_id, name, phone, email, address, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
c.AccountID, c.Name, c.Phone, c.Email, c.Address, c.Notes, c.CreatedAt,
)
if err != nil {
return err
@@ -75,29 +76,35 @@ func (c *Client) Create(db *sql.DB) error {
func (c *Client) Read(db *sql.DB, id int64) error {
return db.QueryRow(
"SELECT client_id, name, phone, email, address, notes, created_at FROM clients WHERE client_id = ?",
"SELECT client_id, account_id, name, COALESCE(phone,''), COALESCE(email,''), COALESCE(address,''), COALESCE(notes,''), created_at FROM clients WHERE client_id = ?",
id,
).Scan(&c.ClientID, &c.Name, &c.Phone, &c.Email, &c.Address, &c.Notes, &c.CreatedAt)
).Scan(&c.ClientID, &c.AccountID, &c.Name, &c.Phone, &c.Email, &c.Address, &c.Notes, &c.CreatedAt)
}
func (c *Client) Update(db *sql.DB) error {
_, err := db.Exec(
"UPDATE clients SET name = ?, phone = ?, email = ?, address = ?, notes = ? WHERE client_id = ?",
c.Name, c.Phone, c.Email, c.Address, c.Notes, c.ClientID,
"UPDATE clients SET name = ?, phone = ?, email = ?, address = ?, notes = ? WHERE client_id = ? AND account_id = ?",
c.Name, c.Phone, c.Email, c.Address, c.Notes, c.ClientID, c.AccountID,
)
return err
}
func (c *Client) Delete(db *sql.DB, id int64) error {
_, err := db.Exec("DELETE FROM clients WHERE client_id = ?", id)
func (c *Client) Delete(db *sql.DB) error {
_, err := db.Exec("DELETE FROM clients WHERE client_id = ? AND account_id = ?", c.ClientID, c.AccountID)
return err
}
func ListClients(db *sql.DB, limit, offset int) ([]Client, error) {
rows, err := db.Query(
"SELECT client_id, name, phone, email, address, notes, created_at FROM clients ORDER BY created_at DESC LIMIT ? OFFSET ?",
limit, offset,
)
func ListClients(db *sql.DB, accountID int64, limit, offset int) ([]Client, error) {
query := "SELECT client_id, account_id, name, COALESCE(phone,''), COALESCE(email,''), COALESCE(address,''), COALESCE(notes,''), created_at FROM clients"
args := []interface{}{}
if accountID > 0 {
query += " WHERE account_id = ?"
args = append(args, accountID)
}
query += " ORDER BY created_at DESC LIMIT ? OFFSET ?"
args = append(args, limit, offset)
rows, err := db.Query(query, args...)
if err != nil {
return nil, err
}
@@ -106,7 +113,7 @@ func ListClients(db *sql.DB, limit, offset int) ([]Client, error) {
var clients []Client
for rows.Next() {
var c Client
if err := rows.Scan(&c.ClientID, &c.Name, &c.Phone, &c.Email, &c.Address, &c.Notes, &c.CreatedAt); err != nil {
if err := rows.Scan(&c.ClientID, &c.AccountID, &c.Name, &c.Phone, &c.Email, &c.Address, &c.Notes, &c.CreatedAt); err != nil {
return nil, err
}
clients = append(clients, c)
@@ -114,12 +121,12 @@ func ListClients(db *sql.DB, limit, offset int) ([]Client, error) {
return clients, rows.Err()
}
func GetClientByID(db *sql.DB, id int64) (*Client, error) {
func GetClientByID(db *sql.DB, accountID, id int64) (*Client, error) {
var c Client
err := db.QueryRow(
"SELECT client_id, name, phone, email, address, notes, created_at FROM clients WHERE client_id = ?",
id,
).Scan(&c.ClientID, &c.Name, &c.Phone, &c.Email, &c.Address, &c.Notes, &c.CreatedAt)
"SELECT client_id, account_id, name, COALESCE(phone,''), COALESCE(email,''), COALESCE(address,''), COALESCE(notes,''), created_at FROM clients WHERE client_id = ? AND account_id = ?",
id, accountID,
).Scan(&c.ClientID, &c.AccountID, &c.Name, &c.Phone, &c.Email, &c.Address, &c.Notes, &c.CreatedAt)
if err != nil {
return nil, err
}
@@ -142,13 +149,24 @@ func (cu *Customer) Create(db *sql.DB) error {
return nil
}
func ListCustomers(db *sql.DB, clientID int64, limit, offset int) ([]Customer, error) {
func ListCustomers(db *sql.DB, accountID, clientID int64, limit, offset int) ([]Customer, error) {
args := []interface{}{}
query := "SELECT customer_id, client_id, name, phone, birth_date, instagram, created_at FROM customers"
var args []interface{}
cond := ""
if clientID > 0 {
query += " WHERE client_id = ?"
cond = "client_id = ?"
args = append(args, clientID)
}
if accountID > 0 {
if cond != "" {
cond += " AND "
}
cond += "client_id IN (SELECT client_id FROM clients WHERE account_id = ?)"
args = append(args, accountID)
}
if cond != "" {
query += " WHERE " + cond
}
query += " ORDER BY created_at DESC LIMIT ? OFFSET ?"
args = append(args, limit, offset)
@@ -185,13 +203,24 @@ func (s *Service) Create(db *sql.DB) error {
return nil
}
func ListServices(db *sql.DB, clientID int64, limit, offset int) ([]Service, error) {
func ListServices(db *sql.DB, accountID, clientID int64, limit, offset int) ([]Service, error) {
args := []interface{}{}
query := "SELECT service_id, client_id, name, price, description, duration, created_at FROM services"
var args []interface{}
cond := ""
if clientID > 0 {
query += " WHERE client_id = ?"
cond = "client_id = ?"
args = append(args, clientID)
}
if accountID > 0 {
if cond != "" {
cond += " AND "
}
cond += "client_id IN (SELECT client_id FROM clients WHERE account_id = ?)"
args = append(args, accountID)
}
if cond != "" {
query += " WHERE " + cond
}
query += " ORDER BY created_at DESC LIMIT ? OFFSET ?"
args = append(args, limit, offset)
@@ -430,7 +459,8 @@ type AnswerWithDetails struct {
QuestionText string `json:"question_text"`
}
func ListAnswersWithDetails(db *sql.DB, questionID int64, limit, offset int) ([]AnswerWithDetails, error) {
func ListAnswersWithDetails(db *sql.DB, accountID, questionID int64, limit, offset int) ([]AnswerWithDetails, error) {
args := []interface{}{accountID}
query := `
SELECT
a.answer_id, a.client_id, a.question_id, a.answer, a.timestamp, a.status, a.created_at,
@@ -441,8 +471,7 @@ func ListAnswersWithDetails(db *sql.DB, questionID int64, limit, offset int) ([]
JOIN questions q ON a.question_id = q.question_id
JOIN customers cu ON q.customer_id = cu.customer_id
JOIN clients c ON q.client_id = c.client_id
WHERE 1=1`
var args []interface{}
WHERE c.account_id = ?`
if questionID > 0 {
query += " AND a.question_id = ?"
args = append(args, questionID)

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
_ "github.com/glebarez/sqlite"
)
@@ -27,12 +28,14 @@ CREATE TABLE IF NOT EXISTS sessions (
CREATE TABLE IF NOT EXISTS clients (
client_id INTEGER PRIMARY KEY AUTOINCREMENT,
account_id INTEGER NOT NULL,
name TEXT NOT NULL,
phone TEXT,
email TEXT,
address TEXT,
notes TEXT,
created_at INTEGER NOT NULL
created_at INTEGER NOT NULL,
FOREIGN KEY (account_id) REFERENCES accounts(account_id)
);
CREATE TABLE IF NOT EXISTS customers (
@@ -138,5 +141,20 @@ func Init(path string) (*sql.DB, error) {
return nil, fmt.Errorf("failed to create schema: %w", err)
}
if err := migrate(database); err != nil {
return nil, fmt.Errorf("failed to migrate: %w", err)
}
return database, nil
}
func migrate(db *sql.DB) error {
_, err := db.Exec("ALTER TABLE clients ADD COLUMN account_id INTEGER")
if err != nil {
if strings.Contains(err.Error(), "duplicate column name") {
return nil
}
return err
}
return nil
}

View File

@@ -68,7 +68,42 @@ func Signup(w http.ResponseWriter, r *http.Request) {
return
}
http.Redirect(w, r, "/auth/login", http.StatusFound)
var accountID int64
err = DB.QueryRow("SELECT account_id FROM accounts WHERE email = ?", email).Scan(&accountID)
if err != nil {
http.Error(w, "Failed to create account", http.StatusInternalServerError)
return
}
client := struct {
AccountID int64
Name string
CreatedAt int64
}{
AccountID: accountID,
Name: name,
CreatedAt: time.Now().Unix(),
}
_, err = DB.Exec(
"INSERT INTO clients (account_id, name, created_at) VALUES (?, ?, ?)",
client.AccountID, client.Name, client.CreatedAt,
)
if err != nil {
http.Error(w, "Failed to create client", http.StatusInternalServerError)
return
}
sessionID := generateSessionID()
expires := time.Now().Add(24 * time.Hour).Unix()
_, err = DB.Exec("INSERT INTO sessions (session_id, account_id, expires) VALUES (?, ?, ?)", sessionID, accountID, expires)
if err != nil {
http.Error(w, "Failed to create session", http.StatusInternalServerError)
return
}
http.SetCookie(w, &http.Cookie{Name: "session", Value: sessionID, Path: "/"})
http.Redirect(w, r, "/", http.StatusFound)
}
func LoginPage(w http.ResponseWriter, r *http.Request) {
@@ -121,7 +156,7 @@ func Login(w http.ResponseWriter, r *http.Request) {
}
http.SetCookie(w, &http.Cookie{Name: "session", Value: sessionID, Path: "/"})
http.Redirect(w, r, "/clients", http.StatusFound)
http.Redirect(w, r, "/", http.StatusFound)
}
func Logout(w http.ResponseWriter, r *http.Request) {
@@ -158,7 +193,67 @@ func getSession(r *http.Request) (int64, error) {
return accountID, err
}
func GetAccountID(r *http.Request) (int64, error) {
return getSession(r)
}
func requireAuth(w http.ResponseWriter, r *http.Request) (int64, bool) {
accountID, err := getSession(r)
if err != nil {
http.Redirect(w, r, "/auth/login", http.StatusFound)
return 0, false
}
return accountID, true
}
func SetupAuthHandlers(db *sql.DB) {
DB = db
chi.RegisterMethod("GET")
}
func AccountPage(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
var name, email string
err := DB.QueryRow("SELECT name, email FROM accounts WHERE account_id = ?", accountID).Scan(&name, &email)
if err != nil {
http.Error(w, "Account not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "text/html")
w.Write([]byte(`<!DOCTYPE html><html><head><title>Account</title></head><body><h1>Account Settings</h1><form method="POST" action="/auth/account">
<p>Name: <input type="text" name="name" value="` + name + `"></p>
<p>Email: <input type="email" value="` + email + `" disabled></p>
<p>New Password: <input type="password" name="password" placeholder="Leave blank to keep current"></p>
<button type="submit">Update</button>
</form>
<a href="/">Back to Dashboard</a></body></html>`))
}
func UpdateAccount(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
r.ParseForm()
name := r.FormValue("name")
password := r.FormValue("password")
if name != "" {
DB.Exec("UPDATE accounts SET name = ? WHERE account_id = ?", name, accountID)
}
if password != "" {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err == nil {
DB.Exec("UPDATE accounts SET password = ? WHERE account_id = ?", string(hashedPassword), accountID)
}
}
http.Redirect(w, r, "/auth/account", http.StatusFound)
}

View File

@@ -11,13 +11,18 @@ import (
)
func ListClients(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
if limit == 0 {
limit = 20
}
clients, err := db.ListClients(DB, limit, offset)
clients, err := db.ListClients(DB, accountID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -81,8 +86,14 @@ func ListClients(w http.ResponseWriter, r *http.Request) {
}
func CreateClient(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
r.ParseForm()
client := db.Client{
AccountID: accountID,
Name: r.FormValue("name"),
Phone: r.FormValue("phone"),
Email: r.FormValue("email"),
@@ -101,8 +112,13 @@ func CreateClient(w http.ResponseWriter, r *http.Request) {
}
func ViewClient(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
client, err := db.GetClientByID(DB, id)
client, err := db.GetClientByID(DB, accountID, id)
if err != nil {
http.Error(w, "Client not found", http.StatusNotFound)
return
@@ -124,10 +140,16 @@ func ViewClient(w http.ResponseWriter, r *http.Request) {
}
func UpdateClient(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
r.ParseForm()
client := db.Client{
ClientID: id,
ClientID: id,
AccountID: accountID,
Name: r.FormValue("name"),
Phone: r.FormValue("phone"),
Email: r.FormValue("email"),
@@ -144,8 +166,14 @@ func UpdateClient(w http.ResponseWriter, r *http.Request) {
}
func DeleteClient(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
if err := (&db.Client{}).Delete(DB, id); err != nil {
client := &db.Client{ClientID: id, AccountID: accountID}
if err := client.Delete(DB); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

View File

@@ -11,6 +11,11 @@ import (
)
func ListCustomers(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
clientID, _ := strconv.ParseInt(r.URL.Query().Get("client_id"), 10, 64)
@@ -18,13 +23,13 @@ func ListCustomers(w http.ResponseWriter, r *http.Request) {
limit = 20
}
customers, err := db.ListCustomers(DB, clientID, limit, offset)
customers, err := db.ListCustomers(DB, accountID, clientID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
clients, err := db.ListClients(DB, limit, offset)
clients, err := db.ListClients(DB, accountID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -44,8 +49,21 @@ func ListCustomers(w http.ResponseWriter, r *http.Request) {
}
func CreateCustomer(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
var checkID int64
err := DB.QueryRow("SELECT client_id FROM clients WHERE client_id = ? AND account_id = ?", clientID, accountID).Scan(&checkID)
if err != nil {
http.Error(w, "Invalid client", http.StatusBadRequest)
return
}
customer := db.Customer{
ClientID: clientID,
Name: r.FormValue("name"),
@@ -64,6 +82,11 @@ func CreateCustomer(w http.ResponseWriter, r *http.Request) {
}
func ViewCustomer(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
var c db.Customer
err := DB.QueryRow("SELECT customer_id, client_id, name, phone, birth_date, instagram, created_at FROM customers WHERE customer_id = ?", id).Scan(&c.CustomerID, &c.ClientID, &c.Name, &c.Phone, &c.BirthDate, &c.Instagram, &c.CreatedAt)
@@ -77,6 +100,11 @@ func ViewCustomer(w http.ResponseWriter, r *http.Request) {
}
func UpdateCustomer(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
@@ -89,6 +117,11 @@ func UpdateCustomer(w http.ResponseWriter, r *http.Request) {
}
func DeleteCustomer(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
DB.Exec("DELETE FROM customers WHERE customer_id = ?", id)
}

View File

@@ -11,6 +11,11 @@ import (
)
func ListPayments(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
clientID, _ := strconv.ParseInt(r.URL.Query().Get("client_id"), 10, 64)
@@ -24,13 +29,13 @@ func ListPayments(w http.ResponseWriter, r *http.Request) {
return
}
clients, err := db.ListClients(DB, limit, offset)
clients, err := db.ListClients(DB, accountID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
customers, err := db.ListCustomers(DB, clientID, limit, offset)
customers, err := db.ListCustomers(DB, accountID, clientID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -69,6 +74,11 @@ func ListPayments(w http.ResponseWriter, r *http.Request) {
}
func CreatePayment(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
customerID, _ := strconv.ParseInt(r.FormValue("customer_id"), 10, 64)
@@ -96,6 +106,11 @@ func CreatePayment(w http.ResponseWriter, r *http.Request) {
}
func ViewPayment(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(r.URL.Query().Get("id"), 10, 64)
var p db.Payment
var hasPaid int
@@ -111,6 +126,11 @@ func ViewPayment(w http.ResponseWriter, r *http.Request) {
}
func UpdatePayment(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
@@ -126,6 +146,11 @@ func UpdatePayment(w http.ResponseWriter, r *http.Request) {
}
func DeletePayment(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(r.URL.Query().Get("id"), 10, 64)
DB.Exec("DELETE FROM payments WHERE payment_id = ?", id)
}

View File

@@ -11,6 +11,11 @@ import (
)
func ListQuestions(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
clientID, _ := strconv.ParseInt(r.URL.Query().Get("client_id"), 10, 64)
@@ -24,13 +29,13 @@ func ListQuestions(w http.ResponseWriter, r *http.Request) {
return
}
clients, err := db.ListClients(DB, limit, offset)
clients, err := db.ListClients(DB, accountID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
customers, err := db.ListCustomers(DB, clientID, limit, offset)
customers, err := db.ListCustomers(DB, accountID, clientID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -65,6 +70,11 @@ func ListQuestions(w http.ResponseWriter, r *http.Request) {
}
func CreateQuestion(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
customerID, _ := strconv.ParseInt(r.FormValue("customer_id"), 10, 64)
@@ -86,6 +96,11 @@ func CreateQuestion(w http.ResponseWriter, r *http.Request) {
}
func ViewQuestion(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
var q db.Question
err := DB.QueryRow("SELECT question_id, client_id, customer_id, question, timestamp, status, created_at FROM questions WHERE question_id = ?", id).Scan(&q.QuestionID, &q.ClientID, &q.CustomerID, &q.Question, &q.Timestamp, &q.Status, &q.CreatedAt)
@@ -99,6 +114,11 @@ func ViewQuestion(w http.ResponseWriter, r *http.Request) {
}
func UpdateQuestion(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
@@ -112,11 +132,21 @@ func UpdateQuestion(w http.ResponseWriter, r *http.Request) {
}
func DeleteQuestion(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
DB.Exec("DELETE FROM questions WHERE question_id = ?", id)
}
func ListAnswers(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
questionID, _ := strconv.ParseInt(r.URL.Query().Get("question_id"), 10, 64)
@@ -124,7 +154,7 @@ func ListAnswers(w http.ResponseWriter, r *http.Request) {
limit = 20
}
answers, err := db.ListAnswersWithDetails(DB, questionID, limit, offset)
answers, err := db.ListAnswersWithDetails(DB, accountID, questionID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -224,6 +254,11 @@ func ListAnswers(w http.ResponseWriter, r *http.Request) {
}
func CreateAnswer(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
r.ParseForm()
questionID, _ := strconv.ParseInt(r.FormValue("question_id"), 10, 64)
@@ -234,6 +269,13 @@ func CreateAnswer(w http.ResponseWriter, r *http.Request) {
return
}
var checkID int64
err = DB.QueryRow("SELECT client_id FROM clients WHERE client_id = ? AND account_id = ?", clientID, accountID).Scan(&checkID)
if err != nil {
http.Error(w, "Invalid question", http.StatusBadRequest)
return
}
answer := db.Answer{
ClientID: clientID,
QuestionID: questionID,
@@ -252,6 +294,11 @@ func CreateAnswer(w http.ResponseWriter, r *http.Request) {
}
func ViewAnswer(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
var a db.Answer
err := DB.QueryRow("SELECT answer_id, client_id, question_id, answer, timestamp, status, created_at FROM answers WHERE answer_id = ?", id).Scan(&a.AnswerID, &a.ClientID, &a.QuestionID, &a.Answer, &a.Timestamp, &a.Status, &a.CreatedAt)
@@ -265,6 +312,11 @@ func ViewAnswer(w http.ResponseWriter, r *http.Request) {
}
func UpdateAnswer(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
r.ParseForm()
questionID, _ := strconv.ParseInt(r.FormValue("question_id"), 10, 64)
@@ -277,6 +329,11 @@ func UpdateAnswer(w http.ResponseWriter, r *http.Request) {
}
func DeleteAnswer(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
DB.Exec("DELETE FROM answers WHERE answer_id = ?", id)
}

View File

@@ -11,6 +11,11 @@ import (
)
func ListSchedules(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
clientID, _ := strconv.ParseInt(r.URL.Query().Get("client_id"), 10, 64)
@@ -25,19 +30,19 @@ func ListSchedules(w http.ResponseWriter, r *http.Request) {
return
}
clients, err := db.ListClients(DB, limit, offset)
clients, err := db.ListClients(DB, accountID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
customers, err := db.ListCustomers(DB, clientID, limit, offset)
customers, err := db.ListCustomers(DB, accountID, clientID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
services, err := db.ListServices(DB, clientID, limit, offset)
services, err := db.ListServices(DB, accountID, clientID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -81,6 +86,11 @@ func ListSchedules(w http.ResponseWriter, r *http.Request) {
}
func CreateSchedule(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
customerID, _ := strconv.ParseInt(r.FormValue("customer_id"), 10, 64)
@@ -104,6 +114,11 @@ func CreateSchedule(w http.ResponseWriter, r *http.Request) {
}
func ViewSchedule(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
var sch db.Schedule
err := DB.QueryRow("SELECT schedule_id, client_id, customer_id, service_id, plan_date, time, status, created_at FROM scheduling WHERE schedule_id = ?", id).Scan(&sch.ScheduleID, &sch.ClientID, &sch.CustomerID, &sch.ServiceID, &sch.PlanDate, &sch.Time, &sch.Status, &sch.CreatedAt)
@@ -117,6 +132,11 @@ func ViewSchedule(w http.ResponseWriter, r *http.Request) {
}
func UpdateSchedule(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
@@ -131,6 +151,11 @@ func UpdateSchedule(w http.ResponseWriter, r *http.Request) {
}
func DeleteSchedule(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
DB.Exec("DELETE FROM scheduling WHERE schedule_id = ?", id)
}

View File

@@ -11,6 +11,11 @@ import (
)
func ListServices(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
clientID, _ := strconv.ParseInt(r.URL.Query().Get("client_id"), 10, 64)
@@ -18,13 +23,13 @@ func ListServices(w http.ResponseWriter, r *http.Request) {
limit = 20
}
services, err := db.ListServices(DB, clientID, limit, offset)
services, err := db.ListServices(DB, accountID, clientID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
clients, err := db.ListClients(DB, limit, offset)
clients, err := db.ListClients(DB, accountID, limit, offset)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -44,8 +49,21 @@ func ListServices(w http.ResponseWriter, r *http.Request) {
}
func CreateService(w http.ResponseWriter, r *http.Request) {
accountID, ok := requireAuth(w, r)
if !ok {
return
}
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
var checkID int64
err := DB.QueryRow("SELECT client_id FROM clients WHERE client_id = ? AND account_id = ?", clientID, accountID).Scan(&checkID)
if err != nil {
http.Error(w, "Invalid client", http.StatusBadRequest)
return
}
price, _ := strconv.ParseFloat(r.FormValue("price"), 64)
service := db.Service{
ClientID: clientID,
@@ -65,6 +83,11 @@ func CreateService(w http.ResponseWriter, r *http.Request) {
}
func ViewService(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
var s db.Service
err := DB.QueryRow("SELECT service_id, client_id, name, price, description, duration, created_at FROM services WHERE service_id = ?", id).Scan(&s.ServiceID, &s.ClientID, &s.Name, &s.Price, &s.Description, &s.Duration, &s.CreatedAt)
@@ -78,6 +101,11 @@ func ViewService(w http.ResponseWriter, r *http.Request) {
}
func UpdateService(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
r.ParseForm()
clientID, _ := strconv.ParseInt(r.FormValue("client_id"), 10, 64)
@@ -91,6 +119,11 @@ func UpdateService(w http.ResponseWriter, r *http.Request) {
}
func DeleteService(w http.ResponseWriter, r *http.Request) {
_, ok := requireAuth(w, r)
if !ok {
return
}
id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
DB.Exec("DELETE FROM services WHERE service_id = ?", id)
}