Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.ar.resx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace Resgrid.Localization.Areas.User.Deployments
{
public class Deployments { }
}
261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.de.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.el.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.en.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.es.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.fr.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.it.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.pl.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.sv.resx

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions Core/Resgrid.Localization/Areas/User/Deployments/Deployments.uk.resx

Large diffs are not rendered by default.

20 changes: 19 additions & 1 deletion Core/Resgrid.Model/AuditLogTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,24 @@ public enum AuditLogTypes
UnitCertificationAdded,
UnitCertificationUpdated,
UnitCertificationRemoved,
UnitCertificationStatusChanged
UnitCertificationStatusChanged,

// Workforce & Business Operations plan Phase C (deployment core). Append-only; the contractor-billing and
// Cal OES MARS milestones append their own entries after these.
DeploymentCreated,
DeploymentUpdated,
DeploymentStatusChanged,
DeploymentRosterChanged,
DeploymentEquipmentChanged,
DeploymentAttachmentAdded,
DeploymentAttachmentRemoved,
TimeReportCreated,
TimeReportUpdated,
TimeReportSubmitted,
TimeReportApproved,
TimeReportVoided,
DeploymentExpenseAdded,
DeploymentExpenseUpdated,
DeploymentExpenseRemoved
}
}
7 changes: 7 additions & 0 deletions Core/Resgrid.Model/Certifications/CertificationModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ public class DepartmentCertificationSettings : IEntity

public string UpdatedByUserId { get; set; }

/// <summary>
/// Department-local date of the last claimed expiry sweep (worker 34). The worker claims the date atomically before it
/// runs, so a repeated or skipped local hour (clock drift, daylight-saving transitions, an overlapping tick) can neither
/// send a day's expiring notifications twice nor miss the day. Owned by the worker; the settings page never writes it.
/// </summary>
public DateTime? LastSweepLocalDate { get; set; }

[NotMapped]
[JsonIgnore]
public object IdValue
Expand Down
9 changes: 9 additions & 0 deletions Core/Resgrid.Model/FeatureFlagKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,14 @@ public static class FeatureFlagKeys

/// <summary>Phase B2 online payment collection through a department's own Stripe account. Child of Invoicing.CustomerInvoicing and Payments.StripeConnect. Seeded off by M0212.</summary>
public const string OnlinePayments = "Invoicing.OnlinePayments";

/// <summary>Phase C deployment core (deployments, roster, daily time reports, expenses, attachments, external-order link). Free: no Business.Operations prerequisite. Seeded off by M0219.</summary>
public const string Deployments = "Operations.Deployments";

/// <summary>Phase C contractor billing (rate schedules, contracts, bids, charge runs, invoice generation). Child of Business.Operations. Seeded off by M0219.</summary>
public const string ContractorBilling = "Invoicing.ContractorBilling";

/// <summary>Phase C Cal OES MARS cost recovery. Child of Business.Operations. Seeded off by M0219.</summary>
public const string CalOesMars = "CostRecovery.CalOesMars";
}
}
109 changes: 109 additions & 0 deletions Core/Resgrid.Model/Invoicing/DeploymentContracts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;

namespace Resgrid.Model.Invoicing
{
// Workforce & Business Operations plan, Phase C (C4): inputs and results of the deployment core services.

/// <summary>Input for <c>CreateFromExternalOrderAsync</c> (plan C4, decision 39).</summary>
public sealed class ExternalOrderDeploymentInput
{
public string RmsExternalOrderId { get; set; }
public DeploymentFinanceModes FinanceMode { get; set; } = DeploymentFinanceModes.OperationalOnly;
/// <summary>Create a Call for the deployment (the department's choice; the Records deployment already has its own identity).</summary>
public bool CreateCall { get; set; }
public string CallType { get; set; }
public int CallPriority { get; set; }
/// <summary>Seat the accepted/mobilized/checked-in/assigned fills' AssignedUserId/AssignedUnitId on the roster.</summary>
public bool PrefillRoster { get; set; } = true;
public string Name { get; set; }
public string ContactId { get; set; }
public string Notes { get; set; }
}

/// <summary>A roster warning or conflict (plan C4/C6): the row is still written unless <see cref="Blocking"/>.</summary>
public sealed class DeploymentRosterWarning
{
public const string ScheduleConflict = "schedule_conflict";
public const string RoleNotHeld = "role_not_held";
public const string CertificationMissing = "certification_missing";
public const string CertificationExpiring = "certification_expiring";
public const string AlreadyRostered = "already_rostered";

public string Code { get; set; }
public string SubjectId { get; set; }
public string Detail { get; set; }
public bool Blocking { get; set; }
}

public sealed class DeploymentRosterResult
{
public DeploymentPersonnel Personnel { get; set; }
public DeploymentUnit Unit { get; set; }
public DeploymentEquipment Equipment { get; set; }
public List<DeploymentRosterWarning> Warnings { get; set; } = new List<DeploymentRosterWarning>();
public bool HasBlockingWarnings => Warnings.Exists(w => w.Blocking);
}

public sealed class DeploymentPersonnelInput
{
public string UserId { get; set; }
public string DeploymentUnitId { get; set; }
public int? UnitRoleId { get; set; }
public string CertificationCode { get; set; }
public string CallSign { get; set; }
public string RmsExternalOrderFillId { get; set; }
/// <summary>Write the row even when a seat requirement fails (the wizard's partial-fill path, decision 17).</summary>
public bool Force { get; set; }
}

public sealed class DeploymentEquipmentInput
{
public string DeploymentUnitId { get; set; }
public string InventoryAssetId { get; set; }
public string InventoryItemId { get; set; }
public string FreeTextName { get; set; }
public string Notes { get; set; }
/// <summary>Post an inventory Issue transaction (ReferenceType=Deployment) when the inventory module is present.</summary>
public bool IssueFromInventory { get; set; }
public string FromLocationId { get; set; }
}

/// <summary>Result of a time-report validation pass (plan C4 ITimeTrackingService).</summary>
public sealed class TimeReportValidation
{
public const string Overlap = "entries_overlap";
public const string EndBeforeStart = "end_before_start";
public const string SubjectNotOnRoster = "subject_not_on_roster";
public const string NoEntries = "no_entries";
public const string BreakRule = "break_rule";
public const string LongTravel = "long_travel";
public const string OutsideReportDate = "outside_report_date";

public List<TimeReportIssue> Errors { get; set; } = new List<TimeReportIssue>();
public List<TimeReportIssue> Warnings { get; set; } = new List<TimeReportIssue>();
public bool IsValid => Errors.Count == 0;
}

public sealed class TimeReportIssue
{
public string Code { get; set; }
public string SubjectId { get; set; }
public string EntryId { get; set; }
public string Detail { get; set; }
}

/// <summary>A saved time report plus the validation that ran on it.</summary>
public sealed class TimeReportSaveResult
{
public DeploymentTimeReport Report { get; set; }
public TimeReportValidation Validation { get; set; } = new TimeReportValidation();
}

/// <summary>The external order and fills behind a deployment, as the RMS pack owns them (decision 39).</summary>
public sealed class DeploymentExternalContext
{
public RmsExternalOrder Order { get; set; }
public List<RmsExternalOrderFill> Fills { get; set; } = new List<RmsExternalOrderFill>();
}
}
Loading
Loading