diff --git a/Bedelia/.dockerignore b/Bedelia/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..2e9693ed1a9619a49dcd4c7f3e9ea26541ff27d7
--- /dev/null
+++ b/Bedelia/.dockerignore
@@ -0,0 +1,2 @@
+obj
+bin
\ No newline at end of file
diff --git a/Bedelia/Bedelia.csproj b/Bedelia/Bedelia.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..e107ff40f0cf5a3da92284e01c9a03c54dc97595
--- /dev/null
+++ b/Bedelia/Bedelia.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0" NoWarn="NU1605" />
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.0" NoWarn="NU1605" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
+    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.0" />
+    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
+  </ItemGroup>
+
+</Project>
diff --git a/Bedelia/Bedelia.csproj.user b/Bedelia/Bedelia.csproj.user
new file mode 100644
index 0000000000000000000000000000000000000000..da34dfb3c7dfbdf3398ff0bdb2f5d654da7d56a9
--- /dev/null
+++ b/Bedelia/Bedelia.csproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Controller_SelectedScaffolderID>ApiControllerWithActionsScaffolder</Controller_SelectedScaffolderID>
+    <Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
+    <WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/Bedelia/Bedelia.sln b/Bedelia/Bedelia.sln
new file mode 100644
index 0000000000000000000000000000000000000000..67548d1d30f7b5f4772d28987a29323225a72553
--- /dev/null
+++ b/Bedelia/Bedelia.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30717.126
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bedelia", "Bedelia.csproj", "{BB028517-233A-466B-A46C-420FC942BA48}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{BB028517-233A-466B-A46C-420FC942BA48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BB028517-233A-466B-A46C-420FC942BA48}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BB028517-233A-466B-A46C-420FC942BA48}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BB028517-233A-466B-A46C-420FC942BA48}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {53DA0290-A5A4-422B-A6DD-837A8FFCF354}
+	EndGlobalSection
+EndGlobal
diff --git a/Bedelia/Controllers/CoursesController.cs b/Bedelia/Controllers/CoursesController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fb73982230f85631fb9490f6ff74abfce5e4cec0
--- /dev/null
+++ b/Bedelia/Controllers/CoursesController.cs
@@ -0,0 +1,148 @@
+using Bedelia.Dtos;
+using Bedelia.EF;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Bedelia.Controllers
+{
+    [Route("api/[controller]")]
+    [ApiController]
+    public class CoursesController : ControllerBase
+    {
+        private readonly BedeliaContext _context;
+
+        public CoursesController(BedeliaContext context)
+        {
+            _context = context;
+        }
+
+        [HttpGet]
+        public async Task<IActionResult> Get()
+        {
+            var courses = await _context.Courses.ToListAsync();
+            return Ok(courses);
+        }
+
+        [HttpGet("{name}")]
+        public async Task<IActionResult> Get(string name)
+        {
+            var course = await _context.Courses.FirstOrDefaultAsync(x => x.Name == name);
+
+            if (course == null)
+            {
+                return BadRequest(string.Format("el curso con nombre {0} no existe", name));
+            }
+
+            return Ok(course);
+        }
+
+        [HttpPost]
+        public async Task<IActionResult> Post([FromBody] string courseName)
+        {
+            var course = new Course()
+            {
+                Name = courseName
+            };
+
+            _context.Courses.Add(course);
+            await _context.SaveChangesAsync();
+
+            return Ok(course);
+        }
+
+        [HttpPost("loadData")]
+        public async Task<IActionResult> Post([FromBody] List<string> courseNames)
+        {
+            var dbCourses = await _context.Courses
+                .Where(x=>courseNames.Contains(x.Name))
+                .ToListAsync();
+
+            var courses = new List<Course>();
+            foreach (var courseName in courseNames)
+            {
+                var dbCourse = dbCourses.FirstOrDefault(x => x.Name == courseName);
+                if (dbCourse == null)
+                {
+                    courses.Add(new Course()
+                    {
+                        Name = courseName
+                    });
+                }
+            }
+
+            _context.Courses.AddRange(courses);
+            await _context.SaveChangesAsync();
+
+            return Ok(courses);
+        }
+
+        [HttpPut("{id}")]
+        public async Task<IActionResult> Put(int id, [FromBody] Course course)
+        {
+            var dbCourse = await _context.Courses.FirstOrDefaultAsync(x => x.Id == id);
+
+            if (dbCourse == null)
+            {
+                return BadRequest(string.Format("el curso con id {0} no existe", id));
+            }
+
+            dbCourse.Name = course.Name;
+            await _context.SaveChangesAsync();
+
+            return Ok(dbCourse);
+        }
+
+        [HttpDelete("{id}")]
+        public async Task<IActionResult> Delete(int id)
+        {
+            var course = await _context.Courses.FirstOrDefaultAsync(x => x.Id == id);
+
+            _context.Courses.Remove(course);
+            await _context.SaveChangesAsync();
+
+            return Ok();
+        }
+
+        [HttpPost("closeRecord")]
+        public async Task<IActionResult> CloseRecord(CloseRecordDto closeRecord)
+        {
+            var now = DateTime.Now;
+            var courseId = await _context.Courses
+                .Where(x => x.Name == closeRecord.CourseName)
+                .Select(x => x.Id)
+                .FirstOrDefaultAsync();
+
+            var userIdentityCards = closeRecord.Users.Select(x => x.IdentityCard);
+
+            var users = await _context.Users
+                .Where(x => userIdentityCards.Contains(x.IdentityCard))
+                .ToListAsync();
+
+            var userCourses = new List<UserCourse>();
+            foreach (var user in users)
+            {
+                var grade = closeRecord.Users
+                    .Where(x => x.IdentityCard == user.IdentityCard)
+                    .Select(x => x.Grade)
+                    .FirstOrDefault();
+
+                userCourses.Add(new UserCourse()
+                {
+                    CourseId = courseId,
+                    UserId = user.Id,
+                    Grade = grade,
+                    GradeDate = now
+                });
+            }
+
+            _context.UserCourses.AddRange(userCourses);
+            await _context.SaveChangesAsync();
+
+            return Ok();
+        }
+    }
+}
diff --git a/Bedelia/Controllers/UsersController.cs b/Bedelia/Controllers/UsersController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bffe06644b7459bf2bb4176ad8fe91dfacc0eaf7
--- /dev/null
+++ b/Bedelia/Controllers/UsersController.cs
@@ -0,0 +1,139 @@
+using Bedelia.Dtos;
+using Bedelia.EF;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Bedelia.Controllers
+{
+    [Route("api/[controller]")]
+    [ApiController]
+    public class UsersController : ControllerBase
+    {
+        private readonly BedeliaContext _context;
+
+        public UsersController(BedeliaContext context)
+        {
+            _context = context;
+        }
+
+        [HttpGet]
+        public async Task<IActionResult> Get()
+        {
+            var users = await _context.Users.ToListAsync();
+            return Ok(users);
+        }
+
+        [HttpGet("{id}")]
+        public async Task<IActionResult> Get(string identityCard)
+        {
+            var user = await _context.Users.FirstOrDefaultAsync(x => x.IdentityCard == identityCard);
+
+            if (user == null)
+            {
+                return BadRequest(string.Format("el usuario con cedula {0} no existe", identityCard));
+            }
+
+            return Ok(user);
+        }
+
+        [HttpPost]
+        public async Task<IActionResult> Post([FromBody] UserCreateDto userDto)
+        {
+            var user = new User()
+            {
+                IdentityCard = userDto.IdentityCard,
+                Name = userDto.Name,
+                Password = userDto.Password
+            };
+
+            _context.Users.Add(user);
+            await _context.SaveChangesAsync();
+
+            return Ok(user);
+        }
+
+        [HttpPost("loadData")]
+        public async Task<IActionResult> Post([FromBody] List<UserCreateDto> userDtos)
+        {
+            var userIdentityCards = userDtos.Select(x => x.IdentityCard);
+
+            var dbUsers = await _context.Users
+                .Where(x => userIdentityCards.Contains(x.IdentityCard))
+                .ToListAsync();
+
+            var users = new List<User>();
+            foreach (var userDto in userDtos)
+            {
+                var dbUser = dbUsers.FirstOrDefault(x => x.IdentityCard == userDto.IdentityCard);
+                if (dbUser == null)
+                {
+                    users.Add(new User()
+                    {
+                        IdentityCard = userDto.IdentityCard,
+                        Name = userDto.Name,
+                        Password = userDto.Password
+                    });
+                }
+            }
+
+            _context.Users.AddRange(users);
+            await _context.SaveChangesAsync();
+
+            return Ok(users);
+        }
+
+        [HttpPut("{id}")]
+        public async Task<IActionResult> Put(int id, [FromBody] User user)
+        {
+            var dbUser = await _context.Users.FirstOrDefaultAsync(x => x.Id == id);
+
+            if (dbUser == null)
+            {
+                return BadRequest(string.Format("el usuario con id {0} no existe", id));
+            }
+
+            dbUser.IdentityCard = user.IdentityCard;
+            dbUser.Name = user.Name;
+            dbUser.Password = user.Password;
+
+            await _context.SaveChangesAsync();
+
+            return Ok(dbUser);
+        }
+
+        [HttpDelete("{id}")]
+        public async Task<IActionResult> Delete(int id)
+        {
+            var user = await _context.Users.FirstOrDefaultAsync(x => x.Id == id);
+
+            _context.Users.Remove(user);
+            await _context.SaveChangesAsync();
+
+            return Ok();
+        }
+
+        [HttpGet("userNotes")]
+        public async Task<IActionResult> UserNotes()
+        {
+            var result = await (from user in _context.Users
+                                join userCourse in _context.UserCourses
+                                    on user.Id equals userCourse.UserId
+                                join course in _context.Courses
+                                    on userCourse.CourseId equals course.Id
+                                select new
+                                {
+                                    User = user.IdentityCard,
+                                    Course = course.Name,
+                                    Grade = userCourse.Grade,
+                                    GradeDate = userCourse.GradeDate
+                                }).ToListAsync();
+
+            return Ok(result);
+        }
+
+    }
+}
diff --git a/Bedelia/Dockerfile b/Bedelia/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b4f2d55aa9108c20dcde071e65b879717b85d25f
--- /dev/null
+++ b/Bedelia/Dockerfile
@@ -0,0 +1,16 @@
+FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
+WORKDIR /app
+
+WORKDIR /src
+COPY *.csproj ./
+RUN dotnet restore ./Bedelia.csproj
+
+COPY . ./
+WORKDIR /src
+RUN dotnet publish -c release -o /app/publish
+
+FROM mcr.microsoft.com/dotnet/sdk:5.0
+WORKDIR /app
+COPY --from=build /app/publish .
+EXPOSE 5000
+ENTRYPOINT ["dotnet", "Bedelia.dll"]
\ No newline at end of file
diff --git a/Bedelia/Dtos/CloseRecordDto.cs b/Bedelia/Dtos/CloseRecordDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3493fb6a7fe4b399370a24ca2fc7e15cb7e2d158
--- /dev/null
+++ b/Bedelia/Dtos/CloseRecordDto.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
+namespace Bedelia.Dtos
+{
+    public class CloseRecordDto
+    {
+        [Required]
+        public string CourseName { get; set; }
+
+        [Required]
+        public List<UserDto> Users { get; set; }
+    }
+}
diff --git a/Bedelia/Dtos/CourseCreateDto.cs b/Bedelia/Dtos/CourseCreateDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..65119ee161ce38b9dcb7a26abad126092c2d99ff
--- /dev/null
+++ b/Bedelia/Dtos/CourseCreateDto.cs
@@ -0,0 +1,10 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Bedelia
+{
+    public class CourseCreateDto
+    {
+        [Required]
+        public string Name { get; set; }
+    }
+}
diff --git a/Bedelia/Dtos/UserCreateDto.cs b/Bedelia/Dtos/UserCreateDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7c6cca67f99a53993111f7b2ea970f68e0884aae
--- /dev/null
+++ b/Bedelia/Dtos/UserCreateDto.cs
@@ -0,0 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Bedelia.Dtos
+{
+    public class UserCreateDto
+    {
+        [Required]
+        public string IdentityCard { get; set; }
+
+        [Required]
+        public string Name { get; set; }
+
+        [Required]
+        public string Password { get; set; }
+    }
+}
diff --git a/Bedelia/Dtos/UserDto.cs b/Bedelia/Dtos/UserDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bd2f6a1e2f82867b1e359a86f7265d6a363d196b
--- /dev/null
+++ b/Bedelia/Dtos/UserDto.cs
@@ -0,0 +1,13 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Bedelia.Dtos
+{
+    public class UserDto
+    {
+        [Required]
+        public string IdentityCard { get; set; }
+
+        [Required]
+        public int Grade { get; set; }
+    }
+}
diff --git a/Bedelia/EF/BedeliaContext.cs b/Bedelia/EF/BedeliaContext.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3104af5b6de497e058331952b06f52096df92364
--- /dev/null
+++ b/Bedelia/EF/BedeliaContext.cs
@@ -0,0 +1,65 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Bedelia.EF
+{
+    public class BedeliaContext : DbContext
+    {
+        public DbSet<User> Users { get; set; }
+        public DbSet<Course> Courses { get; set; }
+        public DbSet<UserCourse> UserCourses { get; set; }
+
+        public BedeliaContext(DbContextOptions options) : base(options) { }
+
+        protected override void OnModelCreating(ModelBuilder modelBuilder)
+        {
+            modelBuilder.Entity<User>(e =>
+            {
+                e.HasKey(x => x.Id);
+
+                e.HasIndex(x => x.IdentityCard)
+                    .IsUnique();
+
+                e.HasIndex(x => x.Name)
+                    .IsUnique();
+
+                e.Property(x => x.IdentityCard)
+                    .IsRequired()
+                    .HasMaxLength(50);
+
+                e.Property(x => x.Name)
+                    .IsRequired()
+                    .HasMaxLength(50);
+
+                e.Property(x => x.Password)
+                    .IsRequired()
+                    .HasMaxLength(255);
+            });
+
+            modelBuilder.Entity<Course>(e =>
+            {
+                e.HasKey(x => x.Id);
+
+                e.Property(x => x.Name)
+                .IsRequired()
+                .HasMaxLength(50);
+            });
+
+            modelBuilder.Entity<UserCourse>(e =>
+            {
+                e.HasKey(x => new { x.UserId, x.CourseId });
+
+                e.HasOne(x => x.Course)
+                    .WithMany(x => x.UserCourses)
+                    .HasForeignKey(x => x.CourseId);
+
+                e.HasOne(x => x.User)
+                    .WithMany(x => x.UserCourses)
+                    .HasForeignKey(x => x.UserId);
+            });
+        }
+    }
+}
diff --git a/Bedelia/EF/Course.cs b/Bedelia/EF/Course.cs
new file mode 100644
index 0000000000000000000000000000000000000000..65a6b5a6bf1e37b5204881a5a82e169190aa65a1
--- /dev/null
+++ b/Bedelia/EF/Course.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Bedelia.EF
+{
+    public class Course
+    {
+        public int Id { get; set; }
+        public string Name { get; set; }
+
+        public ICollection<UserCourse> UserCourses { get; set; }
+    }
+}
diff --git a/Bedelia/EF/User.cs b/Bedelia/EF/User.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4cfc40133510e9343554ac796aa152f1c95e8418
--- /dev/null
+++ b/Bedelia/EF/User.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Bedelia.EF
+{
+    public class User
+    {
+        public int Id { get; set; }
+        public string IdentityCard { get; set; }
+        public string Name { get; set; }
+        public string Password { get; set; }
+
+        public ICollection<UserCourse> UserCourses { get; set; }
+    }
+}
diff --git a/Bedelia/EF/UserCourse.cs b/Bedelia/EF/UserCourse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0b52e7c4c4d3895fe88ec952b8cb5c91b6d8b8c8
--- /dev/null
+++ b/Bedelia/EF/UserCourse.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Bedelia.EF
+{
+    public class UserCourse
+    {
+        public int UserId { get; set; }
+        public int CourseId { get; set; }
+        public int Grade { get; set; }
+        public DateTime GradeDate { get; set; }
+
+        public User User { get; set; }
+        public Course Course { get; set; }
+    }
+}
diff --git a/Bedelia/Migrations/20201128224417_initial.Designer.cs b/Bedelia/Migrations/20201128224417_initial.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1879039ae8918655176d06d108b0ce4de436ded4
--- /dev/null
+++ b/Bedelia/Migrations/20201128224417_initial.Designer.cs
@@ -0,0 +1,58 @@
+// <auto-generated />
+using Bedelia.EF;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Bedelia.Migrations
+{
+    [DbContext(typeof(BedeliaContext))]
+    [Migration("20201128224417_initial")]
+    partial class initial
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .UseIdentityByDefaultColumns()
+                .HasAnnotation("Relational:MaxIdentifierLength", 63)
+                .HasAnnotation("ProductVersion", "5.0.0");
+
+            modelBuilder.Entity("Bedelia.EF.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .UseIdentityByDefaultColumn();
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("Username")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("IdentityCard")
+                        .IsUnique();
+
+                    b.HasIndex("Username")
+                        .IsUnique();
+
+                    b.ToTable("Users");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/Bedelia/Migrations/20201128224417_initial.cs b/Bedelia/Migrations/20201128224417_initial.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9dffea5c79d1ac3380c3e3b88fa4c9d3f8d3d385
--- /dev/null
+++ b/Bedelia/Migrations/20201128224417_initial.cs
@@ -0,0 +1,44 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Bedelia.Migrations
+{
+    public partial class initial : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.CreateTable(
+                name: "Users",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "integer", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    IdentityCard = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
+                    Username = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
+                    Password = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Users", x => x.Id);
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Users_IdentityCard",
+                table: "Users",
+                column: "IdentityCard",
+                unique: true);
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Users_Username",
+                table: "Users",
+                column: "Username",
+                unique: true);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "Users");
+        }
+    }
+}
diff --git a/Bedelia/Migrations/20201128235147_courses.Designer.cs b/Bedelia/Migrations/20201128235147_courses.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..05bcced32a524d9b4a8d5d063ff5f067eaf6589e
--- /dev/null
+++ b/Bedelia/Migrations/20201128235147_courses.Designer.cs
@@ -0,0 +1,126 @@
+// <auto-generated />
+using System;
+using Bedelia.EF;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Bedelia.Migrations
+{
+    [DbContext(typeof(BedeliaContext))]
+    [Migration("20201128235147_courses")]
+    partial class courses
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .UseIdentityByDefaultColumns()
+                .HasAnnotation("Relational:MaxIdentifierLength", 63)
+                .HasAnnotation("ProductVersion", "5.0.0");
+
+            modelBuilder.Entity("Bedelia.EF.Course", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .UseIdentityByDefaultColumn();
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Courses");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .UseIdentityByDefaultColumn();
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("character varying(255)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("IdentityCard")
+                        .IsUnique();
+
+                    b.HasIndex("Name")
+                        .IsUnique();
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.UserCourse", b =>
+                {
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("Grade")
+                        .HasColumnType("integer");
+
+                    b.Property<DateTime>("GradeDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.HasKey("UserId", "CourseId");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("UserCourses");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.UserCourse", b =>
+                {
+                    b.HasOne("Bedelia.EF.Course", "Course")
+                        .WithMany("UserCourses")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bedelia.EF.User", "User")
+                        .WithMany("UserCourses")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Course");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.Course", b =>
+                {
+                    b.Navigation("UserCourses");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.User", b =>
+                {
+                    b.Navigation("UserCourses");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/Bedelia/Migrations/20201128235147_courses.cs b/Bedelia/Migrations/20201128235147_courses.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8203cc103960bf9eebbdd683ddc2f5c92e26304e
--- /dev/null
+++ b/Bedelia/Migrations/20201128235147_courses.cs
@@ -0,0 +1,85 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Bedelia.Migrations
+{
+    public partial class courses : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.RenameColumn(
+                name: "Username",
+                table: "Users",
+                newName: "Name");
+
+            migrationBuilder.RenameIndex(
+                name: "IX_Users_Username",
+                table: "Users",
+                newName: "IX_Users_Name");
+
+            migrationBuilder.CreateTable(
+                name: "Courses",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "integer", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    Name = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Courses", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "UserCourses",
+                columns: table => new
+                {
+                    UserId = table.Column<int>(type: "integer", nullable: false),
+                    CourseId = table.Column<int>(type: "integer", nullable: false),
+                    Grade = table.Column<int>(type: "integer", nullable: false),
+                    GradeDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_UserCourses", x => new { x.UserId, x.CourseId });
+                    table.ForeignKey(
+                        name: "FK_UserCourses_Courses_CourseId",
+                        column: x => x.CourseId,
+                        principalTable: "Courses",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_UserCourses_Users_UserId",
+                        column: x => x.UserId,
+                        principalTable: "Users",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_UserCourses_CourseId",
+                table: "UserCourses",
+                column: "CourseId");
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "UserCourses");
+
+            migrationBuilder.DropTable(
+                name: "Courses");
+
+            migrationBuilder.RenameColumn(
+                name: "Name",
+                table: "Users",
+                newName: "Username");
+
+            migrationBuilder.RenameIndex(
+                name: "IX_Users_Name",
+                table: "Users",
+                newName: "IX_Users_Username");
+        }
+    }
+}
diff --git a/Bedelia/Migrations/BedeliaContextModelSnapshot.cs b/Bedelia/Migrations/BedeliaContextModelSnapshot.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4e00a716072e9bcf6ffb73e32de70f318c6d7c8c
--- /dev/null
+++ b/Bedelia/Migrations/BedeliaContextModelSnapshot.cs
@@ -0,0 +1,124 @@
+// <auto-generated />
+using System;
+using Bedelia.EF;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Bedelia.Migrations
+{
+    [DbContext(typeof(BedeliaContext))]
+    partial class BedeliaContextModelSnapshot : ModelSnapshot
+    {
+        protected override void BuildModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .UseIdentityByDefaultColumns()
+                .HasAnnotation("Relational:MaxIdentifierLength", 63)
+                .HasAnnotation("ProductVersion", "5.0.0");
+
+            modelBuilder.Entity("Bedelia.EF.Course", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .UseIdentityByDefaultColumn();
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Courses");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .UseIdentityByDefaultColumn();
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasMaxLength(255)
+                        .HasColumnType("character varying(255)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("IdentityCard")
+                        .IsUnique();
+
+                    b.HasIndex("Name")
+                        .IsUnique();
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.UserCourse", b =>
+                {
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("Grade")
+                        .HasColumnType("integer");
+
+                    b.Property<DateTime>("GradeDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.HasKey("UserId", "CourseId");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("UserCourses");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.UserCourse", b =>
+                {
+                    b.HasOne("Bedelia.EF.Course", "Course")
+                        .WithMany("UserCourses")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bedelia.EF.User", "User")
+                        .WithMany("UserCourses")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Course");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.Course", b =>
+                {
+                    b.Navigation("UserCourses");
+                });
+
+            modelBuilder.Entity("Bedelia.EF.User", b =>
+                {
+                    b.Navigation("UserCourses");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/Bedelia/Program.cs b/Bedelia/Program.cs
new file mode 100644
index 0000000000000000000000000000000000000000..eaca41ffc496e6b136a31e9421f64d4e5797bba8
--- /dev/null
+++ b/Bedelia/Program.cs
@@ -0,0 +1,27 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Bedelia
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateHostBuilder(args).Build().Run();
+        }
+
+        public static IHostBuilder CreateHostBuilder(string[] args) =>
+            Host.CreateDefaultBuilder(args)
+                .ConfigureWebHostDefaults(webBuilder =>
+                {
+                    webBuilder.UseStartup<Startup>();
+                    webBuilder.UseUrls("http://*:5000/");
+                });
+    }
+}
diff --git a/Bedelia/Properties/launchSettings.json b/Bedelia/Properties/launchSettings.json
new file mode 100644
index 0000000000000000000000000000000000000000..f66813ed228f570421e7108adf6e4ec5b748833a
--- /dev/null
+++ b/Bedelia/Properties/launchSettings.json
@@ -0,0 +1,31 @@
+{
+  "$schema": "http://json.schemastore.org/launchsettings.json",
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:55438",
+      "sslPort": 0
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "launchUrl": "swagger",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "Bedelia": {
+      "commandName": "Project",
+      "dotnetRunMessages": "true",
+      "launchBrowser": true,
+      "launchUrl": "swagger",
+      "applicationUrl": "http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
diff --git a/Bedelia/Startup.cs b/Bedelia/Startup.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f170f55c9a870dedf2ab815e79f9e651f79114f3
--- /dev/null
+++ b/Bedelia/Startup.cs
@@ -0,0 +1,70 @@
+using Bedelia.EF;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.OpenApi.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Bedelia
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration, IWebHostEnvironment env)
+        {
+            Configuration = configuration;
+            _env = env;
+        }
+
+        public IConfiguration Configuration { get; }
+        private readonly IWebHostEnvironment _env;
+
+        // This method gets called by the runtime. Use this method to add services to the container.
+        public void ConfigureServices(IServiceCollection services)
+        {
+
+            services.AddControllers();
+            services.AddSwaggerGen(c =>
+            {
+                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Bedelia", Version = "v1" });
+            });
+
+            var postgreSqlSection = _env.IsProduction() ? "PostgreSqlCloud" : "PostgreSql";
+
+            services.AddDbContext<BedeliaContext>(x => x.UseNpgsql(
+                Configuration.GetConnectionString(postgreSqlSection)));
+        }
+
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, BedeliaContext context)
+        {
+            context.Database.Migrate();
+
+            if (env.IsDevelopment())
+            {
+                app.UseDeveloperExceptionPage();
+            }
+
+            app.UseSwagger();
+            app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Bedelia v1"));
+
+            app.UseRouting();
+
+            app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
+
+            app.UseAuthorization();
+
+            app.UseEndpoints(endpoints =>
+            {
+                endpoints.MapControllers();
+            });
+        }
+    }
+}
diff --git a/Bedelia/appsettings.Development.json b/Bedelia/appsettings.Development.json
new file mode 100644
index 0000000000000000000000000000000000000000..8983e0fc1c5e2795ccfde0c771c6d66c88ef4a42
--- /dev/null
+++ b/Bedelia/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft": "Warning",
+      "Microsoft.Hosting.Lifetime": "Information"
+    }
+  }
+}
diff --git a/Bedelia/appsettings.json b/Bedelia/appsettings.json
new file mode 100644
index 0000000000000000000000000000000000000000..048c2f6d1e366b10da59de510dab3ecb86125fba
--- /dev/null
+++ b/Bedelia/appsettings.json
@@ -0,0 +1,14 @@
+{
+  "ConnectionStrings": {
+    "PostgreSql": "Host=localhost;Database=bedelia;Username=postgres;Password=111111",
+    "PostgreSqlCloud": "Host=db;Database=bedelia;Username=postgres;Password=postgres"
+  },
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft": "Warning",
+      "Microsoft.Hosting.Lifetime": "Information"
+    }
+  },
+  "AllowedHosts": "*"
+}
diff --git a/Bedelia/docker-compose.yml b/Bedelia/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..430f5afafaa0bd15f5434c45042321deec30bfe4
--- /dev/null
+++ b/Bedelia/docker-compose.yml
@@ -0,0 +1,25 @@
+version: '3.8'
+
+services:
+  bedelia:
+    image: esantangelo/bedelia
+    container_name: bedelia
+    depends_on:
+      - db
+    ports: 
+      - 80:5000
+    restart: on-failure
+
+  db:
+    image: postgres
+    container_name: db
+    environment: 
+      POSTGRES_PASSWORD: postgres
+    ports:
+      - 5432:5432
+    volumes:
+      - db-data:/var/lib/postgresql/data
+    restart: on-failure
+
+volumes:
+  db-data:
\ No newline at end of file