• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

HicServices / RDMP / 19852309549

02 Dec 2025 08:38AM UTC coverage: 55.8% (-1.4%) from 57.197%
19852309549

Pull #2279

github

JFriel
fix build
Pull Request #2279: [UI Overhaul] Spike/refresh

11249 of 21727 branches covered (51.77%)

Branch coverage included in aggregate %.

807 of 1108 new or added lines in 29 files covered. (72.83%)

724 existing lines in 67 files now uncovered.

31893 of 55588 relevant lines covered (57.37%)

16683.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.33
/Rdmp.Core/DataExport/Data/Project.cs
1
// Copyright (c) The University of Dundee 2018-2019
2
// This file is part of the Research Data Management Platform (RDMP).
3
// RDMP is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4
// RDMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5
// You should have received a copy of the GNU General Public License along with RDMP. If not, see <https://www.gnu.org/licenses/>.
6

7
using System;
8
using System.Collections.Generic;
9
using System.Data.Common;
10
using System.Linq;
11
using Rdmp.Core.CommandExecution;
12
using Rdmp.Core.Curation.Data;
13
using Rdmp.Core.Curation.Data.Cohort;
14
using Rdmp.Core.DataExport.Checks;
15
using Rdmp.Core.MapsDirectlyToDatabaseTable;
16
using Rdmp.Core.MapsDirectlyToDatabaseTable.Attributes;
17
using Rdmp.Core.Providers;
18
using Rdmp.Core.Repositories;
19
using Rdmp.Core.ReusableLibraryCode;
20
using Rdmp.Core.ReusableLibraryCode.Annotations;
21
using Rdmp.Core.ReusableLibraryCode.Checks;
22

23
namespace Rdmp.Core.DataExport.Data;
24

