Espace de stockage personnel géré depuis PostIt, avec attachement par
référence (sans duplication) des fichiers à la demande du client
(NominativeServiceCommand) et au devis du fournisseur (Estimate).
Backend:
- UploadedFile.OwnerId (FK ApplicationUser, nullable) ; les téléversements
vers api/v1/fs créent/mettent à jour une ligne propriétaire.
- Tables de jointure EstimateAttachedFile et QueryAttachedFile (PK composite),
migration UserFileAttachments.
- EstimateApiController: GET/POST/DELETE estimate/{id}/attachments
(fournisseur uniquement, fichier devant appartenir au caller).
- FrontOfficeApiController: GET/POST/DELETE front/query/{id}/attachments
(client uniquement).
- FileSystemApiController: GET fs/file/{fileId} sert les octets depuis le
host Blogs (autorisation propriétaire ou partie au devis/demande via DB
partagée) — le host API ne gère que les métadonnées, contrainte des
conteneurs docker à disques distincts.
Client .NET:
- UserFilesApiClient (list/upload/delete/download) pointant vers BlogsApiUrl.
- DTOs UserDirectoryDto/FileEntryDto/AttachmentDto/FileReceivedDto/UploadFile.
- Méthodes d'attachement sur EstimateApiClient et FrontOfficeApiClient.
PostIt (Avalonia):
- Page « Mes fichiers » (naviguer/téléverser/télécharger/supprimer), servant
aussi de sélecteur pour l'attachement.
- Section pièces jointes dans l'édition du devis (fournisseur) et le détail
de la demande (client), avec ajout depuis My Files, détachement,
téléchargement.
- Enregistrement DI + mapping ViewLocator + bouton d'accès.
Tests:
- EstimateEditionPageViewModelTests mis à jour (nouveau ctor fsClient,
historique d'appels du stub pour les assertions post-envoi).
Nommage HTTP/méthodes en anglais, documentation en français.
Co-Authored-By: Claude Code <noreply@anthropic.com>
74 lines
2 KiB
C#
74 lines
2 KiB
C#
#nullable enable annotations
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Yavsc.Models.Blog
|
|
{
|
|
public class UploadedFile
|
|
{
|
|
/// <summary>
|
|
/// File Identifier
|
|
/// </summary>
|
|
/// <value></value>
|
|
[Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
[Display(Name = "Identifiant du fichier")]
|
|
public long Id { get; set; }
|
|
|
|
/// <summary>
|
|
/// relative path to the file, relative to the poster space prefix
|
|
/// </summary>
|
|
/// <value></value>
|
|
public string Path { get; set; }
|
|
|
|
/// <summary>
|
|
/// Length
|
|
/// </summary> <summary>
|
|
///
|
|
/// </summary>
|
|
/// <value></value>
|
|
public long Length { get; set; }
|
|
|
|
/// <summary>
|
|
/// File Content type
|
|
/// </summary>
|
|
/// <value></value>
|
|
public string ContentType { get; set; }
|
|
|
|
/// <summary>
|
|
/// Propriétaire du fichier dans l'espace de stockage personnel.
|
|
/// Renseigné pour les fichiers téléversés via <c>api/v1/fs</c>
|
|
/// (référencés par <see cref="EstimateAttachedFile"/> /
|
|
/// <see cref="QueryAttachedFile"/>). Reste <c>null</c> pour les
|
|
/// pièces jointes de blog historiques (<see cref="BlogAttachedFile"/>),
|
|
/// qui ne sont pas adressées par propriétaire.
|
|
/// </summary>
|
|
public string? OwnerId { get; set; }
|
|
|
|
[ForeignKey("OwnerId")]
|
|
public virtual ApplicationUser? Owner { get; set; }
|
|
}
|
|
|
|
[PrimaryKey(nameof(FileId), nameof(PostId))]
|
|
public class BlogAttachedFile
|
|
{
|
|
/// <summary>
|
|
/// File Id (part of composite key)
|
|
/// </summary>
|
|
/// <value></value>
|
|
public long FileId { get; set; }
|
|
|
|
[ForeignKey("FileId")]
|
|
public virtual UploadedFile File { get; set; }
|
|
|
|
/// <summary>
|
|
/// Post Id (part of composite key)
|
|
/// </summary>
|
|
/// <value></value>
|
|
public long PostId { get; set; }
|
|
|
|
[ForeignKey("PostId")]
|
|
public virtual BlogPost Post { get; set; }
|
|
|
|
}
|
|
}
|