Skip to content

Commit 93edcbb

Browse files
authored
Исправить ошибки при копировании проекта (#3119)
* Вынести проверку обязательности в финальные стратегии * Странный повтор в SetCharacterDescription * Добавить конструкторов в CharacterIdentification * Ограничить копируемые поля * Отображать серверную ошибку
1 parent 7396835 commit 93edcbb

File tree

11 files changed

+48
-15
lines changed

11 files changed

+48
-15
lines changed

src/JoinRpg.Domain/CharacterFields/CharacterExistsStrategyBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ protected void SetCharacterDescription(Dictionary<int, FieldWithValue> fields)
4040
var name = GetFieldValue(nameField);
4141

4242
Character.CharacterName = string.IsNullOrWhiteSpace(name) ?
43-
Character.CharacterName = "CHAR" + Character.CharacterId
43+
"CHAR" + Character.CharacterId
4444
: name;
4545
}
4646

src/JoinRpg.Domain/CharacterFields/FieldSaveStrategyBase.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal abstract class FieldSaveStrategyBase(Claim? claim,
2323

2424
protected abstract void SerializeFields(Dictionary<int, FieldWithValue> fields);
2525

26-
public abstract IReadOnlyCollection<FieldWithValue> GetFields();
26+
protected abstract IReadOnlyCollection<FieldWithValue> GetFields();
2727

2828
private void EnsureEditAccess(FieldWithValue field)
2929
{
@@ -107,7 +107,7 @@ public void AssignValues(IReadOnlyDictionary<int, string?> newFieldValue, Dictio
107107

108108
var normalizedValue = NormalizeValueBeforeAssign(field, keyValuePair.Value);
109109

110-
if (normalizedValue is null && field.Field.MandatoryStatus == MandatoryStatus.Required && field.Field.IsAvailableForTarget(Character))
110+
if (normalizedValue is null && FieldIsMandatory(field))
111111
{
112112
ThrowRequiredField(field);
113113
return;
@@ -117,6 +117,8 @@ public void AssignValues(IReadOnlyDictionary<int, string?> newFieldValue, Dictio
117117
}
118118
}
119119

120+
protected abstract bool FieldIsMandatory(FieldWithValue field);
121+
120122
[DoesNotReturn]
121123
protected abstract void ThrowRequiredField(FieldWithValue field);
122124

src/JoinRpg.Domain/CharacterFields/SaveToCharacterAndClaimStrategy.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,7 @@ protected override void SerializeFields(Dictionary<int, FieldWithValue> fields)
2626
}
2727

2828
protected override void SetCharacterNameFromPlayer() => Character.CharacterName = Claim.Player.GetDisplayName();
29-
public override IReadOnlyCollection<FieldWithValue> GetFields() => Claim.GetFields(ProjectInfo);
29+
protected override IReadOnlyCollection<FieldWithValue> GetFields() => Claim.GetFields(ProjectInfo);
30+
31+
protected override bool FieldIsMandatory(FieldWithValue field) => field.Field.MandatoryStatus == MandatoryStatus.Required && field.Field.IsAvailableForTarget(Character);
3032
}

src/JoinRpg.Domain/CharacterFields/SaveToCharacterOnlyStrategy.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public override void Save(Dictionary<int, FieldWithValue> fields)
2222
UpdateSpecialGroups(fields);
2323
}
2424

25-
public override IReadOnlyCollection<FieldWithValue> GetFields() => Character.GetFields(ProjectInfo);
25+
protected override IReadOnlyCollection<FieldWithValue> GetFields() => Character.GetFields(ProjectInfo);
2626

2727
protected override void SetCharacterNameFromPlayer()
2828
{
@@ -38,4 +38,9 @@ protected override void SerializeFields(Dictionary<int, FieldWithValue> fields)
3838
.Where(v => v.Field.BoundTo == FieldBoundTo.Character)
3939
.SerializeFields();
4040
}
41+
42+
protected override bool FieldIsMandatory(FieldWithValue field) =>
43+
field.Field.MandatoryStatus == MandatoryStatus.Required
44+
&& field.Field.BoundTo == FieldBoundTo.Character // Игнорируем пустые поля заявок в данном случае
45+
&& field.Field.IsAvailableForTarget(Character);
4146
}

src/JoinRpg.Domain/CharacterFields/SaveToClaimOnlyStrategy.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Diagnostics.CodeAnalysis;
22
using JoinRpg.DataModel;
33
using JoinRpg.Domain.Access;
4+
using JoinRpg.PrimitiveTypes.ProjectMetadata;
45

56
namespace JoinRpg.Domain.CharacterFields;
67

@@ -11,7 +12,7 @@ internal class SaveToClaimOnlyStrategy : FieldSaveStrategyBase
1112
public SaveToClaimOnlyStrategy(Claim claim,
1213
int currentUserId,
1314
IFieldDefaultValueGenerator generator,
14-
PrimitiveTypes.ProjectMetadata.ProjectInfo projectInfo) : base(claim,
15+
ProjectInfo projectInfo) : base(claim,
1516
character: null,
1617
currentUserId,
1718
generator,
@@ -31,8 +32,10 @@ protected override void SetCharacterNameFromPlayer()
3132
//Do nothing player could not change character yet
3233
}
3334

