Compare commits

..

74 Commits

Author SHA1 Message Date
6e305d0db3 Group by issue in responses 2024-01-22 12:10:26 -05:00
e82bae41c7 Update docker-compose.acr.yml for Azure Pipelines 2024-01-18 17:05:13 +00:00
70e3e24875 Update docker-compose.acr.yml for Azure Pipelines 2024-01-18 17:01:17 +00:00
a3a4a85bc1 fixed region issue 2024-01-18 11:40:20 -05:00
94e340d941 added active and in active survey endpoints 2023-12-19 13:17:05 -05:00
8b05f61f44 Modified logic to get latest response based on survetid, locationId, ane employee id 2023-12-16 12:46:04 -05:00
1c26852670 added survey start and end date validation 2023-12-13 17:08:59 -05:00
9188ded00e adding multiple questions for survey id 2023-12-07 09:47:22 -05:00
4b9ab46901 Merge branch 'docker-sql' of https://dev.azure.com/MDCSB-Telecommuters/Emergency%20Preparedness%20Disaster%20Recovery%20Project%20%28EPDRP%29/_git/Backend-API-Services into docker-sql 2023-12-07 09:27:52 -05:00
f967e38c81 Changing POST to PUT 2023-12-07 02:48:07 -05:00
5ad4478670 Merge Conflict resolution 2023-12-07 02:28:57 -05:00
d7005479c5 Adding endpoint for mutiple questions update 2023-12-07 02:16:00 -05:00
3de53c1198 conflict resolution 2023-12-07 01:45:26 -05:00
5cc331202b mergr conflict resolve 2023-12-07 01:41:00 -05:00
9ec9b8b96f Merged PR 79: changed download url format and added new endpoint for doculink isactive update
changed download url format and added new endpoint for doculink isactive update
2023-12-04 19:57:42 +00:00
e58782243c changed download url format and added new endpoint for doculink isactive update 2023-12-04 14:56:13 -05:00
795c7c021d changed download url format and added new endpoint for doculink isactive update 2023-12-04 14:54:01 -05:00
b209c2619e Merge branch 'docker-sql' of https://dev.azure.com/MDCSB-Telecommuters/Emergency%20Preparedness%20Disaster%20Recovery%20Project%20%28EPDRP%29/_git/Backend-API-Services into docker-sql 2023-12-04 14:52:49 -05:00
b131994274 Merged PR 76: added IsActive flag in doculinks request
added IsActive flag in doculinks request
2023-12-04 14:54:04 +00:00
fcc0205175 added IsActive flag in doculinks request 2023-12-04 09:52:05 -05:00
0c90a6caaa Merge branch 'docker-sql' of https://dev.azure.com/MDCSB-Telecommuters/Emergency%20Preparedness%20Disaster%20Recovery%20Project%20%28EPDRP%29/_git/Backend-API-Services into docker-sql 2023-12-04 09:51:27 -05:00
0ed7641a8b added IsActive flag in doculinks request 2023-12-04 09:51:19 -05:00
92666d6efa Merged PR 74: doculinks and attachments url changes 2023-12-01 23:08:35 +00:00
9aa3f230c5 attachment and doculinks url changes 2023-12-01 17:23:19 -05:00
99a7802cf6 attachment and doculinks url changes 2023-12-01 17:22:49 -05:00
db5e14bde4 added multi language support for doculink attachments 2023-11-30 19:04:14 -05:00
1df15e9a6d Return Employee ID for POST 2023-11-27 14:49:14 -05:00
66215d1fce Merged PR 65: fixed question translation issue
fixed question translation issue
2023-11-15 14:09:10 +00:00
281a789deb fixed question transation issue 2023-11-15 09:05:20 -05:00
8ccb37f45b Merged PR 63: Added new endpoint for creating multiple questions
Added new endpoint for creating multiple questions
2023-11-14 21:48:48 +00:00
fc154274a0 Added new endpoint for creating multiple questions 2023-11-14 15:16:15 -05:00
1fba3e81f1 Reverted Surveys CORS changes WithOrigins('*') 2023-11-13 21:24:16 -05:00
f00c7dd99c Updated WithOrigins(http://localhost:3000) test fix CORS 2023-11-12 14:28:58 -05:00
b7e5e7d7fe Updated CORS with POST specific with Surveys 2023-11-11 22:00:06 -05:00
43eb29c2e8 Updat for CORS Resolution 2023-11-10 14:09:43 -05:00
45c61ee729 Addi ng CORS 2023-11-10 13:27:31 -05:00
17df019d55 Adding CORS policy to all micro-services 2023-11-10 13:07:50 -05:00
d0650c36f3 Merged PR 59: completed heatmap api changes for location and response api
completed heatmap api changes for location and response api
2023-11-07 22:28:57 +00:00
19fac4d810 completed heatmap api changes for location and response api 2023-11-07 17:04:19 -05:00
17cd993a56 Merged PR 56: fixed survey issue in response level, and added logic for start and end date...
fixed survey issue in response level, and added logic for start and end date as optional date.
2023-11-01 18:34:47 +00:00
8285588db9 fixed survey issue in response level, and added logic for start and end date as optional date. 2023-11-01 14:29:47 -04:00
6fbe21979f Merged PR 53: fixed survey put issue, and added export excel in responses
fixed survey put issue, amd added export excel in responses
2023-11-01 13:29:16 +00:00
fc166e65c9 fixed survey put issue, amd added export excel in responses 2023-10-31 16:40:46 -04:00
ae6b306290 reverted doculinks grouping by linktype 2023-10-24 12:22:59 -04:00
d3a751a6ad added status field in survey micro service 2023-10-23 11:56:39 -04:00
2182b9a6b3 added status field in survey micro service 2023-10-23 11:39:56 -04:00
8624eeeb97 Merge branch 'docker-sql' of https://dev.azure.com/MDCSB-Telecommuters/Emergency%20Preparedness%20Disaster%20Recovery%20Project%20%28EPDRP%29/_git/Backend-API-Services into docker-sql 2023-10-16 22:45:08 -04:00
16d45d6632 docker-compose.acr added 2023-10-16 22:44:08 -04:00
c77e0452c4 added logic to get active surveys from survey responses 2023-10-16 14:13:20 -04:00
6ad5bb1572 merged latest changes from docker to dev 2023-10-13 14:48:08 -04:00
8e0a7df68b added muilti language return format for question categories for question by survey 2023-10-13 13:29:21 -04:00
cb3c7f8f6a added muilti language return format for question categories for question by survey 2023-10-13 13:21:33 -04:00
01ccd97528 table update tested 2023-10-13 13:17:00 -04:00
26b360e0a9 Merge branch 'docker-sql' of https://dev.azure.com/MDCSB-Telecommuters/Emergency%20Preparedness%20Disaster%20Recovery%20Project%20%28EPDRP%29/_git/Backend-API-Services into docker-sql 2023-10-13 08:58:24 -04:00
360a58c026 Merge branch 'docker-branch' into docker-sql 2023-10-12 16:03:21 -04:00
26e79432e2 table name changes 2023-10-12 16:01:24 -04:00
11c6fc0dc9 Merge branch 'docker-sql' of https://dev.azure.com/MDCSB-Telecommuters/Emergency%20Preparedness%20Disaster%20Recovery%20Project%20%28EPDRP%29/_git/Backend-API-Services into docker-sql 2023-10-11 21:26:04 -04:00
99633d8dda Connection string sql dev server updated 2023-10-11 21:23:47 -04:00
8e3f6674c6 Merge branch 'docker-branch' into docker-sql 2023-10-11 19:25:09 -04:00
885fdeb117 updated question category 2023-10-11 19:24:50 -04:00
14956057cd Merge branch 'docker-branch' into docker-sql 2023-10-11 15:34:42 -04:00
fa3e3bbd99 added seed data for questions and surveys for demo 2023-10-11 15:33:21 -04:00
340ba6fa6d removed all migrations 2023-10-10 16:34:56 -04:00
46794057c4 Added sql docker logic 2023-10-10 16:28:30 -04:00
71d4b524e7 doculinks changes for grouping 2023-10-09 13:29:01 -04:00
c7a2dc5910 seed changes for doculinks 2023-10-06 15:53:09 -04:00
643bc0c76a Merged docker with docker sql branch 2023-10-06 15:14:13 -04:00
d0023114a3 updated doculink changes 2023-09-26 12:40:55 -04:00
465bf4b081 Merge branch 'dev' into Database-Integration 2023-09-13 16:52:43 -04:00
e04bccfffd Merged new dev changes 2023-09-13 13:16:42 -04:00
0544c7397d 314: updated document multi language output format 2023-09-11 13:34:50 -04:00
9c536a1c52 Modified Documents api for InMemory Logic 2023-09-11 13:34:50 -04:00
48be1a74c9 Merge branch 'DocumentsAPI' into Database-Integration 2023-08-31 19:02:47 -04:00
eb07c31ff6 Database integration 2023-08-18 17:14:41 -04:00
102 changed files with 1522 additions and 352 deletions

Binary file not shown.

View File

@ -0,0 +1,7 @@
{
"ExpandedNodes": [
""
],
"SelectedNode": "\\DamageAssesment.sln",
"PreviewInSolutionExplorer": false
}

View File

@ -396,3 +396,4 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
**/migrations/

View File

@ -13,7 +13,12 @@
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Answers.Db
{
[Table("Answers")]
public class Answer
{
[Key]

View File

@ -1,13 +1,19 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace DamageAssesment.Api.Answers.Db
{
public class AnswerDbContext:DbContext
{
public AnswerDbContext(DbContextOptions options):base(options)
private IConfiguration _Configuration { get; set; }
public AnswerDbContext(DbContextOptions options,IConfiguration configuration):base(options)
{
_Configuration= configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(_Configuration.GetConnectionString("AnswerConnection"));
}
public DbSet<Db.Answer> Answers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)

View File

@ -8,10 +8,16 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// CORS setup to allow requests from any origin.
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
// Add Swagger/OpenAPI documentation support.
builder.Services.AddSwaggerGen(c =>
{
// Include XML comments from your assembly
@ -23,11 +29,14 @@ builder.Services.AddScoped<IAnswersProvider, AnswersProvider>();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //4/30
builder.Services.AddDbContext<AnswerDbContext>(option =>
{
option.UseInMemoryDatabase("Answers");
option.UseSqlServer("AnswerConnection");
});
var app = builder.Build();
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
@ -35,9 +44,13 @@ if (app.Environment.IsDevelopment())
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseCors("DamageAppCorsPolicy");
app.UseAuthorization();
// Enable CORS, authentication, and authorization middleware.
app.UseCors("DamageAppCorsPolicy");
app.UseAuthorization();
// Map controllers to their respective routes.
app.MapControllers();
app.Run();

View File

@ -198,13 +198,12 @@ namespace DamageAssesment.Api.Answers.Providers
{
if (!answerDbContext.Answers.Any())
{
answerDbContext.Answers.Add(new Db.Answer() { Id = 1, AnswerText = "Yes", Comment = "Comment test 4", QuestionId = 1, SurveyResponseId = 1 });
answerDbContext.Answers.Add(new Db.Answer() { Id = 2, AnswerText = "No", Comment = "Comment test 5", QuestionId = 2, SurveyResponseId = 1 });
// Uncomment the lines below to add more initial data if needed
//answerDbContext.Answers.Add(new Db.Answer() { Id = 3, AnswerText = "No", Comment = "No Comment", QuestionId = 3, SurveyResponseId = 1 });
//answerDbContext.Answers.Add(new Db.Answer() { Id = 4, AnswerText = "Yes", Comment = "No Comment", QuestionId = 1, SurveyResponseId = 2 });
//answerDbContext.Answers.Add(new Db.Answer() { Id = 5, AnswerText = "No", Comment = "No Comment", QuestionId = 2, SurveyResponseId = 2 });
//answerDbContext.Answers.Add(new Db.Answer() { Id = 6, AnswerText = "No", Comment = "No Comment", QuestionId = 3, SurveyResponseId = 2 });
answerDbContext.Answers.Add(new Db.Answer() { AnswerText = "Yes", Comment = "", QuestionId = 1, SurveyResponseId = 1 });
answerDbContext.Answers.Add(new Db.Answer() { AnswerText = "No", Comment = "myComment", QuestionId = 2, SurveyResponseId = 1 });
//answerDbContext.Answers.Add(new Db.Answer() { AnswerText = "No", Comment = "No Comment", QuestionId = 3, SurveyResponseId = 1 });
//answerDbContext.Answers.Add(new Db.Answer() { AnswerText = "Yes", Comment = "No Comment", QuestionId = 1, SurveyResponseId = 2 });
//answerDbContext.Answers.Add(new Db.Answer() { AnswerText = "No", Comment = "No Comment", QuestionId = 2, SurveyResponseId = 2 });
//answerDbContext.Answers.Add(new Db.Answer() { AnswerText = "No", Comment = "No Comment", QuestionId = 3, SurveyResponseId = 2 });
answerDbContext.SaveChanges();
}
}

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -8,5 +8,11 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ConnectionStrings": {
//"AnswerConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;"
// "AnswerConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;",
"AnswerConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;"
}
}

View File

@ -136,6 +136,80 @@ namespace DamageAssesment.Api.Attachments.Controllers
}
}
/// <summary>
/// download an existing attachment.
/// </summary>
[HttpGet("attachments/download/{id}")]
public async Task<IActionResult> downloadfile(int id)
{
try
{
var result = await this.AttachmentProvider.GetDownloadAttachmentAsync(id);
if (!result.IsSuccess)
return NotFound();
string path = await UploadService.GetFile(result.Attachment.URI);
if (path == null)
return NotFound();
var contentType = GetContentType(result.Attachment.FileName);
if (contentType == "application/octet-stream")
return PhysicalFile(path, contentType, result.Attachment.FileName);
return PhysicalFile(path, contentType, enableRangeProcessing: true);// result.Attachment.FileName);
}
catch (Exception ex)
{
// Handle the exception here or log it
return StatusCode(500, "An error occurred: " + ex.Message);
}
//try
//{
// var result = await this.AttachmentProvider.GetDownloadAttachmentAsync(id);
// if(!result.IsSuccess)
// return NotFound();
// byte[] fileContent = await UploadService.DownloadFile(result.Attachment.URI);
// if (fileContent == null || fileContent.Length == 0)
// return NotFound();
// var contentType = "application/octet-stream";
// return File(fileContent, contentType, result.Attachment.FileName);
//}
//catch (Exception ex)
//{
// // Handle the exception here or log it
// return StatusCode(500, "An error occurred: " + ex.Message);
//}
}
private string GetContentType(string fileName)
{
// You can add more content types based on the file extensions
switch (Path.GetExtension(fileName).ToLower())
{
//case ".txt":
// return "text/plain";
case ".jpg":
case ".jpeg":
return "image/jpeg";
case ".png":
return "image/png";
case ".gif":
return "image/gif";
case ".bmp":
return "image/bmp";
case ".webp":
return "image/webp";
case ".csv":
return "text/csv";
case ".pdf":
return "application/pdf";
case ".docx":
case ".doc":
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
case ".xlsx":
case ".xls":
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
// Add more cases as needed
default:
return "application/octet-stream";
}
}
/// <summary>
/// Delete an existing attachment.
/// </summary>
[HttpDelete("attachments/{id}")]

View File

@ -14,8 +14,19 @@
<PackageReference Include="Azure.Storage.Blobs" Version="12.16.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Attachments.Db
{
[Table("AnswerAttachments")]
public class Attachment
{
[Key]

View File

@ -1,11 +1,19 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace DamageAssesment.Api.Attachments.Db
{
public class AttachmentsDbContext:DbContext
{
public AttachmentsDbContext(DbContextOptions options) : base(options)
private IConfiguration _Configuration { get; set; }
public AttachmentsDbContext(DbContextOptions options, IConfiguration configuration) : base(options)
{
_Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(_Configuration.GetConnectionString("AttachmentConnection"));
}
public DbSet<Db.Attachment> Attachments { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)

View File

@ -9,6 +9,7 @@ namespace DamageAssesment.Api.Attachments.Interfaces
Task<(bool IsSuccess, IEnumerable<Models.Attachment> Attachments, string ErrorMessage)> PostAttachmentAsync(List<Models.Attachment> Attachments);
Task<(bool IsSuccess, IEnumerable<Models.Attachment> Attachments, string ErrorMessage)> PutAttachmentAsync(List<Models.Attachment> Attachments);
Task<(bool IsSuccess, Models.Attachment Attachment, string Path)> DeleteAttachmentAsync(int Id);
Task<(bool IsSuccess, Models.Attachment Attachment, string Path)> GetDownloadAttachmentAsync(int Id);
Task<(bool IsSuccess, int counter, string Path)> DeleteAttachmentsAsync(int responseId, int answerId);
Task<(bool IsSuccess, int counter, string Path)> DeleteBulkAttachmentsAsync(int responseId, List<int> answerIds);
Task<(bool IsSuccess, int counter, string message)> GetAttachmentCounter();

View File

@ -7,6 +7,8 @@ namespace DamageAssesment.Api.Attachments.Interfaces
List<Models.Attachment> UploadAttachment(int responseId,int answerId, int counter, List<IFormFile> postedFile);
List<Models.Attachment> UploadAttachment(int responseId, int counter, List<AnswerInfo> answers);
public List<Models.Attachment> UpdateAttachments(int responseId, List<AnswerInfo> answers, IEnumerable<Models.Attachment> attachments);
Task<byte[]> DownloadFile(string path);
Task<string> GetFile(string path);
void Deletefile(string path);
void Movefile(string path);
}

View File

@ -8,12 +8,18 @@ using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
// CORS setup to allow requests from any origin.
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
// Add Swagger/OpenAPI documentation support.
builder.Services.AddSwaggerGen(c =>
{
// Include XML comments from your assembly
@ -21,13 +27,14 @@ builder.Services.AddSwaggerGen(c =>
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddScoped<IAttachmentsProvider, AttachmentsProvider>();
builder.Services.AddScoped<IUploadService, UploadService>();
builder.Services.AddScoped<IAzureBlobService,AzureBlobService>();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //4/30
builder.Services.AddDbContext<AttachmentsDbContext>(option =>
{
option.UseInMemoryDatabase("Attachments");
option.UseSqlServer("AttachmentConnection");
});
builder.Services.Configure<FormOptions>(o =>
{
@ -35,6 +42,9 @@ builder.Services.Configure<FormOptions>(o =>
o.MultipartBodyLengthLimit = int.MaxValue;
o.MemoryBufferThreshold = int.MaxValue;
});
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
var app = builder.Build();
@ -45,9 +55,11 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI();
}
// Enable CORS, authentication, and authorization middleware.
app.UseCors("DamageAppCorsPolicy");
app.UseAuthorization();
app.UseHttpsRedirection();
app.MapControllers();
app.UseStaticFiles();
app.Run();

View File

@ -14,14 +14,18 @@ namespace DamageAssesment.Api.Attachments.Providers
private ILogger<AttachmentsProvider> logger;
private IUploadService uploadservice;
private IMapper mapper;
public AttachmentsProvider(AttachmentsDbContext AttachmentDbContext, ILogger<AttachmentsProvider> logger, IMapper mapper,IUploadService uploadservice)
private readonly IHttpContextAccessor httpContextAccessor;
private string baseUrl;
public AttachmentsProvider(AttachmentsDbContext AttachmentDbContext, ILogger<AttachmentsProvider> logger, IMapper mapper,IUploadService uploadservice, IHttpContextAccessor httpContextAccessor)
{
this.AttachmentDbContext = AttachmentDbContext;
this.logger = logger;
this.mapper = mapper;
this.uploadservice = uploadservice;
SeedData();
this.httpContextAccessor = httpContextAccessor;
baseUrl = $"{httpContextAccessor.HttpContext.Request.Scheme}://{httpContextAccessor.HttpContext.Request.Host}";
baseUrl = baseUrl + "/attachments/download";
//SeedData();
}
public async Task<(bool IsSuccess, IEnumerable<Models.Attachment> Attachments, string ErrorMessage)> GetAttachmentsAsync()
{
@ -32,6 +36,10 @@ namespace DamageAssesment.Api.Attachments.Providers
var Attachment = await AttachmentDbContext.Attachments.AsNoTracking().Where(a => !a.IsDeleted).ToListAsync();
if (Attachment != null)
{
foreach (var attachment in Attachment)
{
attachment.URI = $"{baseUrl}/{attachment.Id}";
}
logger?.LogInformation($"{Attachment.Count} Attachments(s) found");
var result = mapper.Map<IEnumerable<Db.Attachment>, IEnumerable<Models.Attachment>>(Attachment);
return (true, result, null);
@ -54,6 +62,7 @@ namespace DamageAssesment.Api.Attachments.Providers
if (Attachment != null)
{
logger?.LogInformation($"{Attachment} customer(s) found");
Attachment.URI = $"{baseUrl}/{Attachment.Id}";
var result = mapper.Map<Db.Attachment, Models.Attachment>(Attachment);
return (true, result, null);
}
@ -73,6 +82,10 @@ namespace DamageAssesment.Api.Attachments.Providers
List<Db.Attachment> attachments = mapper.Map<List<Models.Attachment>, List<Db.Attachment>>(Attachments);
AttachmentDbContext.Attachments.AddRange(attachments);
await AttachmentDbContext.SaveChangesAsync();
foreach (var attachment in attachments)
{
attachment.URI = $"{baseUrl}/{attachment.Id}";
}
var result = mapper.Map<IEnumerable<Db.Attachment>, IEnumerable<Models.Attachment>>(attachments);
return (true, result, null);
}
@ -91,6 +104,10 @@ namespace DamageAssesment.Api.Attachments.Providers
List<Db.Attachment> attachments = mapper.Map<List<Models.Attachment>, List<Db.Attachment>>(Attachments);
AttachmentDbContext.Attachments.UpdateRange(attachments);
await AttachmentDbContext.SaveChangesAsync();
foreach (var attachment in attachments)
{
attachment.URI = $"{baseUrl}/{attachment.Id}";
}
var result = mapper.Map<IEnumerable<Db.Attachment>, IEnumerable<Models.Attachment>>(attachments);
return (true, result, null);
}
@ -197,6 +214,24 @@ namespace DamageAssesment.Api.Attachments.Providers
{
return AttachmentDbContext.Attachments.AsNoTracking().Count(e => e.Id == id && !e.IsDeleted) > 0;
}
public async Task<(bool IsSuccess, Models.Attachment Attachment, string Path)> GetDownloadAttachmentAsync(int Id)
{
try
{
Db.Attachment Attachment = AttachmentDbContext.Attachments.Where(a => a.Id == Id).AsNoTracking().FirstOrDefault();
if (Attachment == null)
{
return (false, null, "Not Found");
}
return (true, mapper.Map<Db.Attachment, Models.Attachment>(Attachment), $"Attachment {Id}");
}
catch (Exception ex)
{
logger?.LogError(ex.ToString());
return (false, null, ex.Message);
}
}
private void SeedData()
{

View File

@ -24,6 +24,41 @@ namespace DamageAssesment.Api.Attachments.Providers
uploadpath = configuration.GetValue<string>("Fileupload:folderpath");
Deletepath = configuration.GetValue<string>("Fileupload:Deletepath");
}
public async Task<string> GetFile(string path)
{
try
{
if (System.IO.File.Exists(path))
{
return path;
}
return null; // File not found
}
catch (Exception ex)
{
// Handle or log the exception as needed
throw;
}
}
public async Task<byte[]> DownloadFile(string path)
{
try
{
if (System.IO.File.Exists(path))
{
return await System.IO.File.ReadAllBytesAsync(path);
}
return null; // File not found
}
catch (Exception ex)
{
// Handle or log the exception as needed
throw;
}
}
public List<Models.Attachment> UploadAttachment(int responseId,int answerId,int counter, List<IFormFile> postedFile)
{
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), uploadpath);
@ -89,7 +124,7 @@ namespace DamageAssesment.Api.Attachments.Providers
{
counter++;
var UserfileName = Path.GetFileName(file.FileName);
var UserfileName = Path.GetFileName(file.FileName+ file.FileExtension);
var fileName = String.Format("Attachment_{0}{1}", counter, file.FileExtension);
var dbPath = Path.Combine(fullDirectoryPath, fileName);
File.WriteAllBytes(dbPath, Convert.FromBase64String(file.FileContent));
@ -126,7 +161,7 @@ namespace DamageAssesment.Api.Attachments.Providers
foreach (var file in item.postedFiles)
{
Models.Attachment attachment= attachments.Where(a=>a.Id == file.AttachmentId).FirstOrDefault();
var UserfileName = Path.GetFileName(file.FileName);
var UserfileName = Path.GetFileName(file.FileName + file.FileExtension);
var fileName = String.Format("Attachment_{0}{1}", attachment?.Id, file.FileExtension);
var dbPath = Path.Combine(fullDirectoryPath, fileName);
File.WriteAllBytes(dbPath, Convert.FromBase64String(file.FileContent));

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -12,5 +12,11 @@
"Fileupload": {
"folderpath": "DMS_Attachments/Active",
"Deletepath": "DMS_Attachments/Deleted"
},
"ConnectionStrings": {
//"AttachmentConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;"
// "AttachmentConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;"
"AttachmentConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;"
}
}

View File

@ -197,7 +197,29 @@ namespace DamageAssesment.Api.DocuLinks.Test
var result = (NotFoundResult)await DocumentProvider.DeleteDocument(1);
Assert.Equal(404, result.StatusCode);
}
[Fact(DisplayName = "Update Document IsActive- Ok case")]
public async Task UpdateDocumentAsync_ShouldReturnStatusCode200()
{
var mockDocumentService = new Mock<IDoculinkProvider>();
var mockUploadService = new Mock<IUploadService>();
var mockResponse = await MockData.getOkResponse(1);
mockDocumentService.Setup(service => service.UpdateDocumentAsync(1,true)).ReturnsAsync(mockResponse);
var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object);
var result = (OkObjectResult)await DocumentProvider.UpdateIsActiveDocument(1,true);
Assert.Equal(200, result.StatusCode);
}
[Fact(DisplayName = "Update Document IsActive - NotFound case")]
public async Task UpdateDocumentAsync_ShouldReturnStatusCode404()
{
var mockDocumentService = new Mock<IDoculinkProvider>();
var mockUploadService = new Mock<IUploadService>();
var mockResponse = await MockData.getNotFoundResponse();
mockDocumentService.Setup(service => service.UpdateDocumentAsync(1,true)).ReturnsAsync(mockResponse);
var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object);
var result = (NotFoundResult)await DocumentProvider.UpdateIsActiveDocument(1,true);
Assert.Equal(404, result.StatusCode);
}
// Link Type Test cases

View File

@ -32,7 +32,8 @@ namespace DamageAssesment.Api.DocuLinks.Test
doclinksAttachments.Add(new DoculinkAttachments()
{
docName = "",Path="www.google.com",
IsAttachments=false,CustomOrder=1
Language = "en",
IsAttachments =false,CustomOrder=1
});
list.Add(new DocuLinks.Models.ResDoculink()
{
@ -74,6 +75,7 @@ namespace DamageAssesment.Api.DocuLinks.Test
docName = "",
Path = "www.google.com",
IsAttachments = false,
Language = "en",
CustomOrder = 1
});
list.Add(new DocuLinks.Models.ResDoculink()
@ -138,6 +140,7 @@ namespace DamageAssesment.Api.DocuLinks.Test
docName = "",
Path = "www.google.com",
IsAttachments = false,
Language = "en",
CustomOrder = 1
});
return new Models.Doculink
@ -165,6 +168,7 @@ namespace DamageAssesment.Api.DocuLinks.Test
docName = "",
Path = "www.google.com",
IsAttachments = false,
Language = "en",
CustomOrder = 1
});
List<DocuLinks.Models.Doculink> DocuLinks = new List<Models.Doculink>();

View File

@ -13,7 +13,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
private readonly IDoculinkProvider documentsProvider;
private readonly IUploadService uploadService;
public DoculinkController(IDoculinkProvider documentsProvider,IUploadService uploadService)
public DoculinkController(IDoculinkProvider documentsProvider, IUploadService uploadService)
{
this.documentsProvider = documentsProvider;
@ -41,7 +41,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
[HttpGet]
[Route("doculinks/types/{id}")]
[Route("doculinks/types/{id}/{language:alpha}")]
public async Task<IActionResult> GetLinkTypeAsync(int id,string? language)
public async Task<IActionResult> GetLinkTypeAsync(int id, string? language)
{
var result = await this.documentsProvider.GetLinkTypeAsync(id, language);
if (result.IsSuccess)
@ -55,11 +55,11 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
/// </summary>
[HttpPut]
[Route("doculinks/types/{id}")]
public async Task<IActionResult> UpdateLinkType(int id,Models.LinkType linkType)
public async Task<IActionResult> UpdateLinkType(int id, Models.LinkType linkType)
{
if (linkType != null)
{
var result = await this.documentsProvider.UpdateLinkTypeAsync(id,linkType);
var result = await this.documentsProvider.UpdateLinkTypeAsync(id, linkType);
if (result.IsSuccess)
{
return Ok(result.LinkType);
@ -104,6 +104,80 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
return NotFound();
}
/// <summary>
/// download an existing attachment.
/// </summary>
[HttpGet("doculinks/download/{id}")]
public async Task<IActionResult> downloadfile(int id)
{
try
{
var result = await this.documentsProvider.GetDownloadAttachmentAsync(id);
if (!result.IsSuccess)
return NotFound();
string path = await uploadService.GetFile(result.DoculinkAttachments.Path);
if (path == null)
return NotFound();
var contentType = GetContentType(result.DoculinkAttachments.docName);
if (contentType == "application/octet-stream")
return PhysicalFile(path, contentType, result.DoculinkAttachments.docName);
return PhysicalFile(path, contentType, enableRangeProcessing: true);
}
catch (Exception ex)
{
// Handle the exception here or log it
return StatusCode(500, "An error occurred: " + ex.Message);
}
//try
//{
// var result = await this.documentsProvider.GetDownloadAttachmentAsync(id);
// if (!result.IsSuccess)
// return NotFound();
// byte[] fileContent = await uploadService.DownloadFile(result.DoculinkAttachments.Path);
// if (fileContent == null || fileContent.Length == 0)
// return NotFound();
// var contentType = "application/octet-stream";
// return File(fileContent, contentType, result.DoculinkAttachments.docName);
//}
//catch (Exception ex)
//{
// // Handle the exception here or log it
// return StatusCode(500, "An error occurred: " + ex.Message);
//}
}
private string GetContentType(string fileName)
{
// You can add more content types based on the file extensions
switch (Path.GetExtension(fileName).ToLower())
{
//case ".txt":
// return "text/plain";
case ".jpg":
case ".jpeg":
return "image/jpeg";
case ".png":
return "image/png";
case ".gif":
return "image/gif";
case ".bmp":
return "image/bmp";
case ".webp":
return "image/webp";
case ".csv":
return "text/csv";
case ".pdf":
return "application/pdf";
case ".docx":
case ".doc":
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
case ".xlsx":
case ".xls":
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
// Add more cases as needed
default:
return "application/octet-stream";
}
}
/// <summary>
/// Get all Doculink.
/// </summary>
///
@ -111,7 +185,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
[Route("doculinks/{linktype:alpha}")]
[Route("doculinks/{linktype:alpha}/{language:alpha}")]
[HttpGet]
public async Task<IActionResult> GetDocumentsAsync(string? linktype, string? language,bool? isactive)
public async Task<IActionResult> GetDocumentsAsync(string? linktype, string? language, bool? isactive)
{
var result = await this.documentsProvider.GetdocumentsByLinkAsync(linktype, language, isactive);
if (result.IsSuccess)
@ -129,7 +203,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
[HttpGet]
public async Task<IActionResult> GetDocumentsByActiveAsync(string? linktype, string? language)
{
var result = await this.documentsProvider.GetdocumentsByLinkAsync(linktype, language,true);
var result = await this.documentsProvider.GetdocumentsByLinkAsync(linktype, language, true);
if (result.IsSuccess)
{
return Ok(result.documents);
@ -158,7 +232,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
[Route("doculinks/{id}")]
[Route("doculinks/{id}/{linktype:alpha}")]
[Route("doculinks/{id}/{linktype:alpha}/{language:alpha}")]
public async Task<IActionResult> GetDocumentAsync(int id,string? linktype, string? language)
public async Task<IActionResult> GetDocumentAsync(int id, string? linktype, string? language)
{
var result = await this.documentsProvider.GetDocumentAsync(id, linktype, language);
if (result.IsSuccess)
@ -172,7 +246,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
/// </summary>
[HttpPut]
[Route("doculinks/{id}")]
public async Task<IActionResult> UpdateDocument(int id,ReqDoculink documentInfo)
public async Task<IActionResult> UpdateDocument(int id, ReqDoculink documentInfo)
{
if (documentInfo != null)
{
@ -180,7 +254,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
if (dbdoc.IsSuccess)
{
var documents = await this.documentsProvider.GetDocumentCounter();
Models.Doculink DocuLink= uploadService.UpdateDocuments(documents.counter,dbdoc.Document, documentInfo);
Models.Doculink DocuLink = uploadService.UpdateDocuments(documents.counter, dbdoc.Document, documentInfo);
var result = await this.documentsProvider.UpdateDocumentAsync(id, DocuLink);
if (result.IsSuccess)
{
@ -193,6 +267,20 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
return BadRequest(documentInfo);
}
/// <summary>
/// update existing doclink isactive field.
/// </summary>
[HttpPut]
[Route("doculinks/{id}/{isactive}")]
public async Task<IActionResult> UpdateIsActiveDocument(int id, bool isactive)
{
var result = await this.documentsProvider.UpdateDocumentAsync(id, isactive);
if (result.IsSuccess)
{
return Ok(result.Document);
}
return NotFound();
}
/// <summary>
/// Create new doclink.
/// </summary>
[HttpPost]
@ -204,7 +292,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers
if (documentInfo != null)
{
var documents = await this.documentsProvider.GetDocumentCounter();
Models.Doculink DocuLink= uploadService.UploadDocument(documents.counter, documentInfo);
Models.Doculink DocuLink = uploadService.UploadDocument(documents.counter, documentInfo);
var result = await this.documentsProvider.PostDocumentAsync(DocuLink);
if (result.IsSuccess)
{

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.DocuLinks.Db
{
[Table("Doculinks")]
public class Doculink
{
[Key]

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace DamageAssesment.Api.DocuLinks.Db
{
[Table("DoculinkAttachments")]
public class DoculinkAttachments
{
@ -14,5 +15,6 @@ namespace DamageAssesment.Api.DocuLinks.Db
public string Path { get; set; }
public bool IsAttachments { get; set; }
public int CustomOrder { get; set; }
public string Language { get; set; }
}
}

View File

@ -7,8 +7,15 @@ namespace DamageAssesment.Api.DocuLinks.Db
{
public class DoculinkDbContext : DbContext
{
public DoculinkDbContext(DbContextOptions options) : base(options)
private IConfiguration _Configuration { get; set; }
public DoculinkDbContext(DbContextOptions options, IConfiguration configuration) : base(options)
{
_Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(_Configuration.GetConnectionString("DoculinConnection"));
}
public DbSet<Db.Doculink> Documents { get; set; }
public DbSet<Db.LinkType> LinkTypes { get; set; }

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.DocuLinks.Db
{
[Table("DoculinkTrans")]
public class DoculinkTranslation
{
[Key]

View File

@ -1,7 +1,9 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.DocuLinks.Db
{
[Table("DoculinkTypes")]
public class LinkType
{
[Key]

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace DamageAssesment.Api.DocuLinks.Db
{
[Table("DoculinkTypeTrans")]
public class LinksTranslation
{
[Key]

View File

@ -11,7 +11,9 @@ namespace DamageAssesment.Api.DocuLinks.Interfaces
Task<(bool IsSuccess, IEnumerable<Models.ResDoculink> documents, string ErrorMessage)> GetdocumentsByLinkTypeIdAsync(int? linkTypeId, string? language, bool? isactive);
Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> PostDocumentAsync(Models.Doculink Document);
Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> UpdateDocumentAsync(int id, Models.Doculink Document);
Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> UpdateDocumentAsync(int id, bool isactive);
Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> DeleteDocumentAsync(int id);
Task<(bool IsSuccess, Models.DoculinkAttachments DoculinkAttachments, string Path)> GetDownloadAttachmentAsync(int id);
Task<(bool IsSuccess, int counter, string message)> GetDocumentCounter();

View File

@ -7,6 +7,8 @@ namespace DamageAssesment.Api.DocuLinks.Interfaces
Models.Doculink UploadDocument( int counter, ReqDoculink documentInfo);
public Models.Doculink UpdateDocuments(int counter, Models.Doculink document, ReqDoculink documentInfo);
void Deletefile(string path);
Task<byte[]> DownloadFile(string path);
Task<string> GetFile(string path);
void Movefile(string path);
}
}

View File

@ -8,6 +8,7 @@ namespace DamageAssesment.Api.DocuLinks.Models
public string docName { get; set; }
public string Path { get; set; }
public bool IsAttachments { get; set; }
public string Language { get; set; }
public int CustomOrder { get; set; }
}
}

View File

@ -7,6 +7,7 @@ namespace DamageAssesment.Api.DocuLinks.Models
public int Id { get; set; }
public int linkTypeId { get; set; }
public List<DoculinkTranslation> documentsTranslations { get; set; }
public bool IsActive { get; set; }
public int CustomOrder { get; set; }
public List<FileModel>? Files { get; set; }
}
@ -18,5 +19,6 @@ namespace DamageAssesment.Api.DocuLinks.Models
public int CustomOrder { get; set; }
public string url { get;set; }
public bool IsAttachments { get; set; }
public string Language { get; set; }
}
}

View File

@ -6,6 +6,11 @@ using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
// CORS setup to allow requests from any origin.
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
// Add services to the container.
builder.Services.AddControllers();
@ -19,14 +24,18 @@ builder.Services.AddSwaggerGen(c =>
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddScoped<IDoculinkProvider, DoculinkProvider>();
builder.Services.AddScoped<IUploadService, UploadService>();
builder.Services.AddScoped<IAzureBlobService, AzureBlobService>();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //4/30
builder.Services.AddDbContext<DoculinkDbContext>(option =>
{
option.UseInMemoryDatabase("DocumentConnection");
option.UseSqlServer("DoculinConnection");
});
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
var app = builder.Build();
// Configure the HTTP request pipeline.
@ -36,6 +45,10 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI();
}
// Enable CORS, authentication, and authorization middleware.
app.UseCors("DamageAppCorsPolicy");
app.UseAuthorization();
app.MapControllers();

View File

@ -2,13 +2,16 @@
using DamageAssesment.Api.DocuLinks.Db;
using DamageAssesment.Api.DocuLinks.Interfaces;
using DamageAssesment.Api.DocuLinks.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.Eventing.Reader;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Xml;
using System.Xml.Linq;
@ -22,13 +25,18 @@ namespace DamageAssesment.Api.DocuLinks.Providers
private ILogger<DoculinkProvider> logger;
private IUploadService uploadservice;
private IMapper mapper;
private readonly IHttpContextAccessor httpContextAccessor;
private string baseUrl;
public DoculinkProvider(DoculinkDbContext DocumentDbContext, ILogger<DoculinkProvider> logger, IMapper mapper, IUploadService uploadservice)
public DoculinkProvider(DoculinkDbContext DocumentDbContext, ILogger<DoculinkProvider> logger, IMapper mapper, IUploadService uploadservice, IHttpContextAccessor httpContextAccessor)
{
this.DocumentDbContext = DocumentDbContext;
this.logger = logger;
this.mapper = mapper;
this.uploadservice = uploadservice;
this.httpContextAccessor = httpContextAccessor;
baseUrl = $"{httpContextAccessor.HttpContext.Request.Scheme}://{httpContextAccessor.HttpContext.Request.Host}";
baseUrl = baseUrl + "/doculinks/download";
SeedData();
}
@ -71,11 +79,11 @@ namespace DamageAssesment.Api.DocuLinks.Providers
{
linkTypeId = 1;
fileModel = new FileModel() { FileName = "Sample" + i, FileExtension = ".txt", FileContent = "c2FtcGxl", IsAttachments = true, CustomOrder = 1 };
fileModel = new FileModel() { FileName = "Sample" + i, FileExtension = ".txt", FileContent = "c2FtcGxl", IsAttachments = true, CustomOrder = 1, Language = "en" };
}
else
fileModel = new FileModel() { url = "www.google" + i + ".com", IsAttachments = false, CustomOrder = 1 };
ReqDoculink documentInfo = new ReqDoculink() { linkTypeId = linkTypeId, CustomOrder = i, Files = new List<FileModel>() { fileModel } };
fileModel = new FileModel() { url = "www.google" + i + ".com", IsAttachments = false, CustomOrder = 1,Language="en" };
ReqDoculink documentInfo = new ReqDoculink() { linkTypeId = i, CustomOrder = i, Files = new List<FileModel>() { fileModel } };
Models.Doculink document = uploadservice.UploadDocument(counter, documentInfo);
DocumentDbContext.Documents.Add(mapper.Map<Models.Doculink, Db.Doculink>(document));
DocumentDbContext.SaveChanges();
@ -170,7 +178,42 @@ namespace DamageAssesment.Api.DocuLinks.Providers
MultiLanguage = dicttitle;
return MultiLanguage;
}
private List<Models.DoculinkAttachments> GetDocumentAttachment(int id,string? language)
{
List<Db.DoculinkAttachments> doculinkAttachments = null;
if (string.IsNullOrEmpty(language))
{
doculinkAttachments = DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id).ToList();
}
else
{
doculinkAttachments = DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id && a.Language == language).ToList();
}
foreach (var attachment in doculinkAttachments)
{
if (attachment.IsAttachments)
attachment.Path = $"{baseUrl}/{attachment.Id}";
}
return mapper.Map<List<Db.DoculinkAttachments>, List<Models.DoculinkAttachments>>(doculinkAttachments);
}
public async Task<(bool IsSuccess, Models.DoculinkAttachments DoculinkAttachments, string Path)> GetDownloadAttachmentAsync(int id)
{
try
{
Db.DoculinkAttachments Attachment = DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.Id == id).AsNoTracking().FirstOrDefault();
if (Attachment == null)
{
return (false, null, "Not Found");
}
return (true, mapper.Map<Db.DoculinkAttachments, Models.DoculinkAttachments>(Attachment), $"Attachment {id}");
}
catch (Exception ex)
{
logger?.LogError(ex.ToString());
return (false, null, ex.Message);
}
}
public async Task<(bool IsSuccess, IEnumerable<Models.ResDoculink> documents, string ErrorMessage)> GetdocumentsByLinkTypeIdAsync(int? linkTypeId, string? language, bool? isactive)
{
@ -192,8 +235,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers
item.titles = multilan.titles;
item.description = multilan.description;
item.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(item.linkTypeId, language));
item.doclinksAttachments = mapper.Map<List<Db.DoculinkAttachments>, List<Models.DoculinkAttachments>>(
DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == item.Id).ToList());
item.doclinksAttachments = GetDocumentAttachment(item.Id,language);
}
// List<ResDoculinks> doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList();
return (true, result, null);
@ -228,8 +270,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers
item.titles = multilan.titles;
item.description = multilan.description;
item.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(item.linkTypeId, language));
item.doclinksAttachments = mapper.Map<List<Db.DoculinkAttachments>, List<Models.DoculinkAttachments>>(
DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == item.Id).ToList());
item.doclinksAttachments = GetDocumentAttachment(item.Id, language);
}
//List<ResDoculinks> doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList();
return (true, result, null);
@ -284,8 +325,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers
result.documentsTranslations = mapper.Map<List<Db.DoculinkTranslation>, List<Models.DoculinkTranslation>>(
DocumentDbContext.DocumentsTranslations.Where(a => a.DocumentId == result.Id).ToList());
result.doclinksAttachments = mapper.Map<List<Db.DoculinkAttachments>, List<Models.DoculinkAttachments>>(
DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id).ToList());
result.doclinksAttachments = GetDocumentAttachment(id, "");
return (true, result, null);
}
return (false, null, "Not found");
@ -317,8 +357,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers
result.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(result.linkTypeId, language));
result.titles = multilan.titles;
result.description = multilan.description;
result.doclinksAttachments = mapper.Map<List<Db.DoculinkAttachments>, List<Models.DoculinkAttachments>>(
DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id).ToList());
result.doclinksAttachments = GetDocumentAttachment(id, language);
return (true, result, null);
}
return (false, null, "Not found");
@ -349,7 +388,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers
result.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(Document.linkTypeId, ""));
result.titles = multilan.titles;
result.description = multilan.description;
result.doclinksAttachments = Document.doclinksAttachments;
result.doclinksAttachments = GetDocumentAttachment(document.Id,"");
return (true, result, null);
}
catch (Exception ex)
@ -391,7 +430,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers
result.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(document.linkTypeId, ""));
result.titles = multilan.titles;
result.description = multilan.description;
result.doclinksAttachments = Document.doclinksAttachments;
result.doclinksAttachments = GetDocumentAttachment(document.Id, "");
return (true, result, "Successful");
}
else
@ -414,6 +453,35 @@ namespace DamageAssesment.Api.DocuLinks.Providers
return (false, null, ex.Message);
}
}
public async Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> UpdateDocumentAsync(int id,bool isactive)
{
try
{
Db.Doculink Document = DocumentDbContext.Documents.AsNoTracking().Where(a => a.Id == id).FirstOrDefault();
if (Document == null)
{
return (false, null, "Not Found");
}
Document.IsActive = isactive;
DocumentDbContext.Documents.Update(Document);
DocumentDbContext.SaveChanges();
var result = mapper.Map<Db.Doculink, Models.ResDoculink>(Document);
var multilan = CreateMultiLanguageObject(GetDocumentTranslations(Document.Id, ""));
result.titles = multilan.titles;
result.description = multilan.description;
result.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(result.linkTypeId, ""));
result.doclinksAttachments = mapper.Map<List<Db.DoculinkAttachments>, List<Models.DoculinkAttachments>>(
DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id).ToList());
return (true, result, $"DocumentId {id} deleted Successfuly");
}
catch (Exception ex)
{
logger?.LogError(ex.ToString());
return (false, null, ex.Message);
}
}
public async Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> DeleteDocumentAsync(int id)
{

View File

@ -25,6 +25,41 @@ namespace DamageAssesment.Api.DocuLinks.Providers
uploadpath = configuration.GetValue<string>("Fileupload:folderpath");
Deletepath = configuration.GetValue<string>("Fileupload:Deletepath");
}
public async Task<string> GetFile(string path)
{
try
{
if (System.IO.File.Exists(path))
{
return path;
}
return null; // File not found
}
catch (Exception ex)
{
// Handle or log the exception as needed
throw;
}
}
public async Task<byte[]> DownloadFile(string path)
{
try
{
if (System.IO.File.Exists(path))
{
return await System.IO.File.ReadAllBytesAsync(path);
}
return null; // File not found
}
catch (Exception ex)
{
// Handle or log the exception as needed
throw;
}
}
public Models.Doculink UploadDocument(int counter, ReqDoculink documentInfo)
{
@ -44,19 +79,20 @@ namespace DamageAssesment.Api.DocuLinks.Providers
counter++;
if (item.IsAttachments)
{
UserfileName = Path.GetFileName(item.FileName);
UserfileName = Path.GetFileName(item.FileName + item.FileExtension);
var fileName = String.Format("Document_{0}{1}", counter, item.FileExtension);
path = Path.Combine(fullDirectoryPath, fileName);
File.WriteAllBytes(path, Convert.FromBase64String(item.FileContent));
}
else
path = item.url;
attachments.Add(new Models.DoculinkAttachments { docName=UserfileName,Path=path,IsAttachments=item.IsAttachments,CustomOrder=item.CustomOrder });
attachments.Add(new Models.DoculinkAttachments { docName=UserfileName,Path=path,IsAttachments=item.IsAttachments,CustomOrder=item.CustomOrder,Language=item.Language });
}
}
Documents=new Models.Doculink (){ linkTypeId = documentInfo.linkTypeId,
documentsTranslations = documentInfo.documentsTranslations,doclinksAttachments=attachments,
IsDeleted=false,CustomOrder=documentInfo.CustomOrder, IsActive =true};
IsDeleted=false,CustomOrder=documentInfo.CustomOrder, IsActive =documentInfo.IsActive
};
return Documents;
}
@ -85,21 +121,21 @@ namespace DamageAssesment.Api.DocuLinks.Providers
counter++;
if (item.IsAttachments)
{
UserfileName = Path.GetFileName(item.FileName);
UserfileName = Path.GetFileName(item.FileName+item.FileExtension);
var fileName = String.Format("Document_{0}{1}", counter, item.FileExtension);
path = Path.Combine(fullDirectoryPath, fileName);
File.WriteAllBytes(path, Convert.FromBase64String(item.FileContent));
}
else
path = item.url;
attachments.Add(new Models.DoculinkAttachments { docName = UserfileName, Path = path,IsAttachments=item.IsAttachments,CustomOrder=item.CustomOrder });
attachments.Add(new Models.DoculinkAttachments { docName = UserfileName, Path = path,IsAttachments=item.IsAttachments,CustomOrder=item.CustomOrder,Language=item.Language });
}
Models.Doculink Documents = new Models.Doculink()
{
Id = documentInfo.Id,
linkTypeId = documentInfo.linkTypeId,
documentsTranslations=documentInfo.documentsTranslations,
IsActive = true,
IsActive = documentInfo.IsActive,
IsDeleted=false,
CustomOrder = documentInfo.CustomOrder,
doclinksAttachments = attachments

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -6,6 +6,12 @@
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
//"DoculinConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;",
//"DoculinConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;"
"DoculinConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;"
},
"Fileupload": {
"folderpath": "DASA_Documents/Active",
"Deletepath": "DASA_Documents/Deleted"

View File

@ -12,8 +12,18 @@
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

View File

@ -1,7 +1,9 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Employees.Db
{
[Table("Employees")]
public class Employee
{
[Key]

View File

@ -4,18 +4,23 @@ namespace DamageAssesment.Api.Employees.Db
{
public class EmployeeDbContext: DbContext
{
public DbSet<Db.Employee> Employees { get; set; }
public EmployeeDbContext(DbContextOptions options) : base(options)
private IConfiguration _Configuration { get; set; }
public EmployeeDbContext(DbContextOptions options, IConfiguration configuration) : base(options)
{
_Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(_Configuration.GetConnectionString("EmployeeConnection"));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Employee>()
.Property(item => item.Id)
.ValueGeneratedOnAdd();
}
public DbSet<Db.Employee> Employees { get; set; }
}
}

View File

@ -6,12 +6,18 @@ using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// CORS setup to allow requests from any origin.
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
// Add Swagger/OpenAPI documentation support.
builder.Services.AddSwaggerGen(c =>
{
// Include XML comments from your assembly
@ -24,9 +30,11 @@ builder.Services.AddScoped<IEmployeesProvider, EmployeesProvider>();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //4/30
builder.Services.AddDbContext<EmployeeDbContext>(option =>
{
option.UseInMemoryDatabase("Employees");
option.UseSqlServer("EmployeeConnection");
});
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
var app = builder.Build();
// Configure the HTTP request pipeline.
@ -43,6 +51,11 @@ if (app.Environment.IsDevelopment())
}
}
app.UseCors("DamageAppCorsPolicy");
// Enable CORS, authentication, and authorization middleware.
app.UseCors("DamageAppCorsPolicy");
app.UseAuthorization();
app.MapControllers();

View File

@ -77,7 +77,8 @@ namespace DamageAssesment.Api.Employees.Providers
EmployeeDbContext.Employees.Add(_employee);
Employee.Id = _employee.Id;
EmployeeDbContext.SaveChanges();
return (true, Employee, null);
//return (true, Employee, null);
return (true, mapper.Map<Db.Employee, Models.Employee>(_employee), null);
}
return (false, null, "Employee code is already exits");
}

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -13,5 +13,11 @@
"endpoint1": "xxx",
"endpoint2": "xxx",
"endpoint3": "xxx"
},
"ConnectionStrings": {
//"EmployeeConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;",
//"EmployeeConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;"
"EmployeeConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;"
}
}

