diff --git a/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs b/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs
index 4a8d4b838b69c414438d9802c0ded5433fa78b0a..22545bafce6ac73370db0e94dc5c9dd2803d2adb 100644
--- a/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs
+++ b/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs
@@ -170,10 +170,25 @@ namespace Tsi1.Api.Controllers
             return Ok(result.Data);
         }
 
+        [Authorize(Roles = UserTypes.FacultyAdmin)]
+        [HttpGet("GetAllTemplates")]
+        public async Task<IActionResult> GetAllTemplates()
+        {
+            var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value);
+
+            var result = await _courseService.GetAll(tenantId, true);
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok(result.Data);
+        }
+
 
         [Authorize(Roles = UserTypes.Professor + ", " + UserTypes.FacultyAdmin)]
         [HttpPut("Modify/{courseId}")]
-        public async Task<IActionResult> Modify(int courseId, CourseCreateDto courseDto)
+        public async Task<IActionResult> Modify(int courseId, CourseModifyDto courseDto)
         {
             var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value);
             courseDto.TenantId = tenantId;
@@ -238,5 +253,19 @@ namespace Tsi1.Api.Controllers
             return Ok(result.Data);
         }
 
+        [AllowAnonymous]
+        [Authorize(Roles = UserTypes.FacultyAdmin)]
+        [HttpPost("CreateFromTemplate")]
+        public async Task<IActionResult> CreateFromTemplate(CourseTemplateCreateDto courseTemplate)
+        {
+            var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value);
+
+            var result = await _courseService.CreateFromTemplate(courseTemplate, tenantId);
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+            return Ok();
+        }
     }
 }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseCreateDto.cs
