feat: reviews

This commit is contained in:
Damien Ostler 2024-02-27 19:58:19 -05:00
parent 4a368fa6a4
commit 660512dbd5
12 changed files with 712 additions and 8 deletions

View File

@ -741,6 +741,31 @@ public class RequestsController : Controller
return Ok(new {paymentUrl = request.PaymentUrl});
}
[Authorize("write:request")]
[HttpPut]
[Route("Customer/{requestId:int}/Review")]
public async Task<IActionResult> ReviewRequest(int requestId, RequestReviewModel model)
{
var userId = User.GetUserId();
var request = await _dbContext.Requests
.Where(x=>x.UserId==userId)
.FirstOrDefaultAsync(x=>x.Id==requestId);
if(request==null)
return NotFound();
if(request.Completed==false || request.Accepted==false || request.Reviewed )
return BadRequest("Request has not been completed or accepted or has already been reviewed.");
request.Reviewed = true;
request.ReviewDate = DateTime.UtcNow;
request.ReviewMessage = model.Message;
request.Rating = model.Rating;
_dbContext.Entry(request).State = EntityState.Modified;
await _dbContext.SaveChangesAsync();
var result = request.ToModel();
return Ok(result);
}
[Authorize("write:request")]
[HttpPost]
[Route("Artist/{requestId:int}/Asset")]

View File

@ -17,7 +17,10 @@ public class Request
public DateTime? PaidDate { get; set; } = null!;
public bool Completed { get; set; } = false;
public DateTime? CompletedDate { get; set; }
public bool Reviewed { get; set; }
public DateTime? ReviewDate { get; set; }
public string? ReviewMessage { get; set; }
public double? Rating { get; set; }
public virtual User User { get; set; } = null!;
public virtual UserArtist Artist { get; set; } = null!;

View File