View File

@ -11,6 +11,17 @@
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.5" />

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Locations.Db
{
[Table("Locations")]
public class Location
{
[Key]

View File

@ -4,6 +4,16 @@ namespace DamageAssesment.Api.Locations.Db
{
public class LocationDbContext : DbContext
{
private IConfiguration _Configuration { get; set; }
public LocationDbContext(DbContextOptions options, IConfiguration configuration) : base(options)
{
_Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(_Configuration.GetConnectionString("LocationConnection"));
}
public DbSet<Db.Location> Locations { get; set; }
public DbSet<Db.Region> Regions { get; set; }
public LocationDbContext(DbContextOptions options) : base(options)

View File

@ -1,7 +1,9 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Locations.Db
{
[Table("Regions")]
public class Region
{
[Key]

View File

@ -5,13 +5,18 @@ using Microsoft.EntityFrameworkCore;
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
// CORS setup to allow requests from any origin.
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
// Add services to the container.
// Add controller services and API Explorer for endpoint discovery.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
// Add Swagger/OpenAPI documentation support.
builder.Services.AddSwaggerGen(c =>
{
// Include XML comments from your assembly
@ -24,8 +29,11 @@ builder.Services.AddScoped<IRegionsProvider, RegionsProvider>();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //4/30
builder.Services.AddDbContext<LocationDbContext>(option =>
{
option.UseInMemoryDatabase("Locations");
option.UseSqlServer("LocationConnection");
});
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
var app = builder.Build();
// Configure the HTTP request pipeline.
@ -44,6 +52,11 @@ if (app.Environment.IsDevelopment())
}
}
app.UseCors("DamageAppCorsPolicy");
// Enable CORS, authentication, and authorization middleware.
app.UseCors("DamageAppCorsPolicy");
app.UseAuthorization();
app.MapControllers();

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -8,5 +8,11 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ConnectionStrings": {
//"LocationConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;",
// "LocationConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;"
"LocationConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;"
}
}

View File

@ -1,4 +1,5 @@
using DamageAssesment.Api.Questions.Interfaces;
using DamageAssesment.Api.Questions.Models;
using Microsoft.AspNetCore.Mvc;
namespace DamageAssesment.Api.Questions.Controllers
@ -109,6 +110,26 @@ namespace DamageAssesment.Api.Questions.Controllers
return CreatedAtRoute("DefaultApi",questions);
}
/// <summary>
/// PUT request for update a multiple question (multilingual) for survey.
/// </summary>
[HttpPut("questions/multiple/{surveyid}")]
public async Task<IActionResult> CreateQuestions(int surveyid, List<Models.Question> questions)
{
if (questions != null)
{
var result = await this.questionsProvider.PutQuestionsAsync(surveyid,questions);
if (result.IsSuccess)
{
return Ok(result.Question);
}
if (result.ErrorMessage == "Not Found")
return NotFound(result.ErrorMessage);
return BadRequest(result.ErrorMessage);
}
return CreatedAtRoute("DefaultApi", questions);
}
/// <summary>
/// POST request for creating a new question (multilingual).
/// </summary>

View File

@ -11,6 +11,17 @@
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.5" />

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace DamageAssesment.Api.Questions.Db
{
[Table("QuestionCategoryTrans")]
public class CategoryTranslation
{
[Key]

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Questions.Db
{
[Table("Questions")]
public class Question
{
[Key]

View File

@ -1,8 +1,10 @@
using System.Buffers.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Questions.Db
{
[Table("QuestionCategories")]
public class QuestionCategory
{
[Key]

View File

@ -6,6 +6,16 @@ namespace DamageAssesment.Api.Questions.Db
{
public class QuestionDbContext : DbContext
{
private IConfiguration _Configuration { get; set; }
public QuestionDbContext(DbContextOptions options, IConfiguration configuration) : base(options)
{
_Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(_Configuration.GetConnectionString("QuestionConnection"));
}
public DbSet<Db.Question> Questions { get; set; }
public DbSet<Db.QuestionType> QuestionTypes { get; set; }
public DbSet<Db.QuestionsTranslation> QuestionsTranslations { get; set; }

View File

@ -1,7 +1,9 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Questions.Db
{
[Table("QuestionTypes")]
public class QuestionType
{
[Key]

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Questions.Db
{
[Table("QuestionTrans")]
public class QuestionsTranslation
{
[Key]

View File

@ -9,6 +9,7 @@ namespace DamageAssesment.Api.Questions.Interfaces
Task<(bool IsSuccess, List<SurveyQuestions> SurveyQuestions, string ErrorMessage)> GetSurveyQuestionAsync(int surveyId,string language);
Task<(bool IsSuccess, Models.MultiLanguage Question, string ErrorMessage)> PostQuestionAsync(Models.Question Question);
Task<(bool IsSuccess, IEnumerable<Models.MultiLanguage> Question, string ErrorMessage)> PostQuestionsAsync(List<Models.Question> Questions);
Task<(bool IsSuccess, IEnumerable<Models.MultiLanguage> Question, string ErrorMessage)> PutQuestionsAsync(int surveyId,List<Models.Question> Questions);
Task<(bool IsSuccess, Models.MultiLanguage Question, string ErrorMessage)> UpdateQuestionAsync(Models.Question Question);
Task<(bool IsSuccess, Models.MultiLanguage Question, string ErrorMessage)> DeleteQuestionAsync(int id);

View File

@ -5,6 +5,7 @@
public int CategoryId { get; set; }
public string IconName { get; set; }
public string IconLibrary { get; set; }
public object CategoryNames { get; set; }
public List<MultiLanguage> QuestionsText { get; set; }
}
}

View File

@ -15,8 +15,14 @@ builder.Services.AddControllers();
builder.Services.AddScoped<IQuestionsProvider, QuestionsProvider>();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
// CORS setup to allow requests from any origin.
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
// Add controller services and API Explorer for endpoint discovery.
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
// Add Swagger/OpenAPI documentation support.
builder.Services.AddSwaggerGen(c =>
{
// Include XML comments from your assembly
@ -26,8 +32,11 @@ builder.Services.AddSwaggerGen(c =>
});
builder.Services.AddDbContext<QuestionDbContext>(option =>
{
option.UseInMemoryDatabase("Questions");
option.UseSqlServer("QuestionConnection");
});
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
var app = builder.Build();
// Configure the HTTP request pipeline.
@ -44,6 +53,9 @@ if (app.Environment.IsDevelopment())
}
}
// Enable CORS, authentication, and authorization middleware.
app.UseCors("DamageAppCorsPolicy");
app.UseAuthorization();
app.MapControllers();

View File

@ -31,8 +31,7 @@ namespace DamageAssesment.Api.Questions.Providers
questionDbContext.QuestionTypes.Add(new Db.QuestionType() { TypeText = "TextBox" });
questionDbContext.SaveChanges();
}
if (!questionDbContext.QuestionCategories.Any())
if (!questionDbContext.QuestionsTranslations.Any())
{
questionDbContext.QuestionCategories.Add(new Db.QuestionCategory() { IconName = "Flooding", IconLibrary = "https://example.com/images/img1.png" });
questionDbContext.QuestionCategories.Add(new Db.QuestionCategory() { IconName = "Electrical", IconLibrary = "https://example.com/images/img2.png" });
@ -65,14 +64,51 @@ namespace DamageAssesment.Api.Questions.Providers
if (!questionDbContext.Questions.Any())
{
var question1 = new Db.Question() { QuestionTypeId = 1, SurveyId = 1, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId = 1 };
var question2 = new Db.Question() { QuestionTypeId = 1, SurveyId = 1, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 1 };
var question2 = new Db.Question() { QuestionTypeId = 1, SurveyId = 1, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 2 };
var question3 = new Db.Question() { QuestionTypeId = 1, SurveyId = 2, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId = 1 };
var question4 = new Db.Question() { QuestionTypeId = 1, SurveyId = 2, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 1 };
var question4 = new Db.Question() { QuestionTypeId = 1, SurveyId = 2, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 2 };
var question5 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId = 1 };
var question6 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 2 };
var question7 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId = 3};
var question8 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 4 };
var question9 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = true, Key = true, CategoryId = 5 };
var question10 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = false, Key = true, CategoryId = 1 };
var question11 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = false, Key = false, CategoryId = 2 };
var question12 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = true, Key = true, CategoryId = 3 };
var question13 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId = 4 };
var question14 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 5 };
var question15 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = false, Key = false, CategoryId = 1 };
var question16 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = true, Key = true, CategoryId = 2 };
var question17 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = false, Key = false, CategoryId = 3 };
var question18 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 4 };
var question19 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId = 5 };
var question20 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = true, Key = false, CategoryId = 1 };
var question21 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId = 2 };
var question22 = new Db.Question() { QuestionTypeId = 1, SurveyId = 3, QuestionNumber = 2, IsRequired = false, Comment = true, Key = true, CategoryId = 3 };
questionDbContext.Questions.Add(question1);
questionDbContext.Questions.Add(question2);
questionDbContext.Questions.Add(question3);
questionDbContext.Questions.Add(question4);
questionDbContext.Questions.Add(question5);
questionDbContext.Questions.Add(question6);
questionDbContext.Questions.Add(question7);
questionDbContext.Questions.Add(question8);
questionDbContext.Questions.Add(question9);
questionDbContext.Questions.Add(question10);
questionDbContext.Questions.Add(question11);
questionDbContext.Questions.Add(question12);
questionDbContext.Questions.Add(question13);
questionDbContext.Questions.Add(question14);
questionDbContext.Questions.Add(question15);
questionDbContext.Questions.Add(question16);
questionDbContext.Questions.Add(question17);
questionDbContext.Questions.Add(question18);
questionDbContext.Questions.Add(question19);
questionDbContext.Questions.Add(question20);
questionDbContext.Questions.Add(question21);
questionDbContext.Questions.Add(question22);
questionDbContext.SaveChanges();
}
@ -90,6 +126,64 @@ namespace DamageAssesment.Api.Questions.Providers
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 4, QuestionText = "Are the grounds flooded ?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 4, QuestionText = "Les terrains sont-ils inondés ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 4, QuestionText = "¿Están inundados los terrenos?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 5, QuestionText = "Can you open?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 6, QuestionText = "Is debris blocking access?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 7, QuestionText = "Are the grounds flooded?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 8, QuestionText = "Is the access blocked by flooding?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 9, QuestionText = "Are any utility wires down?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 10, QuestionText = "Do you have damage to windows, doors, or walls?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 11, QuestionText = "Do you have roof damage?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 12, QuestionText = "Do you have major water intrusion?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 13, QuestionText = "Are any portable classrooms damaged and unusable?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 14, QuestionText = "Does your facility need to be secured/boarded?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 15, QuestionText = "Are you without commercial power?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 16, QuestionText = "Are you without water pressure?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 17, QuestionText = "Are you without telephones?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 18, QuestionText = "Are traffic signals damaged/missing?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 19, QuestionText = "Are you without an operable fire alarm?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 20, QuestionText = "Are you without an operable public address?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 21, QuestionText = "Do you have major debris?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 22, QuestionText = "Are there any problems or issues not addressed above that would impede you from opening? If yes, please explain below?", Language = "en" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 5, QuestionText = "Pouvez-vous ouvrir ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 6, QuestionText = "Est-ce que des débris bloquent l'accès ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 7, QuestionText = "Les terrains sont-ils inondés ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 8, QuestionText = "L'accès est-il bloqué par des inondations ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 9, QuestionText = "Des câbles d'utilité sont-ils tombés ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 10, QuestionText = "Avez-vous des dommages aux fenêtres, portes ou murs ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 11, QuestionText = "Avez-vous des dommages au toit ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 12, QuestionText = "Avez-vous une intrusion d'eau majeure ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 13, QuestionText = "Les salles de classe portables sont-elles endommagées et inutilisables ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 14, QuestionText = "Votre établissement a-t-il besoin d'être sécurisé/protégé ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 15, QuestionText = "Êtes-vous sans alimentation électrique commerciale ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 16, QuestionText = "Êtes-vous sans pression d'eau ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 17, QuestionText = "Êtes-vous sans téléphones ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 18, QuestionText = "Les feux de circulation sont-ils endommagés/absents ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 19, QuestionText = "N'avez-vous pas d'alarme incendie fonctionnelle ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 20, QuestionText = "N'avez-vous pas de système de sonorisation opérationnel ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 21, QuestionText = "Avez-vous une grande quantité de débris ?", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 22, QuestionText = "Y a-t-il des problèmes ou des problèmes non abordés ci-dessus qui vous empêcheraient d'ouvrir ? Si oui, veuillez expliquer ci-dessous.", Language = "fr" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 5, QuestionText = "¿Puedes abrir ?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 6, QuestionText = "¿Los escombros bloquean el acceso?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 7, QuestionText = "¿Están inundados los terrenos?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 8, QuestionText = "¿El acceso está bloqueado por inundaciones?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 9, QuestionText = "¿Hay cables de utilidad caídos?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 10, QuestionText = "¿Tienes daños en ventanas, puertas o paredes?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 11, QuestionText = "¿Tienes daños en el techo?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 12, QuestionText = "¿Tienes una gran intrusión de agua?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 13, QuestionText = "¿Hay aulas portátiles dañadas e inutilizables?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 14, QuestionText = "¿Tu instalación necesita ser asegurada/tabicada?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 15, QuestionText = "¿No tienes energía comercial?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 16, QuestionText = "¿No tienes presión de agua?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 17, QuestionText = "¿No tienes teléfonos?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 18, QuestionText = "¿Los semáforos están dañados/faltan?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 19, QuestionText = "¿No tienes una alarma de incendios operativa?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 20, QuestionText = "¿No tienes un sistema de megafonía operativo?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 21, QuestionText = "¿Tienes una gran cantidad de escombros?", Language = "es" });
questionDbContext.QuestionsTranslations.Add(new Db.QuestionsTranslation() { QuestionId = 22, QuestionText = "¿Hay algún problema o asunto no abordado anteriormente que le impida abrir? Si es así, por favor explíquelo a continuación.", Language = "es" });
questionDbContext.SaveChanges();
}
}
@ -219,6 +313,7 @@ namespace DamageAssesment.Api.Questions.Providers
CategoryId = item.Id,
IconLibrary = item.IconLibrary,
IconName = item.IconName,
CategoryNames= CreateCategoryMultiLanguageObject(GetCategoryTranslations(item.Id, language)),
QuestionsText = GetSurveyQuestion(mapper.Map<List<Db.Question>, List<Models.MultiLanguage>>(questions.Where(a => a.CategoryId == item.Id).ToList()), language)
});
}
@ -254,6 +349,7 @@ namespace DamageAssesment.Api.Questions.Providers
var dbquestiontranslation = mapper.Map<List<Models.QuestionsTranslation>, List<Db.QuestionsTranslation>>(Question.Questions);
dbquestion.QuestionTypeId = questionDbContext.QuestionTypes.Where(a => a.TypeText == Question.TypeText).Select(a => a.Id).FirstOrDefault();
questionDbContext.Questions.Add(dbquestion);
questionDbContext.SaveChanges();
dbquestiontranslation.ForEach(i => i.QuestionId = dbquestion.Id);
questionDbContext.QuestionsTranslations.AddRange(dbquestiontranslation);
questionDbContext.SaveChanges();
@ -280,6 +376,36 @@ namespace DamageAssesment.Api.Questions.Providers
return (false, null, ex.Message);
}
}
public async Task<(bool IsSuccess, IEnumerable<Models.MultiLanguage> Question, string ErrorMessage)> PutQuestionsAsync(int surveyId, List<Models.Question> Questions)
{
try
{
var questions=await questionDbContext.Questions.AsNoTracking().Where(a=>a.SurveyId == surveyId).ToListAsync();
if (questions != null)
{
List<int> questionids=questions.Select(a=>a.Id).ToList();
var questiontrans = await questionDbContext.QuestionsTranslations.AsNoTracking().Where(x => questionids.Contains(x.QuestionId)).ToListAsync();
if (questiontrans != null)
questionDbContext.QuestionsTranslations.RemoveRange(questiontrans);
questionDbContext.Questions.RemoveRange(questions);
questionDbContext.SaveChanges();
}
List<Models.MultiLanguage> results = new List<MultiLanguage>();
logger?.LogInformation("Query Question");
foreach (Models.Question Question in Questions)
{
Question.SurveyId = surveyId;
results.Add(InsertQuestion(Question));
}
return (true, results, null);
}
catch (Exception ex)
{
logger?.LogError(ex.ToString());
return (false, null, ex.Message);
}
}
public async Task<(bool IsSuccess, Models.MultiLanguage Question, string ErrorMessage)> UpdateQuestionAsync(Models.Question Question)
{
try
@ -313,8 +439,11 @@ namespace DamageAssesment.Api.Questions.Providers
if (question != null)
{
var questiontrans=await questionDbContext.QuestionsTranslations.AsNoTracking().Where(x=>x.QuestionId== id).ToListAsync();
var result = mapper.Map<Db.Question, Models.MultiLanguage>(question);
result.Text = CreateMultiLanguageObject(GetQuestionsTranslations(result.Id, ""));
if(questiontrans!=null)
questionDbContext.QuestionsTranslations.RemoveRange(questiontrans);
questionDbContext.Questions.Remove(question);
questionDbContext.SaveChanges();
return (true, result, $"QuestionID {id} deleted Successfuly");

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -8,5 +8,11 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ConnectionStrings": {
//"QuestionConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;"
// "QuestionConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;"
"QuestionConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;"
}
}

