go-crm improvements
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user