25
/// <inheritdoc cref="IProject"/>
26
public class Project : DatabaseEntity, IProject, ICustomSearchString, ICheckable, IHasFolder
27
{
28
    #region Database Properties
29

30
    private string _name;
31
    private string _masterTicket;
32
    private string _extractionDirectory;
33
    private int? _projectNumber;
34
    private string _folder;
35

36
    /// <inheritdoc/>
37
    [NotNull]
38
    [Unique]
39
    public string Name
40
    {
41
        get => _name;
1,708✔
42
        set => SetField(ref _name, value);
3,256✔
43
    }
44

45
    /// <inheritdoc/>
46
    public string MasterTicket
47
    {
48
        get => _masterTicket;
1,188✔
49
        set => SetField(ref _masterTicket, value);
3,060✔
50
    }
51

52
    /// <inheritdoc/>
53
    [AdjustableLocation]
54
    public string ExtractionDirectory
55
    {
56
        get => _extractionDirectory;
1,642✔
57
        set => SetField(ref _extractionDirectory, value);
3,258✔
58
    }
59

60
    /// <inheritdoc/>
61
    [UsefulProperty]
62
    public int? ProjectNumber
63
    {
64
        get => _projectNumber;
2,348✔
65
        set => SetField(ref _projectNumber, value);
3,294✔
66
    }
67

68
    /// <inheritdoc/>
69
    [UsefulProperty]
70
    public string Folder
71
    {
72
        get => _folder;
1,026✔
73
        set => SetField(ref _folder, FolderHelper.Adjust(value));
3,250✔
74
    }
75

76
    #endregion
77

78
    #region Relationships
79

80
    /// <inheritdoc/>
81
    [NoMappingToDatabase]
82
    public IExtractionConfiguration[] ExtractionConfigurations =>
83
        Repository.GetAllObjectsWithParent<ExtractionConfiguration>(this)
64✔
84
            .Cast<IExtractionConfiguration>()
64✔
85
            .ToArray();
64✔
86

87

88
    /// <inheritdoc/>
89
    [NoMappingToDatabase]
90
    public IProjectCohortIdentificationConfigurationAssociation[]
91
        ProjectCohortIdentificationConfigurationAssociations =>
92
        Repository.GetAllObjectsWithParent<ProjectCohortIdentificationConfigurationAssociation>(this);
18✔
93

94
    #endregion
95

96
    public Project()
×
97
    {
98
    }
×
99

100
    /// <summary>
101
    /// Defines a new extraction project this is stored in the Data Export database
102
    /// </summary>
103
    public Project(IDataExportRepository repository, string name)
488✔
104
    {
105
        Repository = repository;
488✔
106

107
        try
108
        {
109
            Repository.InsertAndHydrate(this, new Dictionary<string, object>
488✔
110
            {
488✔
111
                { "Name", name },
488✔
112
                { "Folder", FolderHelper.Root }
488✔
113
            });
488✔
114
        }
488✔
115
        catch (Exception ex)
×
116
        {
117
            //sometimes the user tries to create multiple Projects without fully populating the last one (with a project number)
118
            if (ex.Message.Contains("idx_ProjectNumberMustBeUnique"))
×
119
            {
120
                Project offender;
121
                try
122
                {
123
                    //find the one with the unset project number
124
                    offender = Repository.GetAllObjects<Project>().Single(p => p.ProjectNumber == null);
×
125
                }
×
126
                catch (Exception)
×
127
                {
128
                    throw;
×
129
                }
130

131
                throw new Exception(
×
132
                    $"Could not create a new Project because there is already another Project in the system ({offender}) which is missing a Project Number.  All projects must have a ProjectNumber, there can be 1 Project at a time which does not have a number and that is one that is being built by the user right now.  Either delete Project {offender} or give it a project number",
×
133
                    ex);
×
134
            }
135

136
            throw;
×
137
        }
138
    }
488✔
139

140
    internal Project(IDataExportRepository repository, DbDataReader r)
141
        : base(repository, r)
2,762✔
142
    {
143
        MasterTicket = r["MasterTicket"].ToString();
2,762✔
144
        Name = r["Name"] as string;
2,762✔
145
        ExtractionDirectory = r["ExtractionDirectory"] as string;
2,762✔
146

147
        ProjectNumber = ObjectToNullableInt(r["ProjectNumber"]);
2,762✔
148

149
        Folder = r["Folder"] as string ?? FolderHelper.Root;
2,762!
150
    }
2,762✔
151

152
    /// <summary>
153
    /// Returns <see cref="Name"/>
154
    /// </summary>
155
    /// <returns></returns>
156
    public override string ToString() => Name;
52✔
157

158
    public void Check(ICheckNotifier notifier)
159
    {
160
        new ProjectChecker(new ThrowImmediatelyActivator(new RepositoryProvider(DataExportRepository), notifier), this)
×
161
            .Check(notifier);
×
162
    }
×
163

164
    /// <summary>
165
    /// Returns <see cref="ProjectNumber"/> (if any), <see cref="Name"/> and <see cref="MasterTicket"/>
166
    /// </summary>
167
    /// <returns></returns>
168
    public string GetSearchString() => ProjectNumber == null ? Name : $"{ProjectNumber}_{Name}_{MasterTicket}";
40!
169

170
    /// <summary>
171
    /// Returns all <see cref="CohortIdentificationConfiguration"/> which are associated with the <see cref="IProject"/> (usually because
172
    /// they have been used to create <see cref="ExtractableCohort"/> used by the <see cref="IProject"/>).
173
    /// </summary>
174
    /// <returns></returns>
175
    public CohortIdentificationConfiguration[] GetAssociatedCohortIdentificationConfigurations()
176
    {
177
        var associations =
36✔
178
            Repository.GetAllObjectsWithParent<ProjectCohortIdentificationConfigurationAssociation>(this);
36✔
179
        return associations.Select(a => a.CohortIdentificationConfiguration).Where(c => c != null && !c.IsTemplate).ToArray();
68✔
180
    }
181

182
    public CohortIdentificationConfiguration[] GetAssociatedTemplateCohortIdentificationConfigurations()
183
    {
UNCOV
184
        var associations =
×
UNCOV
185
            Repository.GetAllObjectsWithParent<ProjectCohortIdentificationConfigurationAssociation>(this);
×
UNCOV
186
        return associations.Select(a => a.CohortIdentificationConfiguration).Where(c => c != null && c.IsTemplate).ToArray();
×
187
    }
188

189
    /// <summary>
190
    /// Associates the <paramref name="cic"/> with the <see cref="IProject"/>.  This is usually done after generating an <see cref="IExtractableCohort"/>.
191
    /// You can associate a <see cref="CohortIdentificationConfiguration"/> with multiple <see cref="IProject"/> (M to M relationship).
192
    /// </summary>
193
    /// <param name="cic"></param>
194
    /// <returns></returns>
195
    public ProjectCohortIdentificationConfigurationAssociation
196
        AssociateWithCohortIdentification(CohortIdentificationConfiguration cic) =>
197
        new((IDataExportRepository)Repository, this, cic);
2✔
198

199
    /// <inheritdoc/>
200
    public ICatalogue[] GetAllProjectCatalogues()
201
    {
202
        return Repository.GetAllObjects<ExtractableDataSetProject>().Where(edsp => edsp.Project_ID == this.ID).Select(edsp => edsp.DataSet.Catalogue).ToArray(); 
16✔
203
    }
204

205
    /// <inheritdoc/>
206
    public ExtractionInformation[] GetAllProjectCatalogueColumns(ExtractionCategory c)
207
    {
208
        return GetAllProjectCatalogues().SelectMany(pc => pc.GetAllExtractionInformation(c)).ToArray();
×
209
    }
210

211
    /// <inheritdoc/>
212
    public ExtractionInformation[] GetAllProjectCatalogueColumns(ICoreChildProvider childProvider, ExtractionCategory c)
213
    {
214
        return childProvider is DataExportChildProvider dx
4!
215
            ? dx.ExtractableDataSets.Where(eds => eds.Projects.Select(p=>p.ID).Contains(ID))
28✔
216
                .Select(e => dx.AllCataloguesDictionary[e.Catalogue_ID])
×
217
                .SelectMany(cata => cata.GetAllExtractionInformation(c)).ToArray()
×
218
            : GetAllProjectCatalogueColumns(c);
4✔
219
    }
220

221
    /// <inheritdoc/>
222
    public IHasDependencies[] GetObjectsThisDependsOn() => Array.Empty<IHasDependencies>();
×
223

224
    /// <inheritdoc/>
225
    public IHasDependencies[] GetObjectsDependingOnThis() => ExtractionConfigurations;
12✔
226
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc