diff --git a/.github/workflows/api.yml b/.github/workflows/api.yml
new file mode 100644
index 000000000..9f8b80efb
--- /dev/null
+++ b/.github/workflows/api.yml
@@ -0,0 +1,81 @@
+name: API Deployment
+
+env:
+ registryName: op3eqv3gu7pvecosureg.azurecr.io
+ repositoryName: techexcel/csapi
+ dockerFolderPath: ./src/ContosoSuitesWebAPI
+ tag: ${{github.run_number}}
+
+on:
+ push:
+ branches: [ main ]
+ paths: src/ContosoSuitesWebAPI/**
+ pull_request:
+ branches: [ main ]
+ paths: src/ContosoSuitesWebAPI/**
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0
+
+ - name: Restore dependencies
+ run: dotnet restore ./src/ContosoSuitesWebAPI/ContosoSuitesWebAPI.csproj
+ - name: Build
+ run: dotnet build --no-restore ./src/ContosoSuitesWebAPI/ContosoSuitesWebAPI.csproj
+
+ dockerBuildPush:
+ runs-on: ubuntu-latest
+ needs: build
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Docker Login
+ # You may pin to the exact commit or the version.
+ # uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
+ uses: docker/login-action@v3
+ with:
+ # Server address of Docker registry. If not set then will default to Docker Hub
+ registry: ${{ secrets.ACR_LOGIN_SERVER }}
+ # Username used to log against the Docker registry
+ username: ${{ secrets.ACR_USERNAME }}
+ # Password or personal access token used to log against the Docker registry
+ password: ${{ secrets.ACR_PASSWORD }}
+ # Log out from the Docker registry at the end of a job
+ logout: true
+
+ - name: Docker Build
+ run: docker build -t $registryName/$repositoryName:$tag --build-arg build_version=$tag $dockerFolderPath
+
+ - name: Docker Push
+ run: docker push $registryName/$repositoryName:$tag
+
+ deploy-to-prod:
+
+ runs-on: ubuntu-latest
+ needs: dockerBuildPush
+ environment:
+ name: prod
+ url: https://op3eqv3gu7pve-api.azurewebsites.net/
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: 'Login via Azure CLI'
+ uses: azure/login@v2.1.1
+ with:
+ creds: ${{ secrets.AZURE_CREDENTIALS }}
+
+ - uses: azure/webapps-deploy@v2
+ with:
+ app-name: 'op3eqv3gu7pve-api'
+ images: op3eqv3gu7pvecosureg.azurecr.io/techexcel/csapi:${{github.run_number}}
diff --git a/.github/workflows/dashboard.yml b/.github/workflows/dashboard.yml
new file mode 100644
index 000000000..7bdc6cf5d
--- /dev/null
+++ b/.github/workflows/dashboard.yml
@@ -0,0 +1,70 @@
+name: Dashboard Deployment
+
+env:
+ registryName: op3eqv3gu7pvecosureg.azurecr.io
+ repositoryName: techexcel/csdash
+ dockerFolderPath: ./src/ContosoSuitesDashboard
+ tag: ${{github.run_number}}
+
+on:
+ push:
+ branches: [ main ]
+ paths: src/ContosoSuitesDashboard/**
+ pull_request:
+ branches: [ main ]
+ paths: src/ContosoSuitesDashboard/**
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+jobs:
+ dockerBuildPush:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Docker Login
+ # You may pin to the exact commit or the version.
+ # uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
+ uses: docker/login-action@v3
+ with:
+ # Server address of Docker registry. If not set then will default to Docker Hub
+ registry: ${{ secrets.ACR_LOGIN_SERVER }}
+ # Username used to log against the Docker registry
+ username: ${{ secrets.ACR_USERNAME }}
+ # Password or personal access token used to log against the Docker registry
+ password: ${{ secrets.ACR_PASSWORD }}
+ # Log out from the Docker registry at the end of a job
+ logout: true
+
+ - name: Create Secrets File
+ run: echo "$STREAMLIT_SECRETS" > ./src/ContosoSuitesDashboard/.streamlit/secrets.toml
+ shell: bash
+ env:
+ STREAMLIT_SECRETS: ${{ secrets.STREAMLIT_SECRETS }}
+
+ - name: Docker Build
+ run: docker build -t $registryName/$repositoryName:$tag --build-arg build_version=$tag $dockerFolderPath
+
+ - name: Docker Push
+ run: docker push $registryName/$repositoryName:$tag
+
+ deploy-to-prod:
+
+ runs-on: ubuntu-latest
+ needs: dockerBuildPush
+ environment:
+ name: prod
+ url: https://op3eqv3gu7pve-dash.azurewebsites.net/
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: 'Login via Azure CLI'
+ uses: azure/login@v2.1.1
+ with:
+ creds: ${{ secrets.AZURE_CREDENTIALS }}
+
+ - uses: azure/webapps-deploy@v2
+ with:
+ app-name: 'op3eqv3gu7pve-dash'
+ images: op3eqv3gu7pvecosureg.azurecr.io/techexcel/csdash:${{github.run_number}}
diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yml
deleted file mode 100644
index 431fe11f2..000000000
--- a/.github/workflows/jekyll-gh-pages.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-# Sample workflow for building and deploying a Jekyll site to GitHub Pages
-name: Deploy Jekyll with GitHub Pages dependencies preinstalled
-
-on:
- # Runs on pushes targeting the default branch
- push:
- branches: ["main"]
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
-permissions:
- contents: read
- pages: write
- id-token: write
-
-# Allow only one concurrent deployment to GitHub Pages
-concurrency:
- group: "pages"
- cancel-in-progress: true
-
-jobs:
- # Build job
- build:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Setup Ruby
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: '3.1' # Not needed with a .ruby-version file
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- cache-version: 0 # Increment this number if you need to re-download cached gems
- - name: Setup Pages
- id: pages
- uses: actions/configure-pages@v4
- - name: Build with Jekyll
- # Outputs to the './_site' directory by default
- run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
- env:
- JEKYLL_ENV: production
- - name: Upload artifact
- uses: actions/upload-pages-artifact@v3
-
- # Deployment job
- deploy:
- environment:
- name: github-pages
- url: ${{ steps.deployment.outputs.page_url }}
- runs-on: ubuntu-latest
- needs: build
- steps:
- - name: Deploy to GitHub Pages
- id: deployment
- uses: actions/deploy-pages@v4
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 6f90d62bc..d526e723c 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,11 +1,11 @@
{
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Attach to .NET Functions",
- "type": "coreclr",
- "request": "attach",
- "processId": "${command:azureFunctions.pickProcess}"
- }
- ]
- }
\ No newline at end of file
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Attach to .NET Functions",
+ "type": "coreclr",
+ "request": "attach",
+ "processId": "${command:azureFunctions.pickProcess}"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index b6f83d84d..fca79ee8d 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,81 +1,81 @@
{
- "version": "2.0.0",
- "tasks": [
- {
- "label": "clean (functions)",
- "command": "dotnet",
- "args": [
- "clean",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary"
- ],
- "type": "process",
- "problemMatcher": "$msCompile",
- "options": {
- "cwd": "${workspaceFolder}/src\\ContosoSuitesVectorizationFunction"
- }
- },
- {
- "label": "build (functions)",
- "command": "dotnet",
- "args": [
- "build",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary"
- ],
- "type": "process",
- "dependsOn": "clean (functions)",
- "group": {
- "kind": "build",
- "isDefault": true
- },
- "problemMatcher": "$msCompile",
- "options": {
- "cwd": "${workspaceFolder}/src\\ContosoSuitesVectorizationFunction"
- }
- },
- {
- "label": "clean release (functions)",
- "command": "dotnet",
- "args": [
- "clean",
- "--configuration",
- "Release",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary"
- ],
- "type": "process",
- "problemMatcher": "$msCompile",
- "options": {
- "cwd": "${workspaceFolder}/src\\ContosoSuitesVectorizationFunction"
- }
- },
- {
- "label": "publish (functions)",
- "command": "dotnet",
- "args": [
- "publish",
- "--configuration",
- "Release",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary"
- ],
- "type": "process",
- "dependsOn": "clean release (functions)",
- "problemMatcher": "$msCompile",
- "options": {
- "cwd": "${workspaceFolder}/src\\ContosoSuitesVectorizationFunction"
- }
- },
- {
- "type": "func",
- "dependsOn": "build (functions)",
- "options": {
- "cwd": "${workspaceFolder}/src/ContosoSuitesVectorizationFunction/bin/Debug/net8.0"
- },
- "command": "host start",
- "isBackground": true,
- "problemMatcher": "$func-dotnet-watch"
- }
- ]
- }
\ No newline at end of file
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "clean (functions)",
+ "command": "dotnet",
+ "args": [
+ "clean",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "type": "process",
+ "problemMatcher": "$msCompile",
+ "options": {
+ "cwd": "${workspaceFolder}/src\\ContosoSuitesVectorizationFunction"
+ }
+ },
+ {
+ "label": "build (functions)",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "type": "process",
+ "dependsOn": "clean (functions)",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": "$msCompile",
+ "options": {
+ "cwd": "${workspaceFolder}/src\\ContosoSuitesVectorizationFunction"
+ }
+ },
+ {
+ "label": "clean release (functions)",
+ "command": "dotnet",
+ "args": [
+ "clean",
+ "--configuration",
+ "Release",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "type": "process",
+ "problemMatcher": "$msCompile",
+ "options": {
+ "cwd": "${workspaceFolder}/src\\ContosoSuitesVectorizationFunction"
+ }
+ },
+ {
+ "label": "publish (functions)",
+ "command": "dotnet",
+ "args": [
+ "publish",
+ "--configuration",
+ "Release",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "type": "process",
+ "dependsOn": "clean release (functions)",
+ "problemMatcher": "$msCompile",
+ "options": {
+ "cwd": "${workspaceFolder}/src\\ContosoSuitesVectorizationFunction"
+ }
+ },
+ {
+ "type": "func",
+ "dependsOn": "build (functions)",
+ "options": {
+ "cwd": "${workspaceFolder}/src/ContosoSuitesVectorizationFunction/bin/Debug/net8.0"
+ },
+ "command": "host start",
+ "isBackground": true,
+ "problemMatcher": "$func-dotnet-watch"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/ContosoSuitesDashboard/pages/1_Chat_with_Data.py b/src/ContosoSuitesDashboard/pages/1_Chat_with_Data.py
index 98f65a586..d1b3abd40 100644
--- a/src/ContosoSuitesDashboard/pages/1_Chat_with_Data.py
+++ b/src/ContosoSuitesDashboard/pages/1_Chat_with_Data.py
@@ -11,6 +11,10 @@ def create_chat_completion(messages):
aoai_key = st.secrets["aoai"]["key"]
aoai_deployment_name = st.secrets["aoai"]["deployment_name"]
+ search_endpoint = st.secrets["search"]["endpoint"]
+ search_key = st.secrets["search"]["key"]
+ search_index_name = st.secrets["search"]["index_name"]
+
client = openai.AzureOpenAI(
api_key=aoai_key,
api_version="2024-06-01",
@@ -23,9 +27,25 @@ def create_chat_completion(messages):
{"role": m["role"], "content": m["content"]}
for m in messages
],
- stream=True
+ stream=True,
+ extra_body={
+ "data_sources": [
+ {
+ "type": "azure_search",
+ "parameters": {
+ "endpoint": search_endpoint,
+ "index_name": search_index_name,
+ "authentication": {
+ "type": "api_key",
+ "key": search_key
+ }
+ }
+ }
+ ]
+ }
)
+
def handle_chat_prompt(prompt):
"""Echo the user's prompt to the chat window.
Then, send the user's prompt to Azure OpenAI and display the response."""
diff --git a/src/ContosoSuitesVectorizationFunction/CosmosChangeFeedVectorization.cs b/src/ContosoSuitesVectorizationFunction/CosmosChangeFeedVectorization.cs
index 0eed4f385..1b9efbe32 100644
--- a/src/ContosoSuitesVectorizationFunction/CosmosChangeFeedVectorization.cs
+++ b/src/ContosoSuitesVectorizationFunction/CosmosChangeFeedVectorization.cs
@@ -55,7 +55,7 @@ public object Run([CosmosDBTrigger(
{
// Combine the hotel and details fields into a single string for embedding.
var request_text = $"Hotel: {request.Hotel}\n Request Details: {request.Details}";
- // Generate a vector for the maintenance request.
+ // Generate a vector for the maintenance request
var embedding = _embeddingClient.GenerateEmbedding(request_text);
var requestVector = embedding.Value.Vector;
diff --git a/src/ContosoSuitesWebAPI/ContosoSuitesWebAPI.csproj b/src/ContosoSuitesWebAPI/ContosoSuitesWebAPI.csproj
index 93e25c9b2..7d45eac99 100644
--- a/src/ContosoSuitesWebAPI/ContosoSuitesWebAPI.csproj
+++ b/src/ContosoSuitesWebAPI/ContosoSuitesWebAPI.csproj
@@ -1,18 +1,20 @@
-
-
-
- net8.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ net8.0
+ enable
+ enable
+ 9001f04f-8067-44dc-adfa-3eb2b45b179f
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ContosoSuitesWebAPI/Program.cs b/src/ContosoSuitesWebAPI/Program.cs
index 983cd70bb..9040b4c3d 100644
--- a/src/ContosoSuitesWebAPI/Program.cs
+++ b/src/ContosoSuitesWebAPI/Program.cs
@@ -8,9 +8,17 @@
using Azure.AI.OpenAI;
using Azure;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using Microsoft.SemanticKernel.ChatCompletion;
var builder = WebApplication.CreateBuilder(args);
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
@@ -28,6 +36,18 @@
return client;
});
+builder.Services.AddSingleton((_) =>
+{
+ IKernelBuilder kernelBuilder = Kernel.CreateBuilder();
+ kernelBuilder.AddAzureOpenAIChatCompletion(
+ deploymentName: builder.Configuration["AzureOpenAI:DeploymentName"]!,
+ endpoint: builder.Configuration["AzureOpenAI:Endpoint"]!,
+ apiKey: builder.Configuration["AzureOpenAI:ApiKey"]!
+ );
+ kernelBuilder.Plugins.AddFromType();
+ return kernelBuilder.Build();
+});
+
builder.Services.AddSingleton((_) =>
{
var endpoint = new Uri(builder.Configuration["AzureOpenAI:Endpoint"]!);
@@ -57,34 +77,27 @@
app.MapGet("/Hotels", async () =>
{
- throw new NotImplementedException();
+ var hotels = await app.Services.GetRequiredService().GetHotels();
+ return hotels;
})
.WithName("GetHotels")
.WithOpenApi();
-
+
app.MapGet("/Hotels/{hotelId}/Bookings/", async (int hotelId) =>
{
- throw new NotImplementedException();
+ var bookings = await app.Services.GetRequiredService().GetBookingsForHotel(hotelId);
+ return bookings;
})
.WithName("GetBookingsForHotel")
.WithOpenApi();
-
+
app.MapGet("/Hotels/{hotelId}/Bookings/{min_date}", async (int hotelId, DateTime min_date) =>
{
- throw new NotImplementedException();
+ var bookings = await app.Services.GetRequiredService().GetBookingsByHotelAndMinimumDate(hotelId, min_date);
+ return bookings;
})
.WithName("GetRecentBookingsForHotel")
.WithOpenApi();
-
-app.MapPost("/Chat", async Task (HttpRequest request) =>
-{
- var message = await Task.FromResult(request.Form["message"]);
-
- return "This endpoint is not yet available.";
-})
- .WithName("Chat")
- .WithOpenApi();
-
app.MapGet("/Vectorize", async (string text, [FromServices] IVectorizationService vectorizationService) =>
{
var embeddings = await vectorizationService.GetEmbeddings(text);
@@ -109,4 +122,19 @@
.WithName("Copilot")
.WithOpenApi();
+app.MapPost("/Chat", async Task (HttpRequest request) =>
+{
+ var message = await Task.FromResult(request.Form["message"]);
+ var kernel = app.Services.GetRequiredService();
+ var chatCompletionService = kernel.GetRequiredService();
+ var executionSettings = new OpenAIPromptExecutionSettings
+ {
+ ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
+ };
+ var response = await chatCompletionService.GetChatMessageContentAsync(message.ToString(), executionSettings, kernel);
+ return response?.Content!;
+})
+ .WithName("Chat")
+ .WithOpenApi();
+
app.Run();
diff --git a/src/ContosoSuitesWebAPI/Services/DatabaseService.cs b/src/ContosoSuitesWebAPI/Services/DatabaseService.cs
index 154bdd6c3..ba5881dcb 100644
--- a/src/ContosoSuitesWebAPI/Services/DatabaseService.cs
+++ b/src/ContosoSuitesWebAPI/Services/DatabaseService.cs
@@ -1,11 +1,16 @@
using System.Runtime.CompilerServices;
using Microsoft.Data.SqlClient;
using ContosoSuitesWebAPI.Entities;
+using Microsoft.SemanticKernel;
+using System.ComponentModel;
namespace ContosoSuitesWebAPI.Services;
public class DatabaseService : IDatabaseService
{
+
+ [KernelFunction]
+ [Description("Get all hotels.")]
public async Task> GetHotels()
{
var sql = "SELECT HotelID, HotelName, City, Country FROM dbo.Hotel";
@@ -31,6 +36,98 @@ public async Task> GetHotels()
return hotels;
}
+ [KernelFunction]
+ [Description("Get bookings missing hotel rooms.")]
+ public async Task> GetBookingsMissingHotelRooms()
+ {
+ var sql = """
+ SELECT
+ b.BookingID,
+ b.CustomerID,
+ b.HotelID,
+ b.StayBeginDate,
+ b.StayEndDate,
+ b.NumberOfGuests
+ FROM dbo.Booking b
+ WHERE NOT EXISTS
+ (
+ SELECT 1
+ FROM dbo.BookingHotelRoom h
+ WHERE
+ b.BookingID = h.BookingID
+ );
+ """;
+ using var conn = new SqlConnection(
+ connectionString: Environment.GetEnvironmentVariable("SQLCONNSTR_ContosoSuites")!
+ );
+ conn.Open();
+ using var cmd = new SqlCommand(sql, conn);
+ using var reader = await cmd.ExecuteReaderAsync();
+ var bookings = new List();
+ while (await reader.ReadAsync())
+ {
+ bookings.Add(new Booking
+ {
+ BookingID = reader.GetInt32(0),
+ CustomerID = reader.GetInt32(1),
+ HotelID = reader.GetInt32(2),
+ StayBeginDate = reader.GetDateTime(3),
+ StayEndDate = reader.GetDateTime(4),
+ NumberOfGuests = reader.GetInt32(5)
+ });
+ }
+ conn.Close();
+
+ return bookings;
+ }
+
+ [KernelFunction]
+ [Description("Get bookings with multiple hotel rooms.")]
+ public async Task> GetBookingsWithMultipleHotelRooms()
+ {
+ var sql = """
+ SELECT
+ b.BookingID,
+ b.CustomerID,
+ b.HotelID,
+ b.StayBeginDate,
+ b.StayEndDate,
+ b.NumberOfGuests
+ FROM dbo.Booking b
+ WHERE
+ (
+ SELECT COUNT(1)
+ FROM dbo.BookingHotelRoom h
+ WHERE
+ b.BookingID = h.BookingID
+ ) > 1;
+ """;
+ using var conn = new SqlConnection(
+ connectionString: Environment.GetEnvironmentVariable("SQLCONNSTR_ContosoSuites")!
+ );
+ conn.Open();
+ using var cmd = new SqlCommand(sql, conn);
+ using var reader = await cmd.ExecuteReaderAsync();
+ var bookings = new List();
+ while (await reader.ReadAsync())
+ {
+ bookings.Add(new Booking
+ {
+ BookingID = reader.GetInt32(0),
+ CustomerID = reader.GetInt32(1),
+ HotelID = reader.GetInt32(2),
+ StayBeginDate = reader.GetDateTime(3),
+ StayEndDate = reader.GetDateTime(4),
+ NumberOfGuests = reader.GetInt32(5)
+ });
+ }
+ conn.Close();
+
+ return bookings;
+ }
+
+ [KernelFunction]
+ [Description("Get bookings for hotels.")]
public async Task> GetBookingsForHotel(int hotelId)
{
var sql = "SELECT BookingID, CustomerID, HotelID, StayBeginDate, StayEndDate, NumberOfGuests FROM dbo.Booking WHERE HotelID = @HotelID";
@@ -59,6 +156,8 @@ public async Task> GetBookingsForHotel(int hotelId)
return bookings;
}
+ [KernelFunction]
+ [Description("Get bookings by hotel and minimum date.")]
public async Task> GetBookingsByHotelAndMinimumDate(int hotelId, DateTime dt)
{
var sql = "SELECT BookingID, CustomerID, HotelID, StayBeginDate, StayEndDate, NumberOfGuests FROM dbo.Booking WHERE HotelID = @HotelID AND StayBeginDate >= @StayBeginDate";
diff --git a/src/ContosoSuitesWebAPI/Services/IDatabaseService.cs b/src/ContosoSuitesWebAPI/Services/IDatabaseService.cs
index 8237bb43c..5775e9466 100644
--- a/src/ContosoSuitesWebAPI/Services/IDatabaseService.cs
+++ b/src/ContosoSuitesWebAPI/Services/IDatabaseService.cs
@@ -7,4 +7,8 @@ public interface IDatabaseService
Task> GetHotels();
Task> GetBookingsForHotel(int hotelId);
Task> GetBookingsByHotelAndMinimumDate(int hotelId, DateTime dt);
+
+ Task> GetBookingsMissingHotelRooms();
+Task> GetBookingsWithMultipleHotelRooms();
+
}
\ No newline at end of file
diff --git a/src/InfrastructureAsCode/DeployAzureResources.bicep b/src/InfrastructureAsCode/DeployAzureResources.bicep
index c5a4c82d1..c956ad10e 100644
--- a/src/InfrastructureAsCode/DeployAzureResources.bicep
+++ b/src/InfrastructureAsCode/DeployAzureResources.bicep
@@ -2,7 +2,7 @@
param location string = resourceGroup().location
@description('Password for the SQL Server admin user. PLEASE CHANGE THIS BEFORE DEPLOYMENT!')
-param sqlAdminPassword string = 'g@G9@2nD7C1BP%uh'
+param sqlAdminPassword string = '1$Password'
@description('Model deployments for OpenAI')
param deployments array = [