View File

@ -10,7 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="xunit" Version="2.4.2" />

View File

@ -11,7 +11,21 @@
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="EPPlus" Version="7.0.0" />
<PackageReference Include="ClosedXML" Version="0.102.1" />
<PackageReference Include="EPPlus" Version="6.2.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="7.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.5" />

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace DamageAssesment.Api.Responses.Db
{
[Table("SurveyResponses")]
public class SurveyResponse
{
[Key]

View File

@ -4,12 +4,17 @@ namespace DamageAssesment.Api.Responses.Db
{
public class SurveyResponseDbContext:DbContext
{
public DbSet<Db.SurveyResponse> SurveyResponses { get; set; }
public SurveyResponseDbContext(DbContextOptions options) : base(options)
private IConfiguration _Configuration { get; set; }
public SurveyResponseDbContext(DbContextOptions options, IConfiguration configuration) : base(options)
{
_Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(_Configuration.GetConnectionString("ResponsesConnection"));
}
public DbSet<Db.SurveyResponse> SurveyResponses { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{

View File

@ -16,6 +16,10 @@ const int intervalForCircuitBraker = 5; //5 seconds
// Add services to the container.
builder.Services.AddControllers();
// CORS setup to allow requests from any origin.
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddScoped<ISurveysResponse, SurveyResponsesProvider>();
@ -36,6 +40,7 @@ builder.Services.AddHttpClient<IHttpUtil, HttpUtil>().
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
// Add Swagger/OpenAPI documentation support.
builder.Services.AddSwaggerGen(c =>
{
// Include XML comments from your assembly
@ -45,8 +50,11 @@ builder.Services.AddSwaggerGen(c =>
});
builder.Services.AddDbContext<SurveyResponseDbContext>(option =>
{
option.UseInMemoryDatabase("Responses");
option.UseSqlServer("ResponsesConnection");
});
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
var app = builder.Build();
// Configure the HTTP request pipeline.
@ -56,6 +64,7 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI();
}
app.UseCors("DamageAppCorsPolicy");
app.UseAuthorization();
app.MapControllers();

View File

@ -1,16 +1,16 @@
using DamageAssesment.Api.Responses.Interfaces;
using ClosedXML.Excel;
using DamageAssesment.Api.Responses.Interfaces;
using DamageAssesment.Api.Responses.Models;
using OfficeOpenXml;
using System.Collections.Generic;
using System.ComponentModel;
namespace DamageAssesment.Api.Responses.Providers
{
public class ExcelExportService : IExcelExportService
public class ExcelExportService: IExcelExportService
{
public byte[] ExportToExcel<T1>(List<object> responses)
{
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (var package = new ExcelPackage())
{
// Create the first worksheet and populate it with responses
@ -29,7 +29,7 @@ namespace DamageAssesment.Api.Responses.Providers
for (int col = 1; col <= properties.Length; col++)
{
worksheet.Cells[1, col].Value = properties[col - 1].Name;
if (properties[col - 1].Name.ToLower().Contains("attachment"))
if(properties[col - 1].Name.ToLower().Contains("attachment"))
IsAttchments.Add(col);
}
@ -39,7 +39,7 @@ namespace DamageAssesment.Api.Responses.Providers
for (int col = 1; col <= properties.Length; col++)
{
string value = Convert.ToString(properties[col - 1].GetValue(data[row - 2]));
string value = Convert.ToString(properties[col - 1].GetValue(data[row - 2]));
if (IsAttchments.Where(a => a == col).Count() > 0 && !string.IsNullOrEmpty(value))
{
List<string> attachments = value.Split("##").ToList();

View File

@ -56,16 +56,20 @@ namespace DamageAssesment.Api.Responses.Providers
try
{
logger?.LogInformation("Querying to get SurveyResponse object from DB");
IQueryable<Db.SurveyResponse> listSurveyResponse = null;
List<Db.SurveyResponse> listSurveyResponse = null;
if (employeeid == 0)
{
listSurveyResponse = surveyResponseDbContext.SurveyResponses.Where(s => s.SurveyId == surveyId);
listSurveyResponse = surveyResponseDbContext.SurveyResponses.Where(s => s.SurveyId == surveyId).ToList();
}
else
{
listSurveyResponse = surveyResponseDbContext.SurveyResponses.Where(s => s.SurveyId == surveyId && s.EmployeeId == employeeid);
listSurveyResponse = surveyResponseDbContext.SurveyResponses.Where(s => s.SurveyId == surveyId && s.EmployeeId == employeeid).ToList();
}
listSurveyResponse = listSurveyResponse
.OrderByDescending(obj => obj.Id)
.GroupBy(obj => new { obj.SurveyId, obj.LocationId })//obj.EmployeeId,
.Select(group => group.FirstOrDefault()) // or .FirstOrDefault() if you want to handle empty groups
.ToList();
if (listSurveyResponse.Any())
{
var answers = await getAnswersByRegionAndSurveyIdAsync(listSurveyResponse);
@ -417,14 +421,13 @@ namespace DamageAssesment.Api.Responses.Providers
}
//Method to get Answers by region with surveyId as input parameter
private async Task<dynamic> getAnswersByRegionAndSurveyIdAsync(IQueryable<Db.SurveyResponse> surveyResponses)
private async Task<dynamic> getAnswersByRegionAndSurveyIdAsync(List<Db.SurveyResponse> surveyResponses)
{
try
{
var answersList = await answerServiceProvider.getAnswersAsync();
if (answersList == null || !answersList.Any())
return null;
//get all the answers for the particular survey
var surveyAnswers = answersList.Join(
surveyResponses,
@ -565,7 +568,11 @@ namespace DamageAssesment.Api.Responses.Providers
surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId && x.EmployeeId == employeeid).ToListAsync();
employee = await employeeServiceProvider.getEmployeeAsync(employeeid);
}
surveyResonses = surveyResonses
.OrderByDescending(obj => obj.Id)
.GroupBy(obj => new { obj.SurveyId, obj.LocationId })//obj.EmployeeId,
.Select(group => group.FirstOrDefault()) // or .FirstOrDefault() if you want to handle empty groups
.ToList();
var answers = await answerServiceProvider.getAnswersAsync();
var questions = await questionServiceProvider.getQuestionsAsync(null);
var Locations = await locationServiceProvider.getLocationsAsync();
@ -586,18 +593,18 @@ namespace DamageAssesment.Api.Responses.Providers
r.LocationId,
r.EmployeeId,
r.ClientDevice,
r.KeyAnswerResult,
// r.KeyAnswerResult,
loc.DataValue,
loc.Enrollment,
loc.Longitute,
loc.Latitude,
Employee = (from e in employees where e.Id == r.EmployeeId select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(),
// Employee = (from e in employees where e.Id == r.EmployeeId select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(),
answers = from ans in answers
where ans.SurveyResponseId == r.Id
select new
{
ans.Id,
ans.QuestionId,
// ans.QuestionId,
ans.AnswerText,
ans.Comment,
Questions = (from q in surveyQuestions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(),
@ -623,18 +630,18 @@ namespace DamageAssesment.Api.Responses.Providers
r.LocationId,
r.EmployeeId,
r.ClientDevice,
r.KeyAnswerResult,
// r.KeyAnswerResult,
loc.DataValue,
loc.Enrollment,
loc.Longitute,
loc.Latitude,
Employee = _employee,
// Employee = _employee,
answers = from ans in answers
where ans.SurveyResponseId == r.Id
select new
{
ans.Id,
ans.QuestionId,
// ans.QuestionId,
ans.AnswerText,
ans.Comment,
Questions = (from q in questions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(),
@ -693,18 +700,18 @@ namespace DamageAssesment.Api.Responses.Providers
r.LocationId,
r.EmployeeId,
r.ClientDevice,
r.KeyAnswerResult,
// r.KeyAnswerResult,
loc.DataValue,
loc.Enrollment,
loc.Longitute,
loc.Latitude,
Employee = employeeid != 0 ? _employee : (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(),
// Employee = employeeid != 0 ? _employee : (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(),
answers = from ans in answers
where ans.SurveyResponseId == r.Id
select new
{
ans.Id,
ans.QuestionId,
// ans.QuestionId,
ans.AnswerText,
ans.Comment,
Questions = (from q in questions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(),
@ -945,7 +952,11 @@ namespace DamageAssesment.Api.Responses.Providers
_employee = new { employee.Id, employee.Name, employee.BirthDate, employee.Email, employee.OfficePhoneNumber };
}
}
surveyResonses = surveyResonses
.OrderByDescending(obj => obj.Id)
.GroupBy(obj => new { obj.SurveyId, obj.LocationId }) //obj.EmployeeId,
.Select(group => group.FirstOrDefault()) // or .FirstOrDefault() if you want to handle empty groups
.ToList();
var answers = await answerServiceProvider.getAnswersAsync();
var questions = await questionServiceProvider.getQuestionsAsync(null);
var surveyQuestions = from q in questions where q.SurveyId == surveyId select q;
@ -961,18 +972,18 @@ namespace DamageAssesment.Api.Responses.Providers
r.LocationId,
r.EmployeeId,
r.ClientDevice,
r.KeyAnswerResult,
// r.KeyAnswerResult,
loc.DataValue,
loc.Enrollment,
loc.Longitute,
loc.Latitude,
Employee = employeeid != 0 ? _employee : (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(),
// Employee = employeeid != 0 ? _employee : (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(),
answers = from ans in answers
where ans.SurveyResponseId == r.Id
select new
{
ans.QuestionId,
// ans.QuestionId,
ans.Id,
ans.AnswerText,
ans.Comment,
@ -1016,7 +1027,11 @@ namespace DamageAssesment.Api.Responses.Providers
_employee = new { employee.Id, employee.Name, employee.BirthDate, employee.Email, employee.OfficePhoneNumber };
}
}
surveyResponses = surveyResponses
.OrderByDescending(obj => obj.Id)
.GroupBy(obj => new { obj.SurveyId, obj.LocationId })//, obj.EmployeeId
.Select(group => group.FirstOrDefault()) // or .FirstOrDefault() if you want to handle empty groups
.ToList();
//var surveyResponses = await surveyResponseDbContext.Responses.Where(x => x.SurveyId == survey.Id).ToListAsync();
// var employees = await employeeServiceProvider.getEmployeesAsync();
var answers = await answerServiceProvider.getAnswersAsync();
@ -1031,12 +1046,12 @@ namespace DamageAssesment.Api.Responses.Providers
r.LocationId,
r.EmployeeId,
r.ClientDevice,
r.KeyAnswerResult,
// r.KeyAnswerResult,
loc.DataValue,
loc.Enrollment,
loc.Longitute,
loc.Latitude,
Employee = employeeid != 0 ? _employee : (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(),
// Employee = employeeid != 0 ? _employee : (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(),
answers = from ans in answers
where ans.SurveyResponseId == r.Id
&& ans.QuestionId == question.Id
@ -1044,7 +1059,7 @@ namespace DamageAssesment.Api.Responses.Providers
select new
{
ans.QuestionId,
// ans.QuestionId,
AnswerId = ans.Id,
ans.AnswerText,
ans.Comment,

View File

@ -25,6 +25,7 @@
"AttachmentUrlBase": "http://damageassesment.api.attachments:80",
"SurveyUrlBase": "http://damageassesment.api.surveys:80"
},
"RessourceSettings": {
"Employee": "/employees",
"EmployeeById": "/employees/{0}",
@ -39,5 +40,10 @@
"AnswerByResponse": "/answers/byresponse/{0}",
"Location": "/locations",
"Region": "/regions"
},
"ConnectionStrings": {
//"SurveyResponseConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;"
//"ResponsesConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;"
"ResponsesConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;"
}
}

View File

@ -0,0 +1,55 @@
// <auto-generated />
using DamageAssesment.Api.SurveyResponses.Db;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace DamageAssesment.Api.SurveyResponses.Migrations
{
[DbContext(typeof(SurveyResponseDbContext))]
[Migration("20230817221348_InitialSurveyResponse")]
partial class InitialSurveyResponse
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("DamageAssesment.Api.SurveyResponses.Db.SurveyResponse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("EmployeeId")
.IsRequired()
.HasMaxLength(6)
.HasColumnType("nvarchar(6)");
b.Property<string>("LocationId")
.IsRequired()
.HasMaxLength(4)
.HasColumnType("nvarchar(4)");
b.Property<int>("SurveyId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("SurveyResponses");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DamageAssesment.Api.SurveyResponses.Migrations
{
/// <inheritdoc />
public partial class InitialSurveyResponse : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "SurveyResponses",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
SurveyId = table.Column<int>(type: "int", nullable: false),
LocationId = table.Column<string>(type: "nvarchar(4)", maxLength: 4, nullable: false),
EmployeeId = table.Column<string>(type: "nvarchar(6)", maxLength: 6, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_SurveyResponses", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "SurveyResponses");
}
}
}

View File

@ -0,0 +1,52 @@
// <auto-generated />
using DamageAssesment.Api.SurveyResponses.Db;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace DamageAssesment.Api.SurveyResponses.Migrations
{
[DbContext(typeof(SurveyResponseDbContext))]
partial class SurveyResponseDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("DamageAssesment.Api.SurveyResponses.Db.SurveyResponse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("EmployeeId")
.IsRequired()
.HasMaxLength(6)
.HasColumnType("nvarchar(6)");
b.Property<string>("LocationId")
.IsRequired()
.HasMaxLength(4)
.HasColumnType("nvarchar(4)");
b.Property<int>("SurveyId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("SurveyResponses");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -34,7 +34,55 @@ namespace DamageAssesment.Api.Surveys.Test
Assert.Equal(204, result.StatusCode);
}
[Fact(DisplayName = "Get active Surveys - Ok case")]
public async Task GetActiveSurveysAsync_ShouldReturnStatusCode200()
{
var mockSurveyService = new Mock<ISurveyProvider>();
var mockResponse = await MockData.getOkResponse();
mockSurveyService.Setup(service => service.GetActiveSurveysAsync(true,null)).ReturnsAsync(mockResponse);
var surveyProvider = new SurveysController(mockSurveyService.Object);
var result = (OkObjectResult)await surveyProvider.GetActiveSurveysAsync(null);
Assert.Equal(200, result.StatusCode);
}
[Fact(DisplayName = "Get active Surveys - NoContent Case")]
public async Task GetActiveSurveysAsync_ShouldReturnStatusCode204()
{
var mockSurveyService = new Mock<ISurveyProvider>();
var mockResponse = await MockData.getNoContentResponse();
mockSurveyService.Setup(service => service.GetActiveSurveysAsync(true,null)).ReturnsAsync(mockResponse);
var surveyProvider = new SurveysController(mockSurveyService.Object);
var result = (NoContentResult)await surveyProvider.GetActiveSurveysAsync(null);
Assert.Equal(204, result.StatusCode);
}
[Fact(DisplayName = "Get inactive Surveys - Ok case")]
public async Task GetInActiveSurveysAsync_ShouldReturnStatusCode200()
{
var mockSurveyService = new Mock<ISurveyProvider>();
var mockResponse = await MockData.getOkResponse();
mockSurveyService.Setup(service => service.GetActiveSurveysAsync(false, null)).ReturnsAsync(mockResponse);
var surveyProvider = new SurveysController(mockSurveyService.Object);
var result = (OkObjectResult)await surveyProvider.GetInActiveSurveysAsync(null);
Assert.Equal(200, result.StatusCode);
}
[Fact(DisplayName = "Get in active Surveys - NoContent Case")]
public async Task GetInActiveSurveysAsync_ShouldReturnStatusCode204()
{
var mockSurveyService = new Mock<ISurveyProvider>();
var mockResponse = await MockData.getNoContentResponse();
mockSurveyService.Setup(service => service.GetActiveSurveysAsync(false, null)).ReturnsAsync(mockResponse);
var surveyProvider = new SurveysController(mockSurveyService.Object);
var result = (NoContentResult)await surveyProvider.GetInActiveSurveysAsync(null);
Assert.Equal(204, result.StatusCode);
}
[Fact(DisplayName = "Get Survey by Id - Ok case")]
public async Task GetSurveyAsync_ShouldReturnStatusCode200()
{

View File

@ -27,7 +27,36 @@ namespace DamageAssesment.Api.Surveys.Controllers
}
return NoContent();
}
/// <summary>
/// GET request for retrieving all active surveys.
/// </summary>
[Route("surveys/active")]
[Route("surveys/active/{language:alpha}")]
[HttpGet]
public async Task<ActionResult> GetActiveSurveysAsync(string? language)
{
var result = await this.surveyProvider.GetActiveSurveysAsync(true,language);
if (result.IsSuccess)
{
return Ok(result.Surveys);
}
return NoContent();
}
/// <summary>
/// GET request for retrieving all inactive surveys.
/// </summary>
[Route("surveys/inactive")]
[Route("surveys/inactive/{language:alpha}")]
[HttpGet]
public async Task<ActionResult> GetInActiveSurveysAsync(string? language)
{
var result = await this.surveyProvider.GetActiveSurveysAsync(false, language);
if (result.IsSuccess)
{
return Ok(result.Surveys);
}
return NoContent();
}
/// <summary>
/// GET request for retrieving surveys by ID.
/// </summary>

View File

@ -11,6 +11,17 @@
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.5" />

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace DamageAssesment.Api.Surveys.Db
{
[Table("SurveyTrans")]
public class SurveyTranslation
{
[Key]

View File

@ -4,11 +4,18 @@ namespace DamageAssesment.Api.Surveys.Db
{
public class SurveysDbContext : DbContext
{
private IConfiguration _Configuration { get; set; }
public SurveysDbContext(DbContextOptions options, IConfiguration configuration) : base(options)
{
_Configuration = configuration;
}
public DbSet<Db.Survey> Surveys { get; set; }
public DbSet<Db.SurveyTranslation> SurveysTranslation { get; set; }
public SurveysDbContext(DbContextOptions options) : base(options)
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(_Configuration.GetConnectionString("SurveyConnection"));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{

View File

@ -3,6 +3,7 @@
public interface ISurveyProvider
{
Task<(bool IsSuccess, IEnumerable< Models.MultiLanSurvey> Surveys, string ErrorMessage)> GetSurveysAsync(string language);
Task<(bool IsSuccess, IEnumerable<Models.MultiLanSurvey> Surveys, string ErrorMessage)> GetActiveSurveysAsync(bool IsActive,string language);
Task<(bool IsSuccess, Models.MultiLanSurvey Surveys, string ErrorMessage)> GetSurveysAsync(int id, string language);
Task<(bool IsSuccess, Models.MultiLanSurvey Survey, string ErrorMessage)> PostSurveyAsync(Models.Survey Survey);
Task<(bool IsSuccess, Models.MultiLanSurvey Survey, string ErrorMessage)> PutSurveyAsync(int id, Models.Survey Survey);

View File

@ -10,7 +10,11 @@ using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Retrieve the security key for JWT token validation.
var authkey = builder.Configuration.GetValue<string>("JwtSettings:securitykey");
// Configure JWT authentication and validation.
builder.Services.AddAuthentication(item =>
{
item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
@ -29,12 +33,21 @@ builder.Services.AddAuthentication(item =>
};
});
//CORS setup to allow requests from any origin.
builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => {
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
}));
// Add controller services and API Explorer for endpoint discovery.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddScoped<ISurveyProvider, SurveysProvider>();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
// Add Swagger/OpenAPI documentation support.
builder.Services.AddSwaggerGen(c =>
{
// Include XML comments from your assembly
@ -42,10 +55,13 @@ builder.Services.AddSwaggerGen(c =>
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
// Configure the database context for SurveysDbContext using SQL Server.
builder.Services.AddDbContext<SurveysDbContext>(option =>
{
option.UseInMemoryDatabase("Surveys");
option.UseSqlServer("SurveyConnection");
});
var app = builder.Build();
// Configure the HTTP request pipeline.
@ -53,7 +69,7 @@ if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
// Seed initial data in the database when in development mode
using (var serviceScope = app.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
@ -61,10 +77,11 @@ if (app.Environment.IsDevelopment())
surveyProvider.seedData();
}
}
// Enable CORS, authentication, and authorization middleware.
app.UseCors("DamageAppCorsPolicy");
app.UseAuthentication();
app.UseAuthorization();
// Map controllers to their respective routes.
app.MapControllers();
app.Run();

View File

@ -85,7 +85,7 @@ namespace DamageAssesment.Api.Surveys.Providers
MultiLanguage = dict;
return MultiLanguage;
}
public string GetStatus(DateTime? StartDate, DateTime? EndDate)
public string GetStatus(DateTime? StartDate,DateTime? EndDate)
{
try
{
@ -101,6 +101,43 @@ namespace DamageAssesment.Api.Surveys.Providers
return SurveyStatus.INACTIVE.ToString();
}
}
// Method to get surveys asynchronously with multi-language support
public async Task<(bool IsSuccess, IEnumerable<Models.MultiLanSurvey> Surveys, string ErrorMessage)> GetActiveSurveysAsync(bool IsActive,string language)
{
IEnumerable<Models.MultiLanSurvey> surveysList = null;
try
{
string status = SurveyStatus.ACTIVE.ToString();
if(!IsActive) status = SurveyStatus.INACTIVE.ToString();
logger?.LogInformation("Get all Surveys from DB");
//checking is enabled in survey response
var surveys = await surveyDbContext.Surveys.ToListAsync();//Where(s => s.IsEnabled == true)
if (surveys != null)
{
surveysList = from s in surveys
select new Models.MultiLanSurvey
{
Id = s.Id,
StartDate = s.StartDate,
EndDate = s.EndDate,
IsEnabled = s.IsEnabled,
CreatedDate = s.CreatedDate,
Status = GetStatus(s.StartDate, s.EndDate),
Titles = CreateMultiLanguageObject(GetSurveyTranslations(s.Id, null, language))
};
logger?.LogInformation($"{surveys.Count} Items(s) found");
return (true, surveysList.Where(a=>a.Status==status).OrderByDescending(a=>a.Id), null);
}
return (false, null, "Not found");
}
catch (Exception ex)
{
logger?.LogError(ex.ToString());
return (false, null, ex.Message);
}
}
// Method to get surveys asynchronously with multi-language support
public async Task<(bool IsSuccess, IEnumerable<Models.MultiLanSurvey> Surveys, string ErrorMessage)> GetSurveysAsync(string language)
{
@ -121,7 +158,7 @@ namespace DamageAssesment.Api.Surveys.Providers
EndDate = s.EndDate,
IsEnabled = s.IsEnabled,
CreatedDate = s.CreatedDate,
Status = GetStatus(s.StartDate, s.EndDate),
Status= GetStatus(s.StartDate,s.EndDate),
Titles = CreateMultiLanguageObject(GetSurveyTranslations(s.Id, null, language))
};
@ -179,6 +216,11 @@ namespace DamageAssesment.Api.Surveys.Providers
{
if (survey != null)
{
if (survey.StartDate != null && survey.EndDate != null)
{
if(survey.StartDate.Value>survey.EndDate.Value)
return (false, null, $"Survey start date should be less than enddate");
}
survey.CreatedDate = DateTime.Now;
Db.Survey _survey = mapper.Map<Models.Survey, Db.Survey>(survey);
@ -215,6 +257,11 @@ namespace DamageAssesment.Api.Surveys.Providers
{
if (survey != null)
{
if (survey.StartDate != null && survey.EndDate != null)
{
if (survey.StartDate.Value > survey.EndDate.Value)
return (false, null, $"Survey start date should be less than enddate");
}
var _survey = await surveyDbContext.Surveys.AsNoTracking().Where(s => s.Id == Id).SingleOrDefaultAsync();
if (_survey != null)

View File

@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -8,5 +8,10 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ConnectionStrings": {
//"SurveyConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;"
//"SurveyConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;",
"SurveyConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;"
}
}

View File

@ -0,0 +1,147 @@
using DamageAssesment.Api.UsersAccess.Db;
using DamageAssesment.Api.UsersAccess.Interfaces;
using DamageAssesment.Api.UsersAccess.Providers;
using DamageAssesment.Api.UsersAccess.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Polly;
using DamageAssesment.Api.UsersAccess.Services;
using Microsoft.OpenApi.Models;
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
const int maxApiCallRetries = 3;
const int intervalToRetry = 2; //2 seconds
const int maxRetryForCircuitBraker = 5;
const int intervalForCircuitBraker = 5; //5 seconds
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var authkey = builder.Configuration.GetValue<string>("JwtSettings:securitykey");
builder.Services.AddAuthentication().
AddJwtBearer("DamageApp", item =>
{
item.RequireHttpsMetadata = true;
item.SaveToken = true;
item.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
};
}).AddJwtBearer("Dadeschools", options =>
{
options.Authority = builder.Configuration["Dadeschools:Authority"];
options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
options.TokenValidationParameters.ValidateAudience = false;
});
builder.Services.AddAuthorization(options =>
{
var DamageAppPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("DamageApp")
.Build();
var DadeschoolsPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("Dadeschools")
.Build();
var allPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("DamageApp", "Dadeschools")
.Build();
options.AddPolicy("DamageApp", DamageAppPolicy);
options.AddPolicy("Dadeschools", DadeschoolsPolicy);
options.AddPolicy("AllPolicies", allPolicy);
options.DefaultPolicy = options.GetPolicy("DamageApp")!;
});
var _jwtsettings = builder.Configuration.GetSection("JwtSettings");
builder.Services.Configure<JwtSettings>(_jwtsettings);
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddScoped<IUsersAccessProvider, UsersAccessProvider>();
builder.Services.AddScoped<ITokenServiceProvider, TokenServiceProvider>();
builder.Services.AddScoped<IEmployeeServiceProvider, EmployeeServiceProvider>();
builder.Services.AddHttpClient<IHttpUtil, HttpUtil>().
AddTransientHttpErrorPolicy(policy => policy.WaitAndRetryAsync(maxApiCallRetries, _ => TimeSpan.FromSeconds(intervalToRetry))).
AddTransientHttpErrorPolicy(policy => policy.CircuitBreakerAsync(maxRetryForCircuitBraker, TimeSpan.FromSeconds(intervalForCircuitBraker)));
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
builder.Services.AddSwaggerGen(options =>
{
// Include XML comments from your assembly
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
//options.IncludeXmlComments(xmlPath);
OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme()
{
Name = "Bearer",
BearerFormat = "JWT",
Scheme = "bearer",
Description = "Specify the authorization token.",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
};
options.AddSecurityDefinition("jwt_auth", securityDefinition);
// Make sure swagger UI requires a Bearer token specified
OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme()
{
Reference = new OpenApiReference()
{
Id = "jwt_auth",
Type = ReferenceType.SecurityScheme
}
};
OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement()
{
{securityScheme, new string[] { }},
};
options.AddSecurityRequirement(securityRequirements);
});
builder.Services.AddDbContext<UsersAccessDbContext>(option =>
{
option.UseInMemoryDatabase("UsersAccess");
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
using (var serviceScope = app.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
var usersAccessProvider = services.GetRequiredService<IUsersAccessProvider>();
usersAccessProvider.seedData();
}
}
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@ -11,6 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DamageAssesment.Api.Attachm
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4CB40DC2-D9D2-4384-A7A6-9968F5C777A2}"
ProjectSection(SolutionItems) = preProject
..\..\..\..\Sample\Migrations.ps1 = ..\..\..\..\Sample\Migrations.ps1
ReadMe.txt = ReadMe.txt
ReadMe4Dev.txt = ReadMe4Dev.txt
EndProjectSection

View File

@ -1,18 +0,0 @@
trigger:
- '*'
pr:
- '*'
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
- script: |
#!/bin/bash
chmod +x ./Scripts/build_and_push_services2acr.sh
./Scripts/build_and_push_services2acr.sh
displayName: 'Run build_and_push_services2acr.sh'

View File

@ -0,0 +1,75 @@
version: '3.4'
services:
damageassesment.api.answers:
image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapianswers
build:
context: .
dockerfile: DamageAssesment.Api.Answers/Dockerfile
ports:
- "6001:80"
command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapianswers"
damageassesment.api.attachments:
image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapiattachments
build:
context: .
dockerfile: DamageAssesment.Api.Attachments/Dockerfile
ports:
- "6001:80"
command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapiattachments"
damageassesment.api.employees:
image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapiemployees
build:
context: .
dockerfile: DamageAssesment.Api.Employees/Dockerfile
ports:
- "6003:80"
command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapiemployees"
damageassesment.api.locations:
image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapilocations
build:
context: .
dockerfile: DamageAssesment.Api.Locations/Dockerfile
ports:
- "6004:80"
command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapilocations"
damageassesment.api.questions:
image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapiquestions
build:
context: .
dockerfile: DamageAssesment.Api.Questions/Dockerfile
ports:
- "6005:80"
command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapiquestions"
damageassesment.api.surveys:
image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapisurveys
build:
context: .
dockerfile: DamageAssesment.Api.Surveys/Dockerfile
ports:
- "6006:80"
command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapisurveys"
damageassesment.api.doculinks:
image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapidoculinks
build:
context: .
dockerfile: DamageAssesment.Api.DocuLinks/Dockerfile
ports:
- "6008:80"
command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapidoculinks"
damageassesment.api.responses:
image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapiresponses
build:
context: .
dockerfile: DamageAssesment.Api.Responses/Dockerfile
ports:
- "6007:80"
command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapiresponses"

View File

@ -9,6 +9,7 @@
<DockerServiceName>damageassesment.api.answers</DockerServiceName>
</PropertyGroup>
<ItemGroup>
<None Include="docker-compos.tst.yml" />
<None Include="docker-compose.sql.yml" />
<None Include="docker-compose.asf.yml" />
<None Include="docker-compose.override.yml">

View File

@ -1,78 +1,13 @@
version: '3.4'
services:
answers:
image: santhoshsnair/damageassesmentapianswers:latest
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "6001:80"
attachments:
image: santhoshsnair/damageassesmentapiattachments:latest
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "6002:80"
employees:
image: santhoshsnair/damageassesmentapiemployees:latest
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "6003:80"
locations:
image: santhoshsnair/damageassesmentapilocations:latest
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "6004:80"
questions:
image: santhoshsnair/damageassesmentapiquestions:latest
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "6005:80"
responses:
image: santhoshsnair/damageassesmentapisurveyresponses:latest
environment:
- ASPNETCORE_ENVIRONMENT=Development
- services__Answers=http://10.0.0.4:19081/dasapp/answers/
- services__Locations=http://10.0.0.4:19081/dasapp/locations/
- services__Questions=http://10.0.0.4:19081/dasapp/questions/
- services__Employees=http://10.0.0.4:19081/dasapp/employees/
- services__Attachments=http://10.0.0.4:19081/dasapp/attachments/
- services__Surveys=http://10.0.0.4:19081/dasapp/survey/
ports:
- "6006:80"
surveys:
image: santhoshsnair/damageassesmentapisurveys:latest
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "6007:80"
doculinks:
image: santhoshsnair/damageassesmentapidoculinks:latest
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "6009:80"
sqlserver:
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
- SA_PASSWORD=your_password
- SA_PASSWORD=Test123
- ACCEPT_EULA=Y
ports:
- "1433:1433"
volumes:
- ./data:/var/opt/mssql # Mount a volume to persist data

View File

@ -1,30 +0,0 @@
# powershell -ExecutionPolicy Bypass -File .\build_and_push_services2acr.ps1
# Specify the path to your docker-compose.yml
$composeFile = "C:\Users\santh\OneDrive\Desktop\DOCKERS\ubuntu\Sprint6\C1011\Backend-API-Services\DamageAssesmentApi\docker-compose.yml"
# List of services to build, tag, and push
$services = @(
"damageassesmentapianswers",
"damageassesmentapiattachments",
"damageassesmentapiemployees",
"damageassesmentapilocations",
"damageassesmentapiquestions",
"damageassesmentapisurveys",
"damageassesmentapidoculinks",
"damageassesmentapiresponses"
)
# Log in to ACR (replace ACR_USERNAME and ACR_PASSWORD)
docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegistry -p k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn
# Loop through the services and build, tag, and push
foreach ($service in $services) {
# Build the service
docker-compose -f $composeFile build $service
# Tag the image for ACR
docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service"
# Push the image to ACR
docker push "dadeschoolscontainerregistry.azurecr.io/$service"
}

View File

@ -1,39 +0,0 @@
#!/bin/bash
# Determine the current directory (where the script is located)
script_directory="$( cd "$(dirname "$0")" ; pwd -P )"
# Use the 'find' command to locate the 'docker-compose.yml' file within the repository directory
composeFile=$(find "$script_directory/.." -name "docker-compose.yml" -type f | head -n 1)
if [ -z "$composeFile" ]; then
echo "docker-compose.yml not found."
exit 1
fi
# List of services to build, tag, and push
services=(
"damageassesmentapianswers"
"damageassesmentapiattachments"
"damageassesmentapiemployees"
"damageassesmentapilocations"
"damageassesmentapiquestions"
"damageassesmentapisurveys"
"damageassesmentapidoculinks"
"damageassesmentapiresponses"
)
# Log in to ACR (replace ACR_USERNAME and ACR_PASSWORD)
docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegistry -p k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn
# Loop through the services and build, tag, and push
for service in "${services[@]}"; do
# Build the service
docker-compose -f "$composeFile" build "$service"
# Tag the image for ACR
docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service"
# Push the image to ACR
docker push "dadeschoolscontainerregistry.azurecr.io/$service"
done

39
db/migrate-sqldb_v1.ps1 Normal file
View File

@ -0,0 +1,39 @@
# Define the path to your application's root directory
$applicationRoot = "C:\Users\santh\OneDrive\Desktop\DOCKERS\ubuntu\Sprint6\C1011\Backend-API-Services\DamageAssesmentApi\"
#To execute: powershell -ExecutionPolicy Bypass -File .\migrate-sqldb.ps1
# Define the list of microservice directories
$microservices = @(
"DamageAssesment.Api.Answers",
"DamageAssesment.Api.Attachments",
"DamageAssesment.Api.DocuLinks",
"DamageAssesment.Api.Employees",
"DamageAssesment.Api.Locations",
"DamageAssesment.Api.Questions",
"DamageAssesment.Api.Responses",
"DamageAssesment.Api.Surveys"
)
# Define the migration name with the current date and time
$migrationName = "Migration_" + (Get-Date -Format "yyyyMMdd_HHmmss")
# Function to run migrations for a microservice
Function Run-Migrations {
param (
[string]$microservicePath
)
Write-Host "Running Migrations for $microservicePath..."
Set-Location -Path $microservicePath
dotnet ef migrations add $migrationName
dotnet ef database update
Write-Host "Migrations for $microservicePath completed."
}
# Run migrations for each microservice
$microservices | ForEach-Object {
$microservicePath = Join-Path -Path $applicationRoot -ChildPath $_
Run-Migrations -microservicePath $microservicePath
}
Write-Host "All Migrations Completed."