index ffd3608d231c078c29b2a555f4b20ae565bfeaa8..a3540f451655fc12c4d25a8027dcb7dcedb1bea0 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseCreateDto.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseCreateDto.cs
@@ -8,6 +8,7 @@ namespace Tsi1.BusinessLayer.Dtos
     public class CourseCreateDto
     {
         public string Name { get; set; }
+        public bool IsTemplate { get; set; }
 
         [JsonIgnore]
         public int TenantId { get; set; }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseModifyDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseModifyDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fe5599cc0265bf047c8fae3b65abc1662837821e
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseModifyDto.cs
@@ -0,0 +1,13 @@
+using System.Text.Json.Serialization;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class CourseModifyDto
+    {
+        public string Name { get; set; }
+        public bool IsTemplate { get; set; }
+
+        [JsonIgnore]
+        public int TenantId { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseTemplateCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseTemplateCreateDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..94924d7835c5270b84d97a67c041f563d56ff2e6
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CourseTemplateCreateDto.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class CourseTemplateCreateDto
+    {
+        public string Name { get; set; }
+        public int CourseTemplateId { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
index 41b7cf04530200739506f9fc996dff91c0ac3b81..a004f7a3bab816594826a1ebb47d53beb6f8c741 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
@@ -31,8 +31,9 @@ namespace Tsi1.BusinessLayer.Helpers
         public const string CannotAuthenticateToSmtpServer = "No se pudo autenticar en el servidor SMTP";
         public const string CannotSendEmail = "No se pudo mandar el mail con asunto {0}";
 
-        public const string CourseDoesNotExist = "El curso '{0}' no existe";
+        public const string CourseDoesNotExist = "El curso con id '{0}' no existe";
         public const string DuplicateCourseName = "Ya existe un curso con nombre '{0}'";
+        public const string CourseIsTemplate = "El curso con id '{0}' es un template";
 
         public const string TenantDoesNotExist = "La Facultad '{0}' no existe";
         public const string DuplicateTenantName = "Ya existe una Facultad con nombre '{0}'";
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs
index 4d7d53b30ba60bfd543f4520cac5d16b0a07d6c2..da9824d33e9b439b34192a98f1d6553c76f3a90d 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs
@@ -72,6 +72,13 @@ namespace Tsi1.BusinessLayer.Helpers
             CreateMap<SectionDetailDto, Section>();
             CreateMap<SectionItemDetailDto, SectionItem>();
             CreateMap<FileDetailDto, File>();
+
+            CreateMap<Course, Course>().ForMember(x => x.Id, opt => opt.Ignore());
+            CreateMap<Tenant, Tenant>().ForMember(x => x.Id, opt => opt.Ignore());
+            CreateMap<Section, Section>().ForMember(x => x.Id, opt => opt.Ignore());
+            CreateMap<SectionItem, SectionItem>().ForMember(x => x.Id, opt => opt.Ignore());
+            CreateMap<SectionItemType, SectionItemType>().ForMember(x => x.Id, opt => opt.Ignore());
+            CreateMap<Forum, Forum>().ForMember(x => x.Id, opt => opt.Ignore());
         }
     }
 }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ICourseService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ICourseService.cs
index 836612b7ca3f7dde220cf84c186e2b5892c9719e..640e6ec1deaf374fec7bebe7aa5c44802da38731 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ICourseService.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ICourseService.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
+using System.Collections.Generic;
 using System.Threading.Tasks;
 using Tsi1.BusinessLayer.Dtos;
 using Tsi1.BusinessLayer.Helpers;
@@ -13,14 +11,15 @@ namespace Tsi1.BusinessLayer.Interfaces
         Task<ServiceResult<List<CoursePreviewDto>>> GetCoursePreviews(int userId, string userType);
 
         Task<ServiceResult<Course>> Create(CourseCreateDto newCourse);
+        Task<ServiceResult<bool>> CreateFromTemplate(CourseTemplateCreateDto courseTemplate, int tenantId);
 
         Task<ServiceResult<bool>> Matriculate(int userId, int courseId);
 
         Task<ServiceResult<bool>> AddProfessorToCourse(ProfessorCourseDto professorCourseDto);
 
-        Task<ServiceResult<List<CoursePreviewDto>>> GetAll(int tenantId);
+        Task<ServiceResult<List<CoursePreviewDto>>> GetAll(int tenantId, bool isTemplate = false);
 
-        Task<ServiceResult<bool>> Modify(int courseId, CourseCreateDto courseDto);
+        Task<ServiceResult<bool>> Modify(int courseId, CourseModifyDto courseDto);
 
         Task<ServiceResult<Course>> Delete(int courseId);
 
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/CourseService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/CourseService.cs
index fffcc93913bd4653c1fc9228a6d362b6e2acd8f8..8152ca0b1ff477e95df6aee7eca516ef3f9259a3 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Services/CourseService.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/CourseService.cs
@@ -97,6 +97,7 @@ namespace Tsi1.BusinessLayer.Services
 
             if (user == null || user.Student == null)
             {
+                result.HasError = true;
                 result.Message = string.Format(ErrorMessages.UserDoesNotExist, userId);
                 return result;
             }
@@ -105,10 +106,18 @@ namespace Tsi1.BusinessLayer.Services
 
             if (course == null)
             {
+                result.HasError = true;
                 result.Message = string.Format(ErrorMessages.CourseDoesNotExist, courseId);
                 return result;
             }
 
+            if (course.IsTemplate)
+            {
+                result.HasError = true;
+                result.AddMessage(string.Format(ErrorMessages.CourseIsTemplate, courseId));
+                return result;
+            }
+
             var existingStudentCourse = await _context.StudentCourses
                 .FirstOrDefaultAsync(x => x.StudentId == user.StudentId && x.CourseId == course.Id);
 
@@ -144,6 +153,7 @@ namespace Tsi1.BusinessLayer.Services
 
             if (user == null || user.Professor == null)
             {
+                result.HasError = true;
                 result.Message = string.Format(ErrorMessages.UserDoesNotExist, user.Username);
                 return result;
             }
@@ -153,10 +163,18 @@ namespace Tsi1.BusinessLayer.Services
 
             if (course == null)
             {
+                result.HasError = true;
                 result.Message = string.Format(ErrorMessages.CourseDoesNotExist, professorCourseDto.CourseId);
                 return result;
             }
 
+            if (course.IsTemplate)
+            {
+                result.HasError = true;
+                result.AddMessage(string.Format(ErrorMessages.CourseIsTemplate, professorCourseDto.CourseId));
+                return result;
+            }
+
             var existingProfessorCourse = await _context.ProfessorCourses
                 .FirstOrDefaultAsync(x => x.ProfessorId == user.ProfessorId && x.CourseId == course.Id);
 
@@ -174,30 +192,28 @@ namespace Tsi1.BusinessLayer.Services
             };
 
             _context.ProfessorCourses.Add(professorCourse);
-
             await _context.SaveChangesAsync();
 
             result.Data = true;
-
             return result;
         }
 
