public async Task <AlbumContract> Create(CreateAlbumContract contract) { ParamIs.NotNull(() => contract); if (contract.Names == null || !contract.Names.Any()) { throw new ArgumentException("Album needs at least one name", "contract"); } VerifyManageDatabase(); return(await _repository.HandleTransactionAsync(async ctx => { ctx.AuditLogger.SysLog($"creating a new album with name '{contract.Names.First().Value}'"); var album = new Album { DiscType = contract.DiscType }; album.Names.Init(contract.Names, album); await ctx.SaveAsync(album); foreach (var artistContract in contract.Artists) { var artist = await ctx.LoadAsync <Artist>(artistContract.Id); if (!album.HasArtist(artist)) { await ctx.SaveAsync(artist.AddAlbum(album)); } } album.UpdateArtistString(); var archived = await ArchiveAsync(ctx, album, AlbumArchiveReason.Created); await ctx.UpdateAsync(album); await ctx.AuditLogger.AuditLogAsync($"created album {_entryLinkFactory.CreateEntryLink(album)} ({album.DiscType})"); await AddEntryEditedEntryAsync(ctx.OfType <ActivityEntry>(), album, EntryEditEvent.Created, archived); await _followedArtistNotifier.SendNotificationsAsync(ctx, album, album.ArtistList, PermissionContext.LoggedUser); return new AlbumContract(album, PermissionContext.LanguagePreference); })); }
/// <summary> /// Updates or creates release event. /// /// Album release event names will be updated as well if the name changed. /// </summary> /// <param name="contract">Updated contract. Cannot be null.</param> /// <returns>Updated release event data. Cannot be null.</returns> /// <exception cref="DuplicateEventNameException">If the event name is already in use.</exception> public async Task <ReleaseEventContract> Update(ReleaseEventForEditContract contract, EntryPictureFileContract pictureData) { ParamIs.NotNull(() => contract); PermissionContext.VerifyManageDatabase(); return(await repository.HandleTransactionAsync(async session => { ReleaseEvent ev; if (contract.Id == 0) { var diff = new ReleaseEventDiff(); if (!contract.Series.IsNullOrDefault()) { var series = await session.LoadAsync <ReleaseEventSeries>(contract.Series.Id); ev = new ReleaseEvent(contract.Description, contract.Date, series, contract.SeriesNumber, contract.SeriesSuffix, contract.DefaultNameLanguage, contract.CustomName); series.AllEvents.Add(ev); } else { ev = new ReleaseEvent(contract.Description, contract.Date, contract.DefaultNameLanguage); } ev.Category = contract.Category; ev.EndDate = contract.EndDate; ev.SongList = await session.NullSafeLoadAsync <SongList>(contract.SongList); ev.Status = contract.Status; ev.SetVenue(await session.NullSafeLoadAsync <Venue>(contract.Venue)); ev.VenueName = contract.VenueName; if (contract.SongList != null) { diff.SongList.Set(); } if (contract.Venue != null) { diff.Venue.Set(); } if (!string.IsNullOrEmpty(contract.VenueName)) { diff.VenueName.Set(); } var weblinksDiff = WebLink.Sync(ev.WebLinks, contract.WebLinks, ev); if (weblinksDiff.Changed) { diff.WebLinks.Set(); } var pvDiff = ev.PVs.Sync(contract.PVs, ev.CreatePV); await session.OfType <PVForAlbum>().SyncAsync(pvDiff); if (pvDiff.Changed) { diff.PVs.Set(); } var artistDiff = await ev.SyncArtists(contract.Artists, artistId => session.LoadAsync <Artist>(artistId)); if (artistDiff.Changed) { diff.Artists.Set(); } await session.SaveAsync(ev); var namesChanged = new UpdateEventNamesQuery().UpdateNames(session, ev, contract.Series, contract.CustomName, contract.SeriesNumber, contract.SeriesSuffix, contract.Names); if (namesChanged) { await session.UpdateAsync(ev); } if (pictureData != null) { diff.MainPicture.Set(); SaveImage(ev, pictureData); await session.UpdateAsync(ev); } var archived = Archive(session, ev, diff, EntryEditEvent.Created, string.Empty); await AddEntryEditedEntryAsync(session.OfType <ActivityEntry>(), archived); await session.AuditLogger.AuditLogAsync(string.Format("created {0}", entryLinkFactory.CreateEntryLink(ev))); await followedArtistNotifier.SendNotificationsAsync(session, ev, ev.Artists.Where(a => a?.Artist != null).Select(a => a.Artist), PermissionContext.LoggedUser); } else { ev = await session.LoadAsync(contract.Id); permissionContext.VerifyEntryEdit(ev); var diff = new ReleaseEventDiff(DoSnapshot(ev, session)); if (ev.Category != contract.Category) { diff.Category.Set(); } if (!ev.Date.Equals(contract.Date) || !ev.EndDate.Equals(contract.EndDate)) { diff.Date.Set(); } if (ev.Description != contract.Description) { diff.Description.Set(); } var inheritedLanguage = ev.Series == null || contract.CustomName ? contract.DefaultNameLanguage : ev.Series.TranslatedName.DefaultLanguage; if (ev.TranslatedName.DefaultLanguage != inheritedLanguage) { diff.OriginalName.Set(); } var namesChanged = new UpdateEventNamesQuery().UpdateNames(session, ev, contract.Series, contract.CustomName, contract.SeriesNumber, contract.SeriesSuffix, contract.Names); if (namesChanged) { diff.Names.Set(); } if (!ev.Series.NullSafeIdEquals(contract.Series)) { diff.Series.Set(); } if (ev.SeriesNumber != contract.SeriesNumber) { diff.SeriesNumber.Set(); } if (ev.SeriesSuffix != contract.SeriesSuffix) { diff.SeriesSuffix.Set(); } if (!ev.SongList.NullSafeIdEquals(contract.SongList)) { diff.SongList.Set(); } if (ev.Status != contract.Status) { diff.Status.Set(); } if (!ev.Venue.NullSafeIdEquals(contract.Venue)) { diff.Venue.Set(); } if (!string.Equals(ev.VenueName, contract.VenueName)) { diff.VenueName.Set(); } ev.SetSeries(await session.NullSafeLoadAsync <ReleaseEventSeries>(contract.Series)); ev.Category = contract.Category; ev.CustomName = contract.CustomName; ev.Date = contract.Date; ev.Description = contract.Description; ev.EndDate = contract.EndDate > contract.Date ? contract.EndDate : null; ev.SeriesNumber = contract.SeriesNumber; ev.SeriesSuffix = contract.SeriesSuffix; ev.SongList = await session.NullSafeLoadAsync <SongList>(contract.SongList); ev.Status = contract.Status; ev.TranslatedName.DefaultLanguage = inheritedLanguage; ev.SetVenue(await session.NullSafeLoadAsync <Venue>(contract.Venue)); ev.VenueName = contract.VenueName; var weblinksDiff = WebLink.Sync(ev.WebLinks, contract.WebLinks, ev); if (weblinksDiff.Changed) { diff.WebLinks.Set(); await session.OfType <ReleaseEventWebLink>().SyncAsync(weblinksDiff); } var pvDiff = ev.PVs.Sync(contract.PVs, ev.CreatePV); await session.OfType <PVForAlbum>().SyncAsync(pvDiff); if (pvDiff.Changed) { diff.PVs.Set(); } var artistDiff = await ev.SyncArtists(contract.Artists, artistId => session.LoadAsync <Artist>(artistId)); if (artistDiff.Changed) { diff.Artists.Set(); } if (pictureData != null) { diff.MainPicture.Set(); SaveImage(ev, pictureData); } await session.UpdateAsync(ev); var archived = Archive(session, ev, diff, EntryEditEvent.Updated, string.Empty); await AddEntryEditedEntryAsync(session.OfType <ActivityEntry>(), archived); var logStr = string.Format("updated properties for {0} ({1})", entryLinkFactory.CreateEntryLink(ev), diff.ChangedFieldsString); await session.AuditLogger.AuditLogAsync(logStr); var newSongCutoff = TimeSpan.FromHours(1); if (artistDiff.Added.Any() && ev.CreateDate >= DateTime.Now - newSongCutoff) { var addedArtists = artistDiff.Added.Where(a => a.Artist != null).Select(a => a.Artist).Distinct().ToArray(); if (addedArtists.Any()) { await followedArtistNotifier.SendNotificationsAsync(session, ev, addedArtists, PermissionContext.LoggedUser); } } } return new ReleaseEventContract(ev, LanguagePreference); })); }