34-
public override IReadOnlyCollection<FieldWithValue> GetFields() => Claim.GetFields(ProjectInfo);
35+
protected override IReadOnlyCollection<FieldWithValue> GetFields() => Claim.GetFields(ProjectInfo);
3536

3637
[DoesNotReturn]
3738
protected override void ThrowRequiredField(FieldWithValue field) => throw new CharacterFieldRequiredException(field.Field.Name, field.Field.Id, new(ProjectInfo.ProjectId, Claim.CharacterId));
39+
40+
protected override bool FieldIsMandatory(FieldWithValue field) => field.Field.MandatoryStatus == MandatoryStatus.Required && field.Field.IsAvailableForTarget(Character);
3841
}

src/JoinRpg.Portal/Controllers/WebApi/ProjectCreateController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public async Task<IActionResult> Create([FromBody] ProjectCreateViewModel model,
2929
return result switch
3030
{
3131
FaildToCreateProjectResult failed => Problem(title: "Произошла ошибка при обработке запроса", detail: failed.Message, statusCode: 500),
32-
PartiallySuccessCreateProjectResult partially => Ok(new ProjectCreateResultViewModel(partially.ProjectId, partially.Message)),
32+
PartiallySuccessCreateProjectResult partially => Ok(new ProjectCreateResultViewModel(partially.ProjectId, $"Ошибка: {partially.Message}\n RequestId: {HttpContext.TraceIdentifier}")),
3333
SuccessCreateProjectResult successCreateProjectResult => Ok(new ProjectCreateResultViewModel(successCreateProjectResult.ProjectId, Error: null)),
3434
_ => Ok(result)
3535
};

src/JoinRpg.PrimitiveTypes.Test/IdentificationCommonTest.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ public void IfAcceptsProjectIdShouldImplementIProjectEntityId(Type type)
7272
{
7373
return;
7474
}
75-
var acceptsProjectEntityId = type.GetConstructors().Any(c => c.GetParameters().Any(p => p.ParameterType == typeof(ProjectIdentification) || p.ParameterType.IsAssignableTo(typeof(IProjectEntityId))));
75+
var acceptsProjectEntityId = type.GetConstructors().Any(c => c.GetParameters().Any(
76+
p => p.ParameterType == typeof(ProjectIdentification)
77+
|| p.ParameterType.IsAssignableTo(typeof(IProjectEntityId))
78+
|| p.Name?.Equals("ProjectId", StringComparison.InvariantCultureIgnoreCase) == true
79+
));
7680

7781
if (acceptsProjectEntityId)
7882
{

src/JoinRpg.PrimitiveTypes/CharacterIdentification.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
using System.Text.Json.Serialization;
2+
13
namespace JoinRpg.PrimitiveTypes;
4+
[method: JsonConstructor]
25
public record CharacterIdentification(
3-
int ProjectId,
4-
int CharacterId)
6+
ProjectIdentification ProjectId,
7+
int CharacterId) : IProjectEntityId
58
{
9+
public int Id => CharacterId;
10+
11+
public CharacterIdentification(int projectId, int characterId) : this(new(projectId), characterId)
12+
{
13+
14+
}
615

716
public static CharacterIdentification? FromOptional(int ProjectId, int? CharacterId)
817
{
@@ -17,4 +26,6 @@ public record CharacterIdentification(
1726
}
1827

1928
public static IEnumerable<CharacterIdentification> FromList(IEnumerable<int> list, ProjectIdentification projectId) => list.Select(g => new CharacterIdentification(projectId, g));
29+
30+
public override string ToString() => $"CharacterId({CharacterId}, {ProjectId})";
2031
}

src/JoinRpg.Services.Impl/Projects/CloneProjectHelper.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,10 @@ private async Task CopyCharacter(Character originalChar)
262262
{
263263
var fieldValues = originalChar.GetFields(original);
264264
var setFieldsRequest = new Dictionary<int, string?>();
265-
foreach (var originalFieldValue in fieldValues)
265+
foreach (var originalFieldValue in fieldValues
266+
.Where(fv => fv.Field.BoundTo == FieldBoundTo.Character) // Только поля персонажей
267+
.Where(fv => fv.HasEditableValue) // Только те поля, у которых есть какое-то значение
268+
)
266269
{
267270
var newFieldId = FieldMapping.GetValueOrDefault(originalFieldValue.Field.Id);
268271
if (newFieldId is null)

src/JoinRpg.Services.Impl/Projects/CreateProjectService.Main.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ async Task<CreateProjectResultBase> ICreateProjectService.CreateProject(CreatePr
4747
}
4848
else
4949
{
50-
return new PartiallySuccessCreateProjectResult(projectId, "Удалось скопировать не все");
50+
return new PartiallySuccessCreateProjectResult(projectId, "Удалось скопировать не все элементы проекта");
5151
}
5252
}
5353
catch (Exception ex)

0 commit comments

Comments
 (0)