-        public async Task<ServiceResult<List<CoursePreviewDto>>> GetAll(int tenantId)
+        public async Task<ServiceResult<List<CoursePreviewDto>>> GetAll(int tenantId, bool isTemplate = false)
         {
             var result = new ServiceResult<List<CoursePreviewDto>>();
 
             var courses = await _context.Courses
-                .Where(x => x.TenantId == tenantId)
+                .Where(x => x.TenantId == tenantId
+                    && x.IsTemplate == isTemplate)
                 .ToListAsync();
 
             var coursesDto = _mapper.Map<List<CoursePreviewDto>>(courses);
 
             result.Data = coursesDto;
-
             return result;
         }
 
-        public async Task<ServiceResult<bool>> Modify(int courseId, CourseCreateDto courseDto)
+        public async Task<ServiceResult<bool>> Modify(int courseId, CourseModifyDto courseDto)
         {
             var result = new ServiceResult<bool>();
 
@@ -210,12 +226,10 @@ namespace Tsi1.BusinessLayer.Services
                 return result;
             }
 
-            _mapper.Map(courseDto, course);
-          
+            _mapper.Map(courseDto, course);   
             await _context.SaveChangesAsync();
 
             result.Data = true;
-
             return result;
         }
 
@@ -233,11 +247,9 @@ namespace Tsi1.BusinessLayer.Services
             }
 
             _context.Courses.Remove(course);
-
             await _context.SaveChangesAsync();
 
             result.Data = course;
-
             return result;
         }
 
@@ -316,11 +328,9 @@ namespace Tsi1.BusinessLayer.Services
             }
 
             _context.ProfessorCourses.Remove(professorCourse);
-
             await _context.SaveChangesAsync();
 
             result.Data = true;
-
             return result;
         }
 
@@ -338,7 +348,6 @@ namespace Tsi1.BusinessLayer.Services
             var userDtos = _mapper.Map<List<UserPreviewDto>>(users);
 
             result.Data = userDtos;
-
             return result;
         }
 
@@ -366,5 +375,34 @@ namespace Tsi1.BusinessLayer.Services
 
             return result;
         }
+
+        public async Task<ServiceResult<bool>> CreateFromTemplate(CourseTemplateCreateDto courseTemplate, int tenantId)
+        {
+            var result = new ServiceResult<bool>();
+
+            var course = await _context.Courses.AsNoTracking()
+                .Include(x => x.Sections)
+                    .ThenInclude(x => x.SectionItems)
+                        .ThenInclude(x => x.Forum)
+                .FirstOrDefaultAsync(x => 
+                    x.TenantId == tenantId
+                    && x.IsTemplate
+                    && x.Id == courseTemplate.CourseTemplateId);
+
+            if (course == null)
+            {
+                result.HasError = true;
+                result.AddMessage(string.Format(ErrorMessages.CourseDoesNotExist, courseTemplate.CourseTemplateId));
+                return result;
+            }
+
+            var newCourse = _mapper.Map<Course>(course);
+            newCourse.Name = courseTemplate.Name;
+
+            _context.Add(newCourse);
+            await _context.SaveChangesAsync();
+
+            return result;
+        }
     }
 }
diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs
index 942858fad3a54d8c23bb6142258eb9bdf7e14b23..80c429198380aaf675c92b39bd57261dbda4fc5e 100644
--- a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs
+++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs
@@ -16,6 +16,7 @@ namespace Tsi1.DataLayer.Entities
         public int Id { get; set; }
         public string Name { get; set; }
         public int TenantId { get; set; }
+        public bool IsTemplate { get; set; }
 
         public Tenant Tenant { get; set; }
         public ICollection<StudentCourse> StudentCourses { get; set; }
diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/CourseConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/CourseConfiguration.cs
index 4cea40149d552d51d4c6fab8bc3d4ae20e5b3b48..0676afd111a856e4a50a9a00483498980418509f 100644
--- a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/CourseConfiguration.cs
+++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/CourseConfiguration.cs
@@ -20,6 +20,9 @@ namespace Tsi1.DataLayer.EntityConfiguration
                 .IsRequired()
                 .HasColumnType("character varying(50)");
 
+            builder.Property(x => x.IsTemplate)
+                .IsRequired();
+
             builder.HasOne(x => x.Tenant)
                 .WithMany(x => x.Courses)
                 .HasForeignKey(x => x.TenantId);
diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201112213633_course-template.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201112213633_course-template.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..506ca6417e5346d99fad772524f8ee8d1f69992b
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201112213633_course-template.Designer.cs
@@ -0,0 +1,611 @@
+// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using Tsi1.DataLayer;
+
+namespace Tsi1.DataLayer.Migrations
+{
+    [DbContext(typeof(Tsi1Context))]
+    [Migration("20201112213633_course-template")]
+    partial class coursetemplate
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
+                .HasAnnotation("ProductVersion", "3.1.4")
+                .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b =>
+                {
+                    b.Property<string>("ConnectionId")
+                        .HasColumnType("text");
+
+                    b.Property<string>("GroupName")
+                        .HasColumnType("text");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("ConnectionId");
+
+                    b.HasIndex("GroupName");
+
+                    b.ToTable("Connections");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<bool>("IsTemplate")
+                        .HasColumnType("boolean");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<int>("TenantId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("TenantId");
+
+                    b.HasIndex("Name", "TenantId")
+                        .IsUnique();
+
+                    b.ToTable("Courses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.File", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Path")
+                        .IsRequired()
+                        .HasColumnType("character varying(1000)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Path")
+                        .IsUnique();
+
+                    b.ToTable("Files");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Forums");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b =>
+                {
+                    b.Property<int>("ForumId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("ForumId", "UserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("ForumUsers");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Group", b =>
+                {
+                    b.Property<string>("Name")
+                        .HasColumnType("text");
+
+                    b.HasKey("Name");
+
+                    b.ToTable("Groups");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int>("ForumId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Title")
+                        .IsRequired()
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.HasIndex("ForumId", "Title")
+                        .IsUnique();
+
+                    b.ToTable("Posts");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Content")
+                        .IsRequired()
+                        .HasColumnType("character varying(10485760)");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int>("PostId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("PostId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("PostMessages");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<int>("TenantId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("TenantId");
+
+                    b.HasIndex("IdentityCard", "TenantId")
+                        .IsUnique();
+
+                    b.ToTable("Professors");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b =>
+                {
+                    b.Property<int>("ProfessorId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("ProfessorId", "CourseId");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("ProfessorCourses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("Sections");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<int?>("FileId")
+                        .HasColumnType("integer");
+
+                    b.Property<int?>("ForumId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("SectionId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("SectionItemTypeId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("FileId")
+                        .IsUnique();
+
+                    b.HasIndex("ForumId")
+                        .IsUnique();
+
+                    b.HasIndex("SectionId");
+
+                    b.HasIndex("SectionItemTypeId");
+
+                    b.ToTable("SectionItems");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItemType", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(100)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("SectionItemTypes");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<int>("Age")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<int>("TenantId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("TenantId");
+
+                    b.HasIndex("IdentityCard", "TenantId")
+                        .IsUnique();
+
+                    b.ToTable("Students");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b =>
+                {
+                    b.Property<int>("StudentId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("StudentId", "CourseId");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("StudentCourses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Tenant", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name")
+                        .IsUnique();
+
+                    b.ToTable("Tenants");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("FirstName")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("LastName")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<int?>("ProfessorId")
+                        .HasColumnType("integer");
+
+                    b.Property<int?>("StudentId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("TenantId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserTypeId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Username")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProfessorId")
+                        .IsUnique();
+
+                    b.HasIndex("StudentId")
+                        .IsUnique();
+
+                    b.HasIndex("TenantId");
+
+                    b.HasIndex("UserTypeId");
+
+                    b.HasIndex("Username", "TenantId")
+                        .IsUnique();
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.UserType", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name")
+                        .IsUnique();
+
+                    b.ToTable("UserTypes");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Group", "Group")
+                        .WithMany("Connections")
+                        .HasForeignKey("GroupName");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant")
+                        .WithMany("Courses")
+                        .HasForeignKey("TenantId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum")
+                        .WithMany("ForumUsers")
+                        .HasForeignKey("ForumId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("ForumUsers")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum")
+                        .WithMany("Posts")
+                        .HasForeignKey("ForumId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("Posts")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Post", "Post")
+                        .WithMany("PostMessages")
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("PostMessages")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant")
+                        .WithMany("Professors")
+                        .HasForeignKey("TenantId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("ProfessorCourses")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor")
+                        .WithMany("ProfessorCourses")
+                        .HasForeignKey("ProfessorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("Sections")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.File", "File")
+                        .WithOne("SectionItem")
+                        .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "FileId");
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum")
+                        .WithOne("SectionItem")
+                        .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "ForumId");
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Section", "Section")
+                        .WithMany("SectionItems")
+                        .HasForeignKey("SectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.SectionItemType", "SectionItemType")
+                        .WithMany("SectionItems")
+                        .HasForeignKey("SectionItemTypeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant")
+                        .WithMany("Students")
+                        .HasForeignKey("TenantId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("StudentCourses")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Student", "Student")
+                        .WithMany("StudentCourses")
+                        .HasForeignKey("StudentId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor")
+                        .WithOne("User")
+                        .HasForeignKey("Tsi1.DataLayer.Entities.User", "ProfessorId");
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Student", "Student")
+                        .WithOne("User")
+                        .HasForeignKey("Tsi1.DataLayer.Entities.User", "StudentId");
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant")
+                        .WithMany("Users")
+                        .HasForeignKey("TenantId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.UserType", "UserType")
+                        .WithMany()
+                        .HasForeignKey("UserTypeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201112213633_course-template.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201112213633_course-template.cs
new file mode 100644
index 0000000000000000000000000000000000000000..36d655ab060b7b684c4e175907ac20e21b3b5625
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201112213633_course-template.cs
@@ -0,0 +1,23 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Tsi1.DataLayer.Migrations
+{
+    public partial class coursetemplate : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn<bool>(
+                name: "IsTemplate",
+                table: "Courses",
+                nullable: false,
+                defaultValue: false);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "IsTemplate",
+                table: "Courses");
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs
index e661f62fc22750b698b1da14d4ac889d01af8e80..e07d8848bc5c062202f58b780c9384a0dbf80650 100644
--- a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs
+++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs
@@ -44,6 +44,9 @@ namespace Tsi1.DataLayer.Migrations
                         .HasColumnType("integer")
                         .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
 
+                    b.Property<bool>("IsTemplate")
+                        .HasColumnType("boolean");
+
                     b.Property<string>("Name")
                         .IsRequired()
                         .HasColumnType("character varying(50)");