Add Docker Compose and backend Dockerfile
Include .gitignore, go.mod/go.sum, initial Go source, init.sql, and Docker‑Compose configuration for the MSSQL and backend services.
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
db/data/log
|
||||
34
backend/Dockerfile
Normal file
34
backend/Dockerfile
Normal file
@@ -0,0 +1,34 @@
|
||||
# Use the official Go image as the base image
|
||||
FROM golang:1.22-alpine AS builder
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /app
|
||||
|
||||
# Cache Go modules
|
||||
COPY go.mod ./
|
||||
RUN apk add --no-cache git
|
||||
RUN go mod download
|
||||
|
||||
# Copy the source code
|
||||
COPY . .
|
||||
|
||||
# Build the Go binary
|
||||
RUN go build -o main .
|
||||
|
||||
# ---- Runtime image ----
|
||||
FROM alpine:3.19
|
||||
|
||||
# Install ca-certificates (if needed)
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
# Set workdir
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the binary from the builder stage
|
||||
COPY --from=builder /app/main .
|
||||
|
||||
# Expose the application port (default for the Go server)
|
||||
EXPOSE 8080
|
||||
|
||||
# Command to run the binary
|
||||
CMD ["./main"]
|
||||
11
backend/go.mod
Normal file
11
backend/go.mod
Normal file
@@ -0,0 +1,11 @@
|
||||
module backend
|
||||
|
||||
go 1.22
|
||||
|
||||
require github.com/denisenkom/go-mssqldb v0.12.3
|
||||
|
||||
require (
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
||||
)
|
||||
38
backend/go.sum
Normal file
38
backend/go.sum
Normal file
@@ -0,0 +1,38 @@
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
|
||||
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
BIN
backend/main
Normal file
BIN
backend/main
Normal file
Binary file not shown.
173
backend/main.go
Normal file
173
backend/main.go
Normal file
@@ -0,0 +1,173 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Load DB connection settings from environment (set in docker‑compose)
|
||||
server := os.Getenv("DB_SERVER")
|
||||
user := os.Getenv("DB_USER")
|
||||
password := os.Getenv("DB_PASSWORD")
|
||||
dbName := os.Getenv("DB_NAME")
|
||||
|
||||
if server == "" || user == "" || password == "" || dbName == "" {
|
||||
log.Fatalf("One or more DB environment variables are missing")
|
||||
}
|
||||
|
||||
// Build the connection string for go‑mssqldb
|
||||
connStr := fmt.Sprintf("sqlserver://%s:%s@%s?database=%s", user, password, server, dbName)
|
||||
|
||||
// Open a connection pool
|
||||
db, err := sql.Open("sqlserver", connStr)
|
||||
if err != nil {
|
||||
log.Fatalf("sql.Open failed: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Verify the connection works
|
||||
if err = db.Ping(); err != nil {
|
||||
log.Fatalf("cannot ping database: %v", err)
|
||||
}
|
||||
fmt.Println("✅ Connected to MSSQL")
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 1️⃣ Insert a new customer via the stored procedure sp_InsertCustomer
|
||||
// -----------------------------------------------------------------
|
||||
var newCustID int
|
||||
insertCustSQL := `
|
||||
DECLARE @NewID int;
|
||||
EXEC dbo.sp_InsertCustomer
|
||||
@CustomerName = @name,
|
||||
@AddressLine1 = @addr1,
|
||||
@AddressLine2 = @addr2,
|
||||
@City = @city,
|
||||
@State = @state,
|
||||
@ZipCode = @zip,
|
||||
@Country = @country,
|
||||
@NewCustomerID = @NewID OUTPUT;
|
||||
SELECT @NewID;
|
||||
`
|
||||
row := db.QueryRow(insertCustSQL,
|
||||
sql.Named("name", "Acme Corp"),
|
||||
sql.Named("addr1", "123 Main St"),
|
||||
sql.Named("addr2", nil),
|
||||
sql.Named("city", "New York"),
|
||||
sql.Named("state", "NY"),
|
||||
sql.Named("zip", "10001"),
|
||||
sql.Named("country", "USA"),
|
||||
)
|
||||
if err = row.Scan(&newCustID); err != nil {
|
||||
log.Fatalf("Insert customer failed: %v", err)
|
||||
}
|
||||
fmt.Printf("🆕 Inserted Customer ID: %d\n", newCustID)
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 2️⃣ Insert a contact for the new customer via sp_InsertContact
|
||||
// -----------------------------------------------------------------
|
||||
var newContactID int
|
||||
insertContactSQL := `
|
||||
DECLARE @NewContactID int;
|
||||
EXEC dbo.sp_InsertContact
|
||||
@CustomerID = @custID,
|
||||
@ContactTypeID = @typeID,
|
||||
@ContactValue = @value,
|
||||
@IsPrimary = @primary,
|
||||
@NewContactID = @NewContactID OUTPUT;
|
||||
SELECT @NewContactID;
|
||||
`
|
||||
// Assume ContactTypeID 1 = Phone (created by init.sql)
|
||||
row = db.QueryRow(insertContactSQL,
|
||||
sql.Named("custID", newCustID),
|
||||
sql.Named("typeID", 1),
|
||||
sql.Named("value", "555‑1234"),
|
||||
sql.Named("primary", 1),
|
||||
)
|
||||
if err = row.Scan(&newContactID); err != nil {
|
||||
log.Fatalf("Insert contact failed: %v", err)
|
||||
}
|
||||
fmt.Printf("📞 Inserted Contact ID: %d\n", newContactID)
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 3️⃣ Retrieve the customer via sp_GetCustomer
|
||||
// -----------------------------------------------------------------
|
||||
var custName, addr1, addr2, city, state, zip, country string
|
||||
getCustSQL := `EXEC dbo.sp_GetCustomer @CustomerID = @id`
|
||||
err = db.QueryRow(getCustSQL, sql.Named("id", newCustID)).Scan(
|
||||
&newCustID, &custName, &addr1, &addr2, &city, &state, &zip, &country, &sql.NullTime{}, &sql.NullTime{})
|
||||
if err != nil {
|
||||
log.Fatalf("Get customer failed: %v", err)
|
||||
}
|
||||
fmt.Printf("🔎 Fetched Customer: %s, %s, %s\n", custName, city, state)
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 4️⃣ List contacts for the customer via sp_GetContactsByCustomer
|
||||
// -----------------------------------------------------------------
|
||||
fmt.Println("📄 Contacts for the customer:")
|
||||
rows, err := db.Query(`EXEC dbo.sp_GetContactsByCustomer @CustomerID = @id`, sql.Named("id", newCustID))
|
||||
if err != nil {
|
||||
log.Fatalf("Get contacts failed: %v", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var contactID, custID, ctID int
|
||||
var value string
|
||||
var isPrimary bool
|
||||
var typeName string
|
||||
if err = rows.Scan(&contactID, &custID, &ctID, &value, &isPrimary, &sql.NullTime{}, &sql.NullTime{}, &typeName); err != nil {
|
||||
log.Fatalf("Scanning contacts: %v", err)
|
||||
}
|
||||
fmt.Printf("- %s (%s) Primary:%v\n", value, typeName, isPrimary)
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
log.Fatalf("Row iteration error: %v", err)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 5️⃣ Update the customer name via sp_UpdateCustomer
|
||||
// -----------------------------------------------------------------
|
||||
_, err = db.Exec(`EXEC dbo.sp_UpdateCustomer
|
||||
@CustomerID = @id,
|
||||
@CustomerName = @name,
|
||||
@AddressLine1 = @addr1,
|
||||
@AddressLine2 = @addr2,
|
||||
@City = @city,
|
||||
@State = @state,
|
||||
@ZipCode = @zip,
|
||||
@Country = @country`,
|
||||
sql.Named("id", newCustID),
|
||||
sql.Named("name", "Acme Corp – Updated"),
|
||||
sql.Named("addr1", "123 Main St"),
|
||||
sql.Named("addr2", nil),
|
||||
sql.Named("city", "New York"),
|
||||
sql.Named("state", "NY"),
|
||||
sql.Named("zip", "10001"),
|
||||
sql.Named("country", "USA"),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Update customer failed: %v", err)
|
||||
}
|
||||
fmt.Println("✏️ Updated customer name")
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 6️⃣ Delete the contact and the customer (cleanup)
|
||||
// -----------------------------------------------------------------
|
||||
_, err = db.Exec(`EXEC dbo.sp_DeleteContact @ContactID = @cid`, sql.Named("cid", newContactID))
|
||||
if err != nil {
|
||||
log.Fatalf("Delete contact failed: %v", err)
|
||||
}
|
||||
fmt.Println("🗑️ Deleted contact")
|
||||
|
||||
_, err = db.Exec(`EXEC dbo.sp_DeleteCustomer @CustomerID = @cid`, sql.Named("cid", newCustID))
|
||||
if err != nil {
|
||||
log.Fatalf("Delete customer failed: %v", err)
|
||||
}
|
||||
fmt.Println("🗑️ Deleted customer")
|
||||
|
||||
fmt.Println("✅ All CRUD operations completed successfully")
|
||||
}
|
||||
3
db/data/.system/instance_id
Normal file
3
db/data/.system/instance_id
Normal file
@@ -0,0 +1,3 @@
|
||||
59629046-e974-4356-ba63-5f0605022367
|
||||
9979554600398963173
|
||||
3457
|
||||
0
db/data/.system/system/debug/PASSWD.LOG
Normal file
0
db/data/.system/system/debug/PASSWD.LOG
Normal file
BIN
db/data/.system/system/lsa.hiv
Normal file
BIN
db/data/.system/system/lsa.hiv
Normal file
Binary file not shown.
BIN
db/data/.system/system/security.hiv
Normal file
BIN
db/data/.system/system/security.hiv
Normal file
Binary file not shown.
223
db/init.sql
Normal file
223
db/init.sql
Normal file
@@ -0,0 +1,223 @@
|
||||
-- init.sql: Create CustomerDB schema, tables, types, procedures, and views.
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- Create the database
|
||||
-- ------------------------------------------------------------
|
||||
IF DB_ID(N'CustomerDB') IS NULL
|
||||
BEGIN
|
||||
CREATE DATABASE CustomerDB;
|
||||
END
|
||||
GO
|
||||
|
||||
USE CustomerDB;
|
||||
GO
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- Types / Lookup tables
|
||||
-- ------------------------------------------------------------
|
||||
CREATE TABLE dbo.ContactTypes (
|
||||
ContactTypeID INT IDENTITY(1,1) PRIMARY KEY,
|
||||
TypeName NVARCHAR(50) NOT NULL UNIQUE
|
||||
);
|
||||
GO
|
||||
|
||||
INSERT INTO dbo.ContactTypes (TypeName) VALUES
|
||||
(N'Phone'),
|
||||
(N'Email'),
|
||||
(N'Fax'),
|
||||
(N'Website');
|
||||
GO
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- Core tables
|
||||
-- ------------------------------------------------------------
|
||||
CREATE TABLE dbo.Customers (
|
||||
CustomerID INT IDENTITY(1,1) PRIMARY KEY,
|
||||
CustomerName NVARCHAR(150) NOT NULL,
|
||||
AddressLine1 NVARCHAR(200) NULL,
|
||||
AddressLine2 NVARCHAR(200) NULL,
|
||||
City NVARCHAR(100) NULL,
|
||||
State NVARCHAR(100) NULL,
|
||||
ZipCode NVARCHAR(20) NULL,
|
||||
Country NVARCHAR(100) NULL,
|
||||
CreatedAt DATETIME2(0) NOT NULL CONSTRAINT DF_Customers_CreatedAt DEFAULT (SYSDATETIME()),
|
||||
UpdatedAt DATETIME2(0) NULL
|
||||
);
|
||||
GO
|
||||
|
||||
CREATE TABLE dbo.Contacts (
|
||||
ContactID INT IDENTITY(1,1) PRIMARY KEY,
|
||||
CustomerID INT NOT NULL,
|
||||
ContactTypeID INT NOT NULL,
|
||||
ContactValue NVARCHAR(200) NOT NULL,
|
||||
IsPrimary BIT NOT NULL CONSTRAINT DF_Contacts_IsPrimary DEFAULT (0),
|
||||
CreatedAt DATETIME2(0) NOT NULL CONSTRAINT DF_Contacts_CreatedAt DEFAULT (SYSDATETIME()),
|
||||
UpdatedAt DATETIME2(0) NULL,
|
||||
CONSTRAINT FK_Contacts_Customers FOREIGN KEY (CustomerID) REFERENCES dbo.Customers(CustomerID) ON DELETE CASCADE,
|
||||
CONSTRAINT FK_Contacts_ContactTypes FOREIGN KEY (ContactTypeID) REFERENCES dbo.ContactTypes(ContactTypeID)
|
||||
);
|
||||
GO
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- Stored procedures for Customers
|
||||
-- ------------------------------------------------------------
|
||||
CREATE PROCEDURE dbo.sp_InsertCustomer
|
||||
@CustomerName NVARCHAR(150),
|
||||
@AddressLine1 NVARCHAR(200) = NULL,
|
||||
@AddressLine2 NVARCHAR(200) = NULL,
|
||||
@City NVARCHAR(100) = NULL,
|
||||
@State NVARCHAR(100) = NULL,
|
||||
@ZipCode NVARCHAR(20) = NULL,
|
||||
@Country NVARCHAR(100) = NULL,
|
||||
@NewCustomerID INT OUTPUT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
INSERT INTO dbo.Customers (CustomerName, AddressLine1, AddressLine2, City, State, ZipCode, Country)
|
||||
VALUES (@CustomerName, @AddressLine1, @AddressLine2, @City, @State, @ZipCode, @Country);
|
||||
|
||||
SET @NewCustomerID = SCOPE_IDENTITY();
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE dbo.sp_GetCustomer
|
||||
@CustomerID INT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SELECT *
|
||||
FROM dbo.Customers
|
||||
WHERE CustomerID = @CustomerID;
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE dbo.sp_UpdateCustomer
|
||||
@CustomerID INT,
|
||||
@CustomerName NVARCHAR(150),
|
||||
@AddressLine1 NVARCHAR(200) = NULL,
|
||||
@AddressLine2 NVARCHAR(200) = NULL,
|
||||
@City NVARCHAR(100) = NULL,
|
||||
@State NVARCHAR(100) = NULL,
|
||||
@ZipCode NVARCHAR(20) = NULL,
|
||||
@Country NVARCHAR(100) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
UPDATE dbo.Customers
|
||||
SET CustomerName = @CustomerName,
|
||||
AddressLine1 = @AddressLine1,
|
||||
AddressLine2 = @AddressLine2,
|
||||
City = @City,
|
||||
State = @State,
|
||||
ZipCode = @ZipCode,
|
||||
Country = @Country,
|
||||
UpdatedAt = SYSDATETIME()
|
||||
WHERE CustomerID = @CustomerID;
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE dbo.sp_DeleteCustomer
|
||||
@CustomerID INT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DELETE FROM dbo.Customers WHERE CustomerID = @CustomerID;
|
||||
END
|
||||
GO
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- Stored procedures for Contacts
|
||||
-- ------------------------------------------------------------
|
||||
CREATE PROCEDURE dbo.sp_InsertContact
|
||||
@CustomerID INT,
|
||||
@ContactTypeID INT,
|
||||
@ContactValue NVARCHAR(200),
|
||||
@IsPrimary BIT = 0,
|
||||
@NewContactID INT OUTPUT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
INSERT INTO dbo.Contacts (CustomerID, ContactTypeID, ContactValue, IsPrimary)
|
||||
VALUES (@CustomerID, @ContactTypeID, @ContactValue, @IsPrimary);
|
||||
|
||||
SET @NewContactID = SCOPE_IDENTITY();
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE dbo.sp_GetContactsByCustomer
|
||||
@CustomerID INT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SELECT c.*, ct.TypeName
|
||||
FROM dbo.Contacts c
|
||||
JOIN dbo.ContactTypes ct ON c.ContactTypeID = ct.ContactTypeID
|
||||
WHERE c.CustomerID = @CustomerID;
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE dbo.sp_UpdateContact
|
||||
@ContactID INT,
|
||||
@ContactTypeID INT,
|
||||
@ContactValue NVARCHAR(200),
|
||||
@IsPrimary BIT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
UPDATE dbo.Contacts
|
||||
SET ContactTypeID = @ContactTypeID,
|
||||
ContactValue = @ContactValue,
|
||||
IsPrimary = @IsPrimary,
|
||||
UpdatedAt = SYSDATETIME()
|
||||
WHERE ContactID = @ContactID;
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE dbo.sp_DeleteContact
|
||||
@ContactID INT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DELETE FROM dbo.Contacts WHERE ContactID = @ContactID;
|
||||
END
|
||||
GO
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- Views
|
||||
-- ------------------------------------------------------------
|
||||
CREATE VIEW dbo.vw_CustomerContacts AS
|
||||
SELECT
|
||||
cu.CustomerID,
|
||||
cu.CustomerName,
|
||||
cu.AddressLine1,
|
||||
cu.AddressLine2,
|
||||
cu.City,
|
||||
cu.State,
|
||||
cu.ZipCode,
|
||||
cu.Country,
|
||||
ct.TypeName,
|
||||
co.ContactValue,
|
||||
co.IsPrimary
|
||||
FROM dbo.Customers cu
|
||||
LEFT JOIN dbo.Contacts co ON cu.CustomerID = co.CustomerID
|
||||
LEFT JOIN dbo.ContactTypes ct ON co.ContactTypeID = ct.ContactTypeID;
|
||||
GO
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- Sample data (optional, for quick testing)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO dbo.Customers (CustomerName, City, State, Country)
|
||||
VALUES (N'Acme Corp', N'New York', N'NY', N'USA');
|
||||
|
||||
DECLARE @CustID INT = SCOPE_IDENTITY();
|
||||
|
||||
EXEC dbo.sp_InsertContact @CustomerID = @CustID,
|
||||
@ContactTypeID = (SELECT ContactTypeID FROM dbo.ContactTypes WHERE TypeName = N'Phone'),
|
||||
@ContactValue = N'555-1234',
|
||||
@IsPrimary = 1,
|
||||
@NewContactID = @CustID OUTPUT;
|
||||
GO
|
||||
33
docker-compose.yml
Normal file
33
docker-compose.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
services:
|
||||
mssql:
|
||||
image: mcr.microsoft.com/mssql/server:2019-latest
|
||||
container_name: mssql
|
||||
environment:
|
||||
- SA_PASSWORD=Passw0rd
|
||||
- ACCEPT_EULA=Y
|
||||
ports:
|
||||
- "1433:1433"
|
||||
volumes:
|
||||
- ./db/data:/var/opt/mssql
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
container_name: backend
|
||||
depends_on:
|
||||
- mssql
|
||||
environment:
|
||||
- DB_SERVER=mssql
|
||||
- DB_USER=sa
|
||||
- DB_PASSWORD=Passw0rd
|
||||
- DB_NAME=CustomerDB
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./backend:/app
|
||||
command: ./main
|
||||
|
||||
networks:
|
||||
default:
|
||||
driver: bridge
|
||||
Reference in New Issue
Block a user