Files
marechai/Marechai.Database/Models/SoftwareSimilarTo.cs
Natalia Portillo f4b665cfd7 feat: Add symmetric Similar Software relationship between Software entries
Software entries previously only modeled strict lineage relationships
(Predecessor/Successor sequels, BaseSoftware/Addons DLC). There was no
way to express a looser, symmetric "these are related" link, e.g.
Microsoft Excel and Microsoft Excel for Macintosh.

Adds a new self-referencing many-to-many SoftwareSimilarTo join entity,
following the existing SoftwareCompilationBySoftwareCompilation pattern
(composite PK, Cascade + Restrict delete behavior to satisfy MySQL's
single-cascade-path constraint on self-referencing tables). Each
unordered pair is stored once, normalized so the smaller id is always
SoftwareId, avoiding duplicate inverse rows.

Database:
- New SoftwareSimilarTo model + DbContext configuration + EF migration.

API:
- SoftwareSimilarToDto.
- SoftwareSimilarToController: admin POST/DELETE under /software/similar-to,
  normalizing pair ordering and rejecting self-links/duplicates.
- Public GET /software/{id}/similar on SoftwareController, returning the
  "other side" of the pair regardless of which column matched.
- Regenerated openapi.yaml and the Kiota-generated Marechai.ApiClient.

Blazor (Marechai):
- SoftwareService: GetSimilarSoftwareAsync/AddSimilarSoftwareAsync/
  RemoveSimilarSoftwareAsync.
- Admin SoftwareDialog.razor: new "Similar Software" tab (edit mode only)
  with an autocomplete picker excluding self and already-linked rows.
- Public Software/View.razor: new "Similar Software" card in the Overview
  tab, loaded alongside Addons.

Uno (Marechai.App):
- SoftwareService (admin) + SoftwareBrowsingService (public): matching
  methods backed by the regenerated Kiota client.
- AdminSoftwareViewModel/AdminSoftwarePage: similar-software section with
  search-filtered suggestions, mirroring the External IDs pattern.
- SoftwareViewViewModel/SoftwareViewPage: similar-software list with
  per-item navigation, mirroring the Base Software/Releases patterns.
- Added SimilarSoftwareHeader/SimilarSoftwareSearchLabel strings to all
  five locale .resx files (en, es, fr, de, pt-BR).

This pass is manual curation only; no automated similarity matcher is
included.
2026-06-26 16:09:26 +01:00

44 lines
1.9 KiB
C#

/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program 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.
//
// This program 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.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2026 Natalia Portillo
*******************************************************************************/
namespace Marechai.Database.Models;
/// <summary>
/// A symmetric "is similar to" link between two <see cref="Software" /> entries
/// (e.g. Microsoft Excel and Microsoft Excel for Macintosh). Each unordered pair is
/// stored as a single row with <see cref="SoftwareId" /> &lt; <see cref="SimilarSoftwareId" />;
/// callers must normalize the ordering before writing and query both columns when reading.
/// </summary>
public class SoftwareSimilarTo
{
public ulong SoftwareId { get; set; }
public virtual Software Software { get; set; }
public ulong SimilarSoftwareId { get; set; }
public virtual Software SimilarSoftware { get; set; }
}