@ -0,0 +1,589 @@
// <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 comissions.app.database;
#nullable disable
namespace comissions.app.api.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20240228005126_reviews")]
partial class reviews
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("comissions.app.database.Entities.ArtistPageSettings", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("ArtistId")
.HasColumnType("integer");
b.Property<string>("BackgroundColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DescriptionBackgroundColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DescriptionHeaderColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DescriptionHeaderImageUrl")
.IsRequired()
.HasColumnType("text");
b.Property<int>("DescriptionHeaderSize")
.HasColumnType("integer");
b.Property<string>("DescriptionHeaderText")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("DescriptionHeaderUseImage")
.HasColumnType("boolean");
b.Property<string>("DescriptionTextColor")
.IsRequired()
.HasColumnType("text");
b.Property<int>("DescriptionTextSize")
.HasColumnType("integer");
b.Property<string>("HeaderColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("HeaderImageUrl")
.IsRequired()
.HasColumnType("text");
b.Property<int>("HeaderTextSize")
.HasColumnType("integer");
b.Property<bool>("HeaderUseImage")
.HasColumnType("boolean");
b.Property<string>("PortfolioBackgroundColor")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PortfolioColumns")
.HasColumnType("integer");
b.Property<bool>("PortfolioEnabledScrolling")
.HasColumnType("boolean");
b.Property<bool>("PortfolioMasonry")
.HasColumnType("boolean");
b.Property<int>("PortfolioMaximumSize")
.HasColumnType("integer");
b.Property<string>("PortfolionHeaderColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PortfolionHeaderImageUrl")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PortfolionHeaderSize")
.HasColumnType("integer");
b.Property<string>("PortfolionHeaderText")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("PortfolionHeaderUseImage")
.HasColumnType("boolean");
b.Property<string>("RequestBackgroundColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("RequestButtonBGColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("RequestButtonHoverBGColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("RequestButtonHoverTextColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("RequestButtonTextColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("RequestHeaderColor")
.IsRequired()
.HasColumnType("text");
b.Property<string>("RequestHeaderImageUrl")
.IsRequired()
.HasColumnType("text");
b.Property<int>("RequestHeaderSize")
.HasColumnType("integer");
b.Property<string>("RequestHeaderText")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("RequestHeaderUseImage")
.HasColumnType("boolean");
b.Property<string>("RequestTermsColor")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ArtistId")
.IsUnique();
b.ToTable("ArtistPageSettings");
});
modelBuilder.Entity("comissions.app.database.Entities.ArtistPortfolioPiece", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("ArtistId")
.HasColumnType("integer");
b.Property<string>("FileReference")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ArtistId");
b.ToTable("ArtistPortfolioPieces");
});
modelBuilder.Entity("comissions.app.database.Entities.ArtistRequest", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("Accepted")
.HasColumnType("boolean");
b.Property<DateTime?>("AcceptedDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("RequestDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Review")
.HasColumnType("text");
b.Property<double?>("ReviewRating")
.HasColumnType("double precision");
b.Property<bool>("Reviewed")
.HasColumnType("boolean");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("ArtistRequests");
});
modelBuilder.Entity("comissions.app.database.Entities.Request", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("Accepted")
.HasColumnType("boolean");
b.Property<DateTime?>("AcceptedDate")
.HasColumnType("timestamp with time zone");
b.Property<decimal>("Amount")
.HasColumnType("numeric");
b.Property<int>("ArtistId")
.HasColumnType("integer");
b.Property<bool>("Completed")
.HasColumnType("boolean");
b.Property<DateTime?>("CompletedDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("Declined")
.HasColumnType("boolean");
b.Property<DateTime?>("DeclinedDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("Paid")
.HasColumnType("boolean");
b.Property<DateTime?>("PaidDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("PaymentUrl")
.HasColumnType("text");
b.Property<double?>("Rating")
.HasColumnType("double precision");
b.Property<DateTime>("RequestDate")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("ReviewDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ReviewMessage")
.HasColumnType("text");
b.Property<bool>("Reviewed")
.HasColumnType("boolean");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ArtistId");
b.HasIndex("UserId");
b.ToTable("Requests");
});
modelBuilder.Entity("comissions.app.database.Entities.RequestAsset", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("FileReference")
.IsRequired()
.HasColumnType("text");
b.Property<int>("RequestId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("RequestId");
b.ToTable("RequestAssets");
});
modelBuilder.Entity("comissions.app.database.Entities.RequestReference", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("FileReference")
.IsRequired()
.HasColumnType("text");
b.Property<int>("RequestId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("RequestId");
b.ToTable("RequestReferences");
});
modelBuilder.Entity("comissions.app.database.Entities.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("BanAdminId")
.HasColumnType("text");
b.Property<bool>("Banned")
.HasColumnType("boolean");
b.Property<DateTime?>("BannedDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("BannedReason")
.HasColumnType("text");
b.Property<string>("Biography")
.IsRequired()
.HasColumnType("text");
b.Property<string>("DisplayName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SuspendAdminId")
.HasColumnType("text");
b.Property<bool>("Suspended")
.HasColumnType("boolean");
b.Property<DateTime?>("SuspendedDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("SuspendedReason")
.HasColumnType("text");
b.Property<DateTime?>("UnbanDate")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("UnsuspendDate")
.HasColumnType("timestamp with time zone");
b.Property<int?>("UserArtistId")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("comissions.app.database.Entities.UserArtist", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("AgeRestricted")
.HasColumnType("boolean");
b.Property<int>("ArtistPageSettingsId")
.HasColumnType("integer");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("PrepaymentRequired")
.HasColumnType("boolean");
b.Property<string>("RequestGuidelines")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SocialMediaLink1")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SocialMediaLink2")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SocialMediaLink3")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SocialMediaLink4")
.IsRequired()
.HasColumnType("text");
b.Property<string>("StripeAccountId")
.HasColumnType("text");
b.Property<string>("SuspendAdminId")
.HasColumnType("text");
b.Property<bool>("Suspended")
.HasColumnType("boolean");
b.Property<DateTime?>("SuspendedDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("SuspendedReason")
.HasColumnType("text");
b.Property<DateTime?>("UnsuspendDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId")
.IsUnique();
b.ToTable("UserArtists");
});
modelBuilder.Entity("comissions.app.database.Entities.ArtistPageSettings", b =>
{
b.HasOne("comissions.app.database.Entities.UserArtist", "Artist")
.WithOne("ArtistPageSettings")
.HasForeignKey("comissions.app.database.Entities.ArtistPageSettings", "ArtistId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Artist");
});
modelBuilder.Entity("comissions.app.database.Entities.ArtistPortfolioPiece", b =>
{
b.HasOne("comissions.app.database.Entities.UserArtist", "Artist")
.WithMany("PortfolioPieces")
.HasForeignKey("ArtistId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Artist");
});
modelBuilder.Entity("comissions.app.database.Entities.ArtistRequest", b =>
{
b.HasOne("comissions.app.database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("comissions.app.database.Entities.Request", b =>
{
b.HasOne("comissions.app.database.Entities.UserArtist", "Artist")
.WithMany("Requests")
.HasForeignKey("ArtistId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("comissions.app.database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Artist");
b.Navigation("User");
});
modelBuilder.Entity("comissions.app.database.Entities.RequestAsset", b =>
{
b.HasOne("comissions.app.database.Entities.Request", "Request")
.WithMany("RequestAssets")
.HasForeignKey("RequestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Request");
});
modelBuilder.Entity("comissions.app.database.Entities.RequestReference", b =>
{
b.HasOne("comissions.app.database.Entities.Request", "Request")
.WithMany("RequestReferences")
.HasForeignKey("RequestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Request");
});
modelBuilder.Entity("comissions.app.database.Entities.UserArtist", b =>
{
b.HasOne("comissions.app.database.Entities.User", "User")
.WithOne("UserArtist")
.HasForeignKey("comissions.app.database.Entities.UserArtist", "UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("comissions.app.database.Entities.Request", b =>
{
b.Navigation("RequestAssets");
b.Navigation("RequestReferences");
});
modelBuilder.Entity("comissions.app.database.Entities.User", b =>
{
b.Navigation("UserArtist");
});
modelBuilder.Entity("comissions.app.database.Entities.UserArtist", b =>
{
b.Navigation("ArtistPageSettings")
.IsRequired();
b.Navigation("PortfolioPieces");
b.Navigation("Requests");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace comissions.app.api.Migrations
{
/// <inheritdoc />
public partial class reviews : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<double>(
name: "Rating",
table: "Requests",
type: "double precision",
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "ReviewDate",
table: "Requests",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "ReviewMessage",
table: "Requests",
type: "text",
nullable: true);
migrationBuilder.AddColumn<bool>(
name: "Reviewed",
table: "Requests",
type: "boolean",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Rating",
table: "Requests");
migrationBuilder.DropColumn(
name: "ReviewDate",
table: "Requests");
migrationBuilder.DropColumn(
name: "ReviewMessage",
table: "Requests");
migrationBuilder.DropColumn(
name: "Reviewed",
table: "Requests");
}
}
}

View File

@ -272,9 +272,21 @@ namespace comissions.app.api.Migrations
b.Property<string>("PaymentUrl")
.HasColumnType("text");
b.Property<double?>("Rating")
.HasColumnType("double precision");
b.Property<DateTime>("RequestDate")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("ReviewDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ReviewMessage")
.HasColumnType("text");
b.Property<bool>("Reviewed")
.HasColumnType("boolean");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");

View File

@ -17,4 +17,8 @@ public class RequestModel
public string? PaymentUrl { get; set; }
public DateTime? PaidDate { get; set; }
public bool Paid { get; set; }
public bool Reviewed { get; set; }
public double? ReviewRating { get; set; }
public string? ReviewMessage { get; set; }
public DateTime? ReviewDate { get; set; }
}

View File

@ -35,7 +35,11 @@ public static class RequestModelExtensions
Paid = sellerProfile.Paid,
PaidDate = sellerProfile.PaidDate,
PaymentUrl = sellerProfile.PaymentUrl,
Message = sellerProfile.Message
Message = sellerProfile.Message,
Reviewed = sellerProfile.Reviewed,
ReviewDate = sellerProfile.ReviewDate,
ReviewMessage = sellerProfile.ReviewMessage,
ReviewRating = sellerProfile.Rating,
};
}
}

View File

@ -0,0 +1,7 @@
namespace comissions.app.database.Models.Request;
public class RequestReviewModel
{
public string Message { get; set; }
public double Rating { get; set; }
}

View File

@ -13,14 +13,14 @@
"password": "postgres"
},
"Stripe": {
"WebHookSecret": "whsec_Jdj6IL9NwFO3MtPpry3vJhE72kZjeCtI",
"WebHookSecret": "whsec_WTxw2seQHaJjSbLiRr1q8fs1wh8vGdGn",
"ApiKey": "sk_test_51OdJ1SLooS0IZqYkx2IdNoLcscm6BisgaUyYVIc5jM1RMmarww2e9hLLQS3Atn6TQi00p9YQkCLGQPhAI2gf9ZSY00HmbQYCvP"
},
"Auth0": {
"Domain": "https://dev-12mb5yq82dow1twh.us.auth0.com/",
"Audience": "https://api.artplatform.com",
"ClientId": "19GWUL7fWFQWEpdFFtlgv2x3kqfSa0ES",
"ClientSecret": "VX5LKeGHeaqKsgNz8Kn1gQ7MSHmwrXJdC2DMjVY82_YHjiRqdPrVNpFFkXBZy8yh"
"ClientId": "U39Jg6oyFoNihzjZ24SX2FxiBx2lqvsC",
"ClientSecret": "UBH4HTsvkoWHImQwI4abyh46s6qpEnD3hfrODEYBTX7p_5v0bYogz-b_6wJtOkDg"
},
"Logging": {
"LogLevel": {

View File

@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("comissions.app.database.migrator")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+ce945516fa472044c5900b733c4ac70a7330bddf")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+4a368fa6a4bcab54e27c3e60b022ebc300fae2c5")]
[assembly: System.Reflection.AssemblyProductAttribute("comissions.app.database.migrator")]
[assembly: System.Reflection.AssemblyTitleAttribute("comissions.app.database.migrator")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@ -1 +1 @@
649880a5ab7f36fa2046be54ee1f282be3d10c5d68933f1dd6511910a7605702
8aab6962eb9a200d66074ae0c76e50836aa7bee26184fdee895d75ccc7cdcb8f

View File

@ -1 +1 @@
17086505533886000
17089118002979834