Changeset fa0fbaf for KernelRecordsMVC.Web/Controllers/AdminController.cs
- Timestamp:
- 09/01/26 06:11:34 (4 weeks ago)
- Branches:
- main
- Children:
- d2eccb3
- Parents:
- 08aefc6
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
KernelRecordsMVC.Web/Controllers/AdminController.cs
r08aefc6 rfa0fbaf 1 using Microsoft.AspNetCore.Mvc; 1 using KernelRecordsMVC.Application.ViewModels; 2 using KernelRecordsMVC.Domain.Enums; 3 using KernelRecordsMVC.Infrastructure.Data; 4 using KernelRecordsMVC.Models; 5 using Microsoft.AspNetCore.Mvc; 2 6 using Microsoft.EntityFrameworkCore; 3 using KernelRecordsMVC.Data; 4 using KernelRecordsMVC.Models; 5 using KernelRecordsMVC.Domain.Enums; 6 using KernelRecordsMVC.Application.ViewModels; 7 using Microsoft.AspNetCore.Http; 8 9 namespace KernelRecordsMVC.Controllers; 7 8 namespace KernelRecordsMVC.Web.Controllers; 10 9 11 10 public class AdminController : Controller … … 19 18 20 19 21 // ========================================== 20 // ========================================================= 22 21 // ADMIN DASHBOARD 23 // ========================================== 22 // ========================================================= 24 23 25 24 [HttpGet] … … 29 28 return Forbid(); 30 29 30 31 ViewBag.ProductCount = 32 _context.Products.Count(); 33 34 ViewBag.ReleaseCount = 35 _context.Releases.Count(); 36 37 ViewBag.OutOfStockCount = 38 _context.Products.Count(x => 39 x.Stock <= 0); 40 41 ViewBag.LowStockCount = 42 _context.Products.Count(x => 43 x.Stock > 0 && 44 x.Stock <= 5); 45 46 31 47 return View(); 32 48 } 33 49 34 50 35 // ========================================== 36 // UC008 37 // NEW PRODUCT - GET 38 // ========================================== 51 // ========================================================= 52 // PRODUCTS 53 // ========================================================= 54 55 [HttpGet] 56 public IActionResult Products() 57 { 58 if (!IsProductManager()) 59 return Forbid(); 60 61 62 var products = _context.Products 63 .Include(p => p.Release) 64 .OrderBy(p => p.Release.Title) 65 .ThenBy(p => p.Format) 66 .ToList(); 67 68 69 return View(products); 70 } 71 72 73 // ========================================================= 74 // CREATE PRODUCT - GET 75 // ========================================================= 39 76 40 77 [HttpGet] … … 44 81 return Forbid(); 45 82 46 ViewBag.Releases = _context.Releases 47 .OrderBy(x => x.Title)48 .ToList(); 49 50 return View( new CreateProductViewModel());51 }52 53 54 // ========================================== 55 // UC00856 // NEWPRODUCT - POST57 // ========================================== 83 84 LoadReleases(); 85 86 87 return View( 88 new CreateProductViewModel()); 89 } 90 91 92 // ========================================================= 93 // CREATE PRODUCT - POST 94 // ========================================================= 58 95 59 96 [HttpPost] … … 65 102 return Forbid(); 66 103 104 67 105 if (!ModelState.IsValid) 68 106 { 69 107 LoadReleases(); 108 70 109 return View(model); 71 110 } 72 111 73 112 74 // Make sure the release actually exists.75 113 var release = _context.Releases 76 114 .FirstOrDefault(x => 77 115 x.ReleaseId == model.ReleaseId); 78 116 117 79 118 if (release == null) 80 119 { 81 120 ModelState.AddModelError( 82 "ReleaseId",121 nameof(model.ReleaseId), 83 122 "The selected release does not exist."); 84 123 124 85 125 LoadReleases(); 126 127 86 128 return View(model); 87 129 } 88 130 89 131 90 // Don't allow duplicate format for91 // the same release.92 var alreadyExists = _context.Products.Any(p =>93 p.ReleaseId == model.ReleaseId &&94 p.Format == model.Format); 132 var alreadyExists = 133 _context.Products.Any(p => 134 p.ReleaseId == model.ReleaseId && 135 p.Format == model.Format); 136 95 137 96 138 if (alreadyExists) 97 139 { 98 140 ModelState.AddModelError( 99 "Format",141 nameof(model.Format), 100 142 "This release already has a product in this format."); 101 143 144 102 145 LoadReleases(); 146 147 103 148 return View(model); 104 149 } 105 150 106 151 107 var product = new Product 108 { 109 ProductId = GetNextProductId(), 110 111 ReleaseId = model.ReleaseId, 112 113 Format = model.Format, 114 115 Price = model.Price, 116 117 ProductDescription = 118 model.ProductDescription, 119 120 Stock = model.Stock 121 }; 122 123 124 _context.Products.Add(product); 125 126 _context.SaveChanges(); 127 128 129 // Record the modification. 130 CreateModification( 131 ModificationType.CREATE, 132 product.ProductId); 133 134 135 TempData["Success"] = 136 "Product created successfully."; 137 138 139 return RedirectToAction( 140 nameof(Index)); 141 } 142 143 144 // ========================================== 145 // HELPERS 146 // ========================================== 152 using var transaction = 153 _context.Database.BeginTransaction(); 154 155 156 try 157 { 158 var product = new Product 159 { 160 ProductId = 161 GetNextProductId(), 162 163 ReleaseId = 164 model.ReleaseId, 165 166 Format = 167 model.Format, 168 169 Price = 170 model.Price, 171 172 ProductDescription = 173 model.ProductDescription, 174 175 Stock = 176 model.Stock 177 }; 178 179 180 _context.Products.Add(product); 181 182 _context.SaveChanges(); 183 184 185 CreateModification( 186 ModificationType.CREATE, 187 product.ProductId); 188 189 190 transaction.Commit(); 191 192 193 TempData["Success"] = 194 $"{release.Title} ({product.Format}) was created successfully."; 195 196 197 return RedirectToAction( 198 nameof(Products)); 199 } 200 catch 201 { 202 transaction.Rollback(); 203 204 throw; 205 } 206 } 207 208 209 // ========================================================= 210 // EDIT PRODUCT - GET 211 // ========================================================= 212 213 [HttpGet] 214 public IActionResult EditProduct(long id) 215 { 216 if (!IsProductManager()) 217 return Forbid(); 218 219 220 var product = _context.Products 221 .Include(p => p.Release) 222 .FirstOrDefault(p => 223 p.ProductId == id); 224 225 226 if (product == null) 227 return NotFound(); 228 229 230 var model = 231 new EditProductViewModel 232 { 233 ProductId = 234 product.ProductId, 235 236 ReleaseId = 237 product.ReleaseId, 238 239 ReleaseTitle = 240 product.Release.Title, 241 242 Format = 243 product.Format, 244 245 Price = 246 product.Price, 247 248 ProductDescription = 249 product.ProductDescription, 250 251 Stock = 252 product.Stock, 253 254 ModificationType = 255 ModificationType.UPDATE 256 }; 257 258 259 return View(model); 260 } 261 262 263 // ========================================================= 264 // EDIT PRODUCT - POST 265 // ========================================================= 266 267 [HttpPost] 268 [ValidateAntiForgeryToken] 269 public IActionResult EditProduct( 270 EditProductViewModel model) 271 { 272 if (!IsProductManager()) 273 return Forbid(); 274 275 276 var product = _context.Products 277 .Include(p => p.Release) 278 .FirstOrDefault(p => 279 p.ProductId == model.ProductId); 280 281 282 if (product == null) 283 return NotFound(); 284 285 286 // These values come from the database. 287 model.ReleaseId = 288 product.ReleaseId; 289 290 model.ReleaseTitle = 291 product.Release.Title; 292 293 model.Format = 294 product.Format; 295 296 297 // Display-only fields should not block 298 // validation of the submitted form. 299 ModelState.Remove( 300 nameof(model.ReleaseId)); 301 302 ModelState.Remove( 303 nameof(model.ReleaseTitle)); 304 305 ModelState.Remove( 306 nameof(model.Format)); 307 308 309 // ===================================================== 310 // DISCOUNT VALIDATION 311 // ===================================================== 312 313 if (model.ModificationType == 314 ModificationType.DISCOUNT) 315 { 316 if (!model.Discount.HasValue) 317 { 318 ModelState.AddModelError( 319 nameof(model.Discount), 320 "Please enter a discount percentage."); 321 } 322 else if ( 323 model.Discount.Value <= 0 || 324 model.Discount.Value >= 100) 325 { 326 ModelState.AddModelError( 327 nameof(model.Discount), 328 "Discount must be greater than 0 and less than 100."); 329 } 330 } 331 332 333 if (!ModelState.IsValid) 334 return View(model); 335 336 337 using var transaction = 338 _context.Database.BeginTransaction(); 339 340 341 try 342 { 343 // ================================================= 344 // APPLY DISCOUNT 345 // ================================================= 346 347 if (model.ModificationType == 348 ModificationType.DISCOUNT) 349 { 350 var discountPercentage = 351 model.Discount!.Value; 352 353 354 var oldPrice = 355 product.Price; 356 357 358 var discountAmount = 359 oldPrice * 360 (discountPercentage / 100m); 361 362 363 var newPrice = 364 oldPrice - discountAmount; 365 366 367 newPrice = 368 Math.Round( 369 newPrice, 370 2, 371 MidpointRounding.AwayFromZero); 372 373 374 // Product.Price becomes the 375 // actual current sale price. 376 product.Price = 377 newPrice; 378 379 380 _context.Products.Update( 381 product); 382 383 _context.SaveChanges(); 384 385 386 CreateModification( 387 ModificationType.DISCOUNT, 388 product.ProductId, 389 discountPercentage); 390 391 392 transaction.Commit(); 393 394 395 TempData["Success"] = 396 $"{discountPercentage:0.##}% discount applied. " + 397 $"Price changed from {oldPrice:C} to {newPrice:C}."; 398 399 400 return RedirectToAction( 401 nameof(Products)); 402 } 403 404 405 // ================================================= 406 // NORMAL UPDATE 407 // ================================================= 408 409 product.Price = 410 model.Price; 411 412 product.ProductDescription = 413 model.ProductDescription; 414 415 product.Stock = 416 model.Stock; 417 418 419 _context.Products.Update( 420 product); 421 422 _context.SaveChanges(); 423 424 425 CreateModification( 426 ModificationType.UPDATE, 427 product.ProductId); 428 429 430 transaction.Commit(); 431 432 433 TempData["Success"] = 434 $"{product.Release.Title} was updated successfully."; 435 436 437 return RedirectToAction( 438 nameof(Products)); 439 } 440 catch 441 { 442 transaction.Rollback(); 443 444 throw; 445 } 446 } 447 448 449 // ========================================================= 450 // CREATE RELEASE - GET 451 // ========================================================= 452 453 [HttpGet] 454 public IActionResult CreateRelease() 455 { 456 if (!IsAdmin()) 457 return Forbid(); 458 459 460 LoadArtists(); 461 462 463 var model = 464 new CreateReleaseViewModel 465 { 466 ReleaseDate = 467 DateTime.Today, 468 469 ReleaseType = 470 "ALBUM", 471 472 // Start an album with one empty track. 473 Tracks = 474 new List<CreateTrackViewModel> 475 { 476 new CreateTrackViewModel() 477 } 478 }; 479 480 481 return View(model); 482 } 483 484 485 // ========================================================= 486 // CREATE RELEASE - POST 487 // ========================================================= 488 489 [HttpPost] 490 [ValidateAntiForgeryToken] 491 public IActionResult CreateRelease( 492 CreateReleaseViewModel model) 493 { 494 if (!IsAdmin()) 495 return Forbid(); 496 497 498 // ===================================================== 499 // RELEASE TYPE VALIDATION 500 // ===================================================== 501 502 if (model.ReleaseType != "ALBUM" && 503 model.ReleaseType != "SINGLE") 504 { 505 ModelState.AddModelError( 506 nameof(model.ReleaseType), 507 "Please select Album or Single."); 508 } 509 510 511 // ===================================================== 512 // MAIN ARTIST VALIDATION 513 // ===================================================== 514 515 var mainArtistExists = 516 _context.Artists.Any(a => 517 a.ArtistId == 518 model.MainArtistId); 519 520 521 if (!mainArtistExists) 522 { 523 ModelState.AddModelError( 524 nameof(model.MainArtistId), 525 "Please select a valid main artist."); 526 } 527 528 529 // ===================================================== 530 // FEATURED ARTISTS 531 // ===================================================== 532 533 model.FeaturedArtistIds ??= 534 new List<long>(); 535 536 537 model.FeaturedArtistIds = 538 model.FeaturedArtistIds 539 .Distinct() 540 .ToList(); 541 542 543 // Do not allow the main artist 544 // to also be a featured artist. 545 model.FeaturedArtistIds.Remove( 546 model.MainArtistId); 547 548 549 // Validate that featured artists exist. 550 if (model.FeaturedArtistIds.Count > 0) 551 { 552 var validFeaturedArtistCount = 553 _context.Artists.Count(a => 554 model.FeaturedArtistIds 555 .Contains(a.ArtistId)); 556 557 558 if (validFeaturedArtistCount != 559 model.FeaturedArtistIds.Count) 560 { 561 ModelState.AddModelError( 562 nameof(model.FeaturedArtistIds), 563 "One or more featured artists are invalid."); 564 } 565 } 566 567 568 // ===================================================== 569 // SINGLE VALIDATION 570 // ===================================================== 571 572 if (model.ReleaseType == "SINGLE") 573 { 574 if (string.IsNullOrWhiteSpace( 575 model.SingleDuration)) 576 { 577 ModelState.AddModelError( 578 nameof(model.SingleDuration), 579 "Duration is required for a single."); 580 } 581 } 582 583 584 // ===================================================== 585 // ALBUM VALIDATION 586 // ===================================================== 587 588 if (model.ReleaseType == "ALBUM") 589 { 590 model.Tracks ??= 591 new List<CreateTrackViewModel>(); 592 593 594 // Remove completely empty rows. 595 model.Tracks = 596 model.Tracks 597 .Where(t => 598 !string.IsNullOrWhiteSpace( 599 t.SongName) || 600 !string.IsNullOrWhiteSpace( 601 t.SongDuration)) 602 .ToList(); 603 604 605 if (model.Tracks.Count == 0) 606 { 607 ModelState.AddModelError( 608 nameof(model.Tracks), 609 "An album must contain at least one track."); 610 } 611 612 613 for (var i = 0; 614 i < model.Tracks.Count; 615 i++) 616 { 617 var track = 618 model.Tracks[i]; 619 620 621 if (string.IsNullOrWhiteSpace( 622 track.SongName)) 623 { 624 ModelState.AddModelError( 625 $"Tracks[{i}].SongName", 626 "Track name is required."); 627 } 628 629 630 if (string.IsNullOrWhiteSpace( 631 track.SongDuration)) 632 { 633 ModelState.AddModelError( 634 $"Tracks[{i}].SongDuration", 635 "Track duration is required."); 636 } 637 638 639 track.ArtistIds ??= 640 new List<long>(); 641 642 643 track.ArtistIds = 644 track.ArtistIds 645 .Distinct() 646 .ToList(); 647 648 649 // Validate selected track artists. 650 if (track.ArtistIds.Count > 0) 651 { 652 var validTrackArtistCount = 653 _context.Artists.Count(a => 654 track.ArtistIds.Contains( 655 a.ArtistId)); 656 657 658 if (validTrackArtistCount != 659 track.ArtistIds.Count) 660 { 661 ModelState.AddModelError( 662 $"Tracks[{i}].ArtistIds", 663 "One or more selected track artists are invalid."); 664 } 665 } 666 } 667 } 668 669 670 if (!ModelState.IsValid) 671 { 672 LoadArtists(); 673 674 return View(model); 675 } 676 677 678 using var transaction = 679 _context.Database.BeginTransaction(); 680 681 682 try 683 { 684 // ================================================= 685 // CREATE RELEASE 686 // ================================================= 687 688 var release = 689 new Release 690 { 691 ReleaseId = 692 GetNextReleaseId(), 693 694 Title = 695 model.Title.Trim(), 696 697 RecordLabel = 698 string.IsNullOrWhiteSpace( 699 model.RecordLabel) 700 ? null 701 : model.RecordLabel.Trim(), 702 703 Genre = 704 model.Genre.Trim(), 705 706 ReleaseDate = 707 model.ReleaseDate, 708 709 CoverPhoto = 710 model.CoverPhoto.Trim() 711 }; 712 713 714 _context.Releases.Add( 715 release); 716 717 _context.SaveChanges(); 718 719 720 // ================================================= 721 // MAIN RELEASE ARTIST 722 // ================================================= 723 724 var mainReleaseArtist = 725 new ReleaseArtist 726 { 727 ReleaseId = 728 release.ReleaseId, 729 730 ArtistId = 731 model.MainArtistId, 732 733 ReleaseOrdinal = 1, 734 735 Type = 736 ArtistReleaseType.MAIN 737 }; 738 739 740 _context.ReleaseArtists.Add( 741 mainReleaseArtist); 742 743 744 // ================================================= 745 // FEATURED RELEASE ARTISTS 746 // ================================================= 747 748 long releaseOrdinal = 2; 749 750 751 foreach (var artistId 752 in model.FeaturedArtistIds) 753 { 754 var featuredArtist = 755 new ReleaseArtist 756 { 757 ReleaseId = 758 release.ReleaseId, 759 760 ArtistId = 761 artistId, 762 763 ReleaseOrdinal = 764 releaseOrdinal++, 765 766 Type = 767 ArtistReleaseType.FEATURE 768 }; 769 770 771 _context.ReleaseArtists.Add( 772 featuredArtist); 773 } 774 775 776 _context.SaveChanges(); 777 778 779 // ================================================= 780 // ALBUM 781 // ================================================= 782 783 if (model.ReleaseType == "ALBUM") 784 { 785 var album = 786 new Album 787 { 788 ReleaseId = 789 release.ReleaseId 790 }; 791 792 793 _context.Albums.Add( 794 album); 795 796 _context.SaveChanges(); 797 798 799 // ============================================= 800 // TRACKS 801 // ============================================= 802 803 foreach (var trackModel 804 in model.Tracks) 805 { 806 var song = 807 new Song 808 { 809 SongId = 810 GetNextSongId(), 811 812 SongName = 813 trackModel 814 .SongName 815 .Trim(), 816 817 SongDuration = 818 trackModel 819 .SongDuration 820 .Trim() 821 }; 822 823 824 _context.Songs.Add( 825 song); 826 827 _context.SaveChanges(); 828 829 830 // ========================================= 831 // LINK SONG TO ALBUM 832 // ========================================= 833 834 var albumSong = 835 new AlbumSong 836 { 837 AlbumId = 838 release.ReleaseId, 839 840 SongId = 841 song.SongId 842 }; 843 844 845 _context.AlbumSongs.Add( 846 albumSong); 847 848 849 // ========================================= 850 // SONG ARTISTS 851 // ========================================= 852 853 var trackArtistIds = 854 trackModel.ArtistIds 855 .Distinct() 856 .ToList(); 857 858 859 // If no track artists were selected, 860 // automatically use the release's 861 // main artist. 862 if (trackArtistIds.Count == 0) 863 { 864 trackArtistIds.Add( 865 model.MainArtistId); 866 } 867 868 869 long songOrdinal = 1; 870 871 872 foreach (var artistId 873 in trackArtistIds) 874 { 875 var songArtist = 876 new SongArtist 877 { 878 SongId = 879 song.SongId, 880 881 ArtistId = 882 artistId, 883 884 SongOrdinal = 885 songOrdinal++ 886 }; 887 888 889 _context.SongArtists.Add( 890 songArtist); 891 } 892 893 894 _context.SaveChanges(); 895 } 896 } 897 898 899 // ================================================= 900 // SINGLE 901 // ================================================= 902 903 else 904 { 905 var single = 906 new SingleRelease 907 { 908 ReleaseId = 909 release.ReleaseId, 910 911 Duration = 912 model.SingleDuration! 913 .Trim() 914 }; 915 916 917 _context.SingleReleases.Add( 918 single); 919 920 _context.SaveChanges(); 921 } 922 923 924 transaction.Commit(); 925 926 927 TempData["Success"] = 928 $"{release.Title} was created successfully."; 929 930 931 return RedirectToAction( 932 nameof(Index)); 933 } 934 catch 935 { 936 transaction.Rollback(); 937 938 throw; 939 } 940 } 941 942 943 // ========================================================= 944 // AUTHORIZATION HELPERS 945 // ========================================================= 147 946 148 947 private bool IsAdmin() 149 948 { 150 949 return HttpContext.Session 151 .GetString("Role") == "Admin"; 950 .GetString("Role") == 951 "Admin"; 152 952 } 153 953 … … 155 955 private bool IsProductManager() 156 956 { 157 var role = HttpContext.Session 158 .GetString("Role"); 159 160 var adminType = HttpContext.Session 161 .GetString("AdminType"); 957 var role = 958 HttpContext.Session 959 .GetString("Role"); 960 961 var adminType = 962 HttpContext.Session 963 .GetString("AdminType"); 964 162 965 163 966 return role == "Admin" && 164 (adminType == "PRODUCT_MANAGER" || 165 adminType == "SUPER_ADMIN"); 166 } 167 967 ( 968 adminType == "PRODUCT_MANAGER" || 969 adminType == "SUPER_ADMIN" 970 ); 971 } 972 973 974 // ========================================================= 975 // CURRENT ADMIN ID 976 // ========================================================= 168 977 169 978 private long? GetCurrentUserId() 170 979 { 171 var value = HttpContext.Session 172 .GetString("UserId"); 173 174 if (long.TryParse(value, out var userId)) 175 return userId; 176 177 return null; 178 } 179 980 var userId = 981 HttpContext.Session 982 .GetInt32("UserId"); 983 984 985 if (!userId.HasValue) 986 return null; 987 988 989 return userId.Value; 990 } 991 992 993 // ========================================================= 994 // LOAD RELEASES 995 // ========================================================= 996 997 private void LoadReleases() 998 { 999 ViewBag.Releases = 1000 _context.Releases 1001 .OrderBy(x => 1002 x.Title) 1003 .ToList(); 1004 } 1005 1006 1007 // ========================================================= 1008 // LOAD ARTISTS 1009 // ========================================================= 1010 1011 private void LoadArtists() 1012 { 1013 ViewBag.Artists = 1014 _context.Artists 1015 .OrderBy(a => 1016 a.ArtistName) 1017 .ToList(); 1018 } 1019 1020 1021 // ========================================================= 1022 // NEXT PRODUCT ID 1023 // ========================================================= 180 1024 181 1025 private long GetNextProductId() 182 1026 { 183 var maxId = _context.Products 184 .Select(x => (long?)x.ProductId) 185 .Max(); 1027 var maxId = 1028 _context.Products 1029 .Select(x => 1030 (long?)x.ProductId) 1031 .Max(); 1032 186 1033 187 1034 return (maxId ?? 0) + 1; … … 189 1036 190 1037 191 private void LoadReleases() 192 { 193 ViewBag.Releases = _context.Releases 194 .OrderBy(x => x.Title) 195 .ToList(); 196 } 197 1038 // ========================================================= 1039 // NEXT RELEASE ID 1040 // ========================================================= 1041 1042 private long GetNextReleaseId() 1043 { 1044 var maxId = 1045 _context.Releases 1046 .Select(x => 1047 (long?)x.ReleaseId) 1048 .Max(); 1049 1050 1051 return (maxId ?? 0) + 1; 1052 } 1053 1054 1055 // ========================================================= 1056 // NEXT SONG ID 1057 // ========================================================= 1058 1059 private long GetNextSongId() 1060 { 1061 var maxId = 1062 _context.Songs 1063 .Select(x => 1064 (long?)x.SongId) 1065 .Max(); 1066 1067 1068 return (maxId ?? 0) + 1; 1069 } 1070 1071 1072 // ========================================================= 1073 // NEXT MODIFICATION ID 1074 // ========================================================= 1075 1076 private long GetNextModificationId() 1077 { 1078 var maxId = 1079 _context.Modifications 1080 .Select(x => 1081 (long?)x.ModificationId) 1082 .Max(); 1083 1084 1085 return (maxId ?? 0) + 1; 1086 } 1087 1088 1089 // ========================================================= 1090 // CREATE MODIFICATION RECORD 1091 // ========================================================= 198 1092 199 1093 private void CreateModification( … … 202 1096 decimal? discount = null) 203 1097 { 204 var adminId = GetCurrentUserId(); 1098 var adminId = 1099 GetCurrentUserId(); 1100 205 1101 206 1102 if (adminId == null) 207 return; 208 209 210 var modification = new Modification 211 { 212 ModificationId = 213 GetNextModificationId(), 214 215 AdminId = adminId.Value, 216 217 DateModified = DateTime.Today, 218 219 TypeOfModification = type, 220 221 Discount = discount 222 }; 223 224 225 _context.Modifications.Add(modification); 1103 { 1104 throw new InvalidOperationException( 1105 "The current admin could not be identified."); 1106 } 1107 1108 1109 var modification = 1110 new Modification 1111 { 1112 ModificationId = 1113 GetNextModificationId(), 1114 1115 AdminId = 1116 adminId.Value, 1117 1118 DateModified = 1119 DateTime.Today, 1120 1121 TypeOfModification = 1122 type, 1123 1124 Discount = 1125 discount 1126 }; 1127 1128 1129 _context.Modifications.Add( 1130 modification); 226 1131 227 1132 _context.SaveChanges(); … … 234 1139 modification.ModificationId, 235 1140 236 ProductId = productId 1141 ProductId = 1142 productId 237 1143 }; 238 1144 … … 243 1149 _context.SaveChanges(); 244 1150 } 245 246 247 private long GetNextModificationId()248 {249 var maxId = _context.Modifications250 .Select(x => (long?)x.ModificationId)251 .Max();252 253 return (maxId ?? 0) + 1;254 }255 // ==========================================256 // UC009257 // MODIFY PRODUCT - GET258 // ==========================================259 260 [HttpGet]261 public IActionResult EditProduct(long id)262 {263 if (!IsProductManager())264 return Forbid();265 266 var product = _context.Products267 .Include(p => p.Release)268 .FirstOrDefault(p => p.ProductId == id);269 270 if (product == null)271 return NotFound();272 273 var model = new EditProductViewModel274 {275 ProductId = product.ProductId,276 ReleaseId = product.ReleaseId,277 ReleaseTitle = product.Release.Title,278 Format = product.Format,279 Price = product.Price,280 ProductDescription = product.ProductDescription,281 Stock = product.Stock282 };283 284 return View(model);285 }286 // ==========================================287 // UC009288 // MODIFY PRODUCT - POST289 // ==========================================290 291 [HttpPost]292 [ValidateAntiForgeryToken]293 public IActionResult EditProduct(294 EditProductViewModel model)295 {296 if (!IsProductManager())297 return Forbid();298 299 var product = _context.Products300 .Include(p => p.Release)301 .FirstOrDefault(p =>302 p.ProductId == model.ProductId);303 304 if (product == null)305 return NotFound();306 307 if (!ModelState.IsValid)308 {309 model.ReleaseTitle = product.Release.Title;310 model.ReleaseId = product.ReleaseId;311 model.Format = product.Format;312 313 return View(model);314 }315 316 317 // ==========================================318 // DISCOUNT319 // ==========================================320 321 if (model.ModificationType ==322 ModificationType.DISCOUNT)323 {324 if (!model.Discount.HasValue)325 {326 ModelState.AddModelError(327 "Discount",328 "Please enter a discount percentage.");329 330 model.ReleaseTitle = product.Release.Title;331 model.ReleaseId = product.ReleaseId;332 model.Format = product.Format;333 334 return View(model);335 }336 337 product.Price =338 product.Price *339 (1 - model.Discount.Value / 100m);340 }341 else342 {343 // ==========================================344 // NORMAL UPDATE345 // ==========================================346 347 product.Price = model.Price;348 349 product.ProductDescription =350 model.ProductDescription;351 352 product.Stock = model.Stock;353 }354 355 356 _context.SaveChanges();357 358 359 // ==========================================360 // RECORD MODIFICATION361 // ==========================================362 363 CreateModification(364 model.ModificationType,365 product.ProductId,366 model.Discount);367 368 369 TempData["Success"] =370 "Product modified successfully.";371 372 return RedirectToAction(nameof(Index));373 1151 } 374 [HttpGet]375 public IActionResult Products()376 {377 if (!IsProductManager())378 return Forbid();379 380 var products = _context.Products381 .Include(p => p.Release)382 .OrderBy(p => p.Release.Title)383 .ThenBy(p => p.Format)384 .ToList();385 386 return View(products);387 }388 }
Note:
See TracChangeset
for help on using the changeset viewer.
