new updates
This commit is contained in:
@@ -29,6 +29,21 @@ public sealed class AuthSessionResponse
|
||||
public int ExpiresIn { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>Result of AuthHex's admin-only deleteUser function.</summary>
|
||||
public sealed class DeleteAuthHexUserResult
|
||||
{
|
||||
public int DeletedCount { get; set; }
|
||||
public List<DeletedAuthHexUser>? Deleted { get; set; }
|
||||
}
|
||||
|
||||
public sealed class DeletedAuthHexUser
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? FullName { get; set; }
|
||||
public string? UserName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
}
|
||||
|
||||
public sealed class RegisterRequest
|
||||
{
|
||||
/// <summary>Optional — AuthHex requires a client-supplied id; ERPCore generates one when omitted.</summary>
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace ERPCore.Dtos.Config;
|
||||
|
||||
/// <summary>Branch configuration resource — the singleton toggle for whether this deployment
|
||||
/// requires a branch on Employee/Warehouse records at all.</summary>
|
||||
public sealed record BranchConfigDto(bool BranchingEnabled, DateTime? UpdatedAt, int? UpdatedBy);
|
||||
public sealed record BranchConfigDto(bool BranchingEnabled, bool WarehouseBranchingEnabled, DateTime? UpdatedAt, int? UpdatedBy);
|
||||
|
||||
/// <summary>
|
||||
/// Full replacement of the flag. <c>UpdatedBy</c> is derived from the token, never posted.
|
||||
@@ -17,4 +17,5 @@ public sealed record BranchConfigDto(bool BranchingEnabled, DateTime? UpdatedAt,
|
||||
public sealed class UpdateBranchConfigRequest
|
||||
{
|
||||
[Required] public bool? BranchingEnabled { get; set; }
|
||||
[Required] public bool? WarehouseBranchingEnabled { get; set; }
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public sealed record CustomerDto(
|
||||
int CreditDays,
|
||||
int? DefaultWarehouseId,
|
||||
EntityStatus Status,
|
||||
int BranchId,
|
||||
DateTime CreatedAt,
|
||||
DateTime? UpdatedAt);
|
||||
|
||||
@@ -40,6 +41,7 @@ public sealed class CreateCustomerRequest
|
||||
[Range(0, double.MaxValue)] public decimal CreditLimit { get; set; }
|
||||
[Range(0, int.MaxValue)] public int CreditDays { get; set; }
|
||||
public int? DefaultWarehouseId { get; set; }
|
||||
public int BranchId { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateCustomerRequest
|
||||
@@ -58,6 +60,7 @@ public sealed class UpdateCustomerRequest
|
||||
[Range(0, double.MaxValue)] public decimal CreditLimit { get; set; }
|
||||
[Range(0, int.MaxValue)] public int CreditDays { get; set; }
|
||||
public int? DefaultWarehouseId { get; set; }
|
||||
public int BranchId { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateCustomerStatusRequest
|
||||
|
||||
@@ -4,9 +4,12 @@ namespace ERPCore.Dtos.Dashboard;
|
||||
/// Aggregate counts for the dashboard overview — mirrors the widget set in
|
||||
/// docs/dashboard-implementation.pdf: reorder alerts, on-hand summary, stock valuation,
|
||||
/// pending-approval POs, pending GRNs, open requisitions, open counts awaiting posting,
|
||||
/// and open RFQs. Recent movements isn't here — it's just GET /stock/ledger with a small
|
||||
/// pageSize, no aggregation needed. A single computed-on-read object, not a stored
|
||||
/// entity — same as reorder alerts (docs/11 §5.7).
|
||||
/// open RFQs, pending leave requests, and overdue sales invoices. Also reused as small
|
||||
/// KPI tiles on individual list pages (Purchase Orders, GRN, Requisitions, RFQs, Stock
|
||||
/// Counts, Reorder Alerts, HRM Leave, Sales Invoices), not just the Dashboard home page.
|
||||
/// Recent movements isn't here — it's just GET /stock/ledger with a small pageSize, no
|
||||
/// aggregation needed. A single computed-on-read object, not a stored entity — same as
|
||||
/// reorder alerts (docs/11 §5.7).
|
||||
/// </summary>
|
||||
public sealed record DashboardStatsDto(
|
||||
int LowStockAlerts,
|
||||
@@ -18,7 +21,9 @@ public sealed record DashboardStatsDto(
|
||||
int PendingGrns,
|
||||
int OpenRequisitions,
|
||||
int PendingCounts,
|
||||
int OpenRfqs);
|
||||
int OpenRfqs,
|
||||
int PendingLeaveRequests,
|
||||
int OverdueSalesInvoices);
|
||||
|
||||
/// <summary>One bar in the Stock Valuation chart — total FIFO layer value for a warehouse.</summary>
|
||||
public sealed record WarehouseValuationDto(int WarehouseId, decimal Total);
|
||||
|
||||
@@ -63,8 +63,9 @@ public sealed class CreateGrnLineInput
|
||||
[Range(0, double.MaxValue)] public decimal UnitCost { get; set; }
|
||||
/// <summary>Trade discount percentage (0–100). Reduces the inventory cost.</summary>
|
||||
[Range(0, 100)] public decimal DiscountPct { get; set; }
|
||||
/// <summary>VAT percentage (0–100). Recoverable — does not affect stock value.</summary>
|
||||
[Range(0, 100)] public decimal VatPct { get; set; }
|
||||
/// <summary>VAT percentage (0–100). Recoverable — does not affect stock value. Explicit
|
||||
/// override; omit (null) to use the item's assigned TaxRate percentage instead.</summary>
|
||||
[Range(0, 100)] public decimal? VatPct { get; set; }
|
||||
[EnumDataType(typeof(HoldStatus))] public HoldStatus HoldStatus { get; set; } = HoldStatus.Available;
|
||||
public BatchInput? Batch { get; set; }
|
||||
/// <summary>
|
||||
|
||||
@@ -3,6 +3,8 @@ using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Dtos.Hrm;
|
||||
|
||||
public sealed record EmployeeDeleteResultDto(bool UserAccountDeleted, bool UserAccountDeactivated, bool AuthHexIdentityPurged = false);
|
||||
|
||||
public sealed record EmployeeListItemDto(
|
||||
int EmployeeId, string EmployeeCode, string FullName, string? Email,
|
||||
int DepartmentId, string? DepartmentName, int DesignationId, string? DesignationName,
|
||||
|
||||
@@ -10,10 +10,11 @@ public sealed record ItemListItemDto(
|
||||
int ItemId, string Sku, string Name, int CategoryId, int? SubCategoryId, int? BrandId,
|
||||
int BaseUomId, int? DefaultVendorId, StockNature StockNature, TrackingMode TrackingMode,
|
||||
Warranty Warranty, int? WarrantyPeriodMonths,
|
||||
string? TaxClass, decimal? SellingMinPrice, decimal? SellingMaxPrice, decimal? SellingFlatPrice,
|
||||
int? TaxRateId, string? TaxRateName, decimal? TaxRatePercentage,
|
||||
decimal? SellingMinPrice, decimal? SellingMaxPrice, decimal? SellingFlatPrice,
|
||||
decimal? ContentQty, MeasureUnit? ContentUnit,
|
||||
decimal? ContentBaseQty, MeasureUnit? ContentBaseUnit,
|
||||
EntityStatus Status);
|
||||
EntityStatus Status, string? Barcode);
|
||||
|
||||
/// <summary>A single per-warehouse reorder policy row.</summary>
|
||||
public sealed record ItemReorderDto(int WarehouseId, decimal ReorderPoint, decimal ReorderQty);
|
||||
@@ -31,10 +32,11 @@ public sealed record ItemDetailDto(
|
||||
int? SubCategoryId, int? BrandId, int BaseUomId, int? DefaultVendorId,
|
||||
StockNature StockNature, TrackingMode TrackingMode,
|
||||
Warranty Warranty, int? WarrantyPeriodMonths,
|
||||
string? TaxClass, decimal? SellingMinPrice, decimal? SellingMaxPrice, decimal? SellingFlatPrice,
|
||||
int? TaxRateId, string? TaxRateName, decimal? TaxRatePercentage,
|
||||
decimal? SellingMinPrice, decimal? SellingMaxPrice, decimal? SellingFlatPrice,
|
||||
decimal? ContentQty, MeasureUnit? ContentUnit,
|
||||
decimal? ContentBaseQty, MeasureUnit? ContentBaseUnit,
|
||||
EntityStatus Status, IReadOnlyList<ItemReorderDto> Reorder,
|
||||
EntityStatus Status, string? Barcode, IReadOnlyList<ItemReorderDto> Reorder,
|
||||
DateTime CreatedAt, DateTime? UpdatedAt);
|
||||
|
||||
/// <summary>Response body for <c>PUT /items/{id}/reorder</c>.</summary>
|
||||
@@ -64,7 +66,8 @@ public sealed class CreateItemRequest
|
||||
[EnumDataType(typeof(Warranty))] public Warranty Warranty { get; set; } = Warranty.NonWarranty;
|
||||
/// <summary>Required (one of <see cref="Enums.WarrantyPeriods.AllowedMonths"/>) when <see cref="Warranty"/> is Warranty; ignored otherwise.</summary>
|
||||
public int? WarrantyPeriodMonths { get; set; }
|
||||
[StringLength(20)] public string? TaxClass { get; set; }
|
||||
/// <summary>The tax rate sales/purchase lines for this item default to — see <see cref="Domain.Entities.TaxRate"/>.</summary>
|
||||
public int? TaxRateId { get; set; }
|
||||
/// <summary>Optional fixed sale price (Sales only). Null ⇒ sell at stock/FIFO value.</summary>
|
||||
[Range(0, double.MaxValue)] public decimal? SellingMinPrice { get; set; }
|
||||
[Range(0, double.MaxValue)] public decimal? SellingMaxPrice { get; set; }
|
||||
@@ -77,6 +80,8 @@ public sealed class CreateItemRequest
|
||||
/// </summary>
|
||||
[Range(0.0001, double.MaxValue)] public decimal? ContentQty { get; set; }
|
||||
[EnumDataType(typeof(MeasureUnit))] public MeasureUnit? ContentUnit { get; set; }
|
||||
/// <summary>Optional scan code for barcode/RFID lookup. Unlike <see cref="Sku"/>, not required.</summary>
|
||||
[StringLength(100)] public string? Barcode { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateItemRequest
|
||||
@@ -96,7 +101,8 @@ public sealed class UpdateItemRequest
|
||||
[EnumDataType(typeof(Warranty))] public Warranty Warranty { get; set; } = Warranty.NonWarranty;
|
||||
/// <summary>Required (one of <see cref="Enums.WarrantyPeriods.AllowedMonths"/>) when <see cref="Warranty"/> is Warranty; ignored otherwise.</summary>
|
||||
public int? WarrantyPeriodMonths { get; set; }
|
||||
[StringLength(20)] public string? TaxClass { get; set; }
|
||||
/// <summary>The tax rate sales/purchase lines for this item default to — see <see cref="Domain.Entities.TaxRate"/>.</summary>
|
||||
public int? TaxRateId { get; set; }
|
||||
/// <summary>Optional fixed sale price (Sales only). Null ⇒ sell at stock/FIFO value.</summary>
|
||||
[Range(0, double.MaxValue)] public decimal? SellingMinPrice { get; set; }
|
||||
[Range(0, double.MaxValue)] public decimal? SellingMaxPrice { get; set; }
|
||||
@@ -109,6 +115,8 @@ public sealed class UpdateItemRequest
|
||||
/// </summary>
|
||||
[Range(0.0001, double.MaxValue)] public decimal? ContentQty { get; set; }
|
||||
[EnumDataType(typeof(MeasureUnit))] public MeasureUnit? ContentUnit { get; set; }
|
||||
/// <summary>Optional scan code for barcode/RFID lookup. Unlike <see cref="Sku"/>, not required.</summary>
|
||||
[StringLength(100)] public string? Barcode { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateItemStatusRequest
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Dtos.Items;
|
||||
|
||||
/// <summary>Result of a barcode/RFID scan lookup — an item, or an item resolved via a
|
||||
/// specific batch/serial. See <see cref="Services.Interfaces.IItemService.ScanAsync"/>.</summary>
|
||||
public sealed record ItemScanResultDto(
|
||||
int ItemId, string Sku, string Name, TrackingMode TrackingMode, int BaseUomId,
|
||||
string MatchedBy, // "Item" | "Batch" | "Serial"
|
||||
int? BatchId, string? BatchNo, DateOnly? ExpiryDate,
|
||||
int? SerialId, string? SerialNo, string? SerialStatus);
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace ERPCore.Dtos.Notifications;
|
||||
|
||||
public sealed record NotificationDto(
|
||||
int NotificationId,
|
||||
string ModuleKey,
|
||||
string Title,
|
||||
string Message,
|
||||
string? RelatedEntityType,
|
||||
int? RelatedEntityId,
|
||||
DateTime CreatedAt,
|
||||
bool IsRead);
|
||||
|
||||
public sealed record NotificationFeedDto(
|
||||
IReadOnlyList<NotificationDto> Notifications,
|
||||
int UnreadCount);
|
||||
@@ -12,14 +12,14 @@ public sealed record PurchaseInvoiceTotalsDto(
|
||||
|
||||
public sealed record PurchaseInvoiceDto(
|
||||
int PurchaseInvoiceId, string DocNo, string VendorInvoiceNo, DateTime VendorInvoiceDate,
|
||||
int VendorId, string VendorSnapshotName, string? VendorSnapshotTaxNo,
|
||||
int VendorId, int BranchId, string VendorSnapshotName, string? VendorSnapshotTaxNo,
|
||||
PurchaseInvoiceStatus Status, int GrnCount, int CreatedBy, DateTime CreatedAt, DateTime? UpdatedAt,
|
||||
string? GlJournalNo, DateTime? GlPostedAt,
|
||||
PurchaseInvoiceTotalsDto Totals, IReadOnlyList<PurchaseInvoiceLineDto> Lines);
|
||||
|
||||
public sealed record PurchaseInvoiceSummaryDto(
|
||||
int PurchaseInvoiceId, string DocNo, string VendorInvoiceNo, DateTime VendorInvoiceDate,
|
||||
int VendorId, string VendorSnapshotName, PurchaseInvoiceStatus Status, int GrnCount,
|
||||
int VendorId, int BranchId, string VendorSnapshotName, PurchaseInvoiceStatus Status, int GrnCount,
|
||||
PurchaseInvoiceTotalsDto Totals, DateTime CreatedAt, string? GlJournalNo);
|
||||
|
||||
public sealed record PurchaseInvoicePaymentDto(
|
||||
|
||||
@@ -12,13 +12,14 @@ public sealed record PoLineDto(
|
||||
public sealed record PoTotalsDto(decimal SubTotal, decimal Tax, decimal GrandTotal, string Currency);
|
||||
|
||||
public sealed record PurchaseOrderDto(
|
||||
int PoId, string DocNo, int VendorId, int? RequisitionId, PurchaseOrderStatus Status,
|
||||
bool ApprovalRequired, int CreatedBy, DateTime CreatedAt, DateTime? UpdatedAt,
|
||||
int PoId, string DocNo, int VendorId, int BranchId, int? RequisitionId, PurchaseOrderStatus Status,
|
||||
bool ApprovalRequired, int CreatedBy, int? ApprovedBy, DateTime? ApprovedAt,
|
||||
DateTime CreatedAt, DateTime? UpdatedAt,
|
||||
PoTotalsDto Totals, IReadOnlyList<PoLineDto> Lines);
|
||||
|
||||
public sealed record PurchaseOrderSummaryDto(
|
||||
int PoId, string DocNo, int VendorId, PurchaseOrderStatus Status,
|
||||
bool ApprovalRequired, DateTime CreatedAt, PoTotalsDto Totals);
|
||||
int PoId, string DocNo, int VendorId, int BranchId, PurchaseOrderStatus Status,
|
||||
bool ApprovalRequired, int CreatedBy, DateTime CreatedAt, PoTotalsDto Totals);
|
||||
|
||||
// Requests — server sets docNo, status, createdBy, timestamps, qtyReceived, totals
|
||||
|
||||
@@ -35,12 +36,13 @@ public sealed class CreatePurchaseOrderRequest
|
||||
{
|
||||
[Required] public int VendorId { get; set; }
|
||||
public int? RequisitionId { get; set; }
|
||||
public int BranchId { get; set; }
|
||||
[Required, MinLength(1)] public List<CreatePoLineInput> Lines { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// When true the PO is created in <c>Draft</c> (editable/deletable, not yet issued).
|
||||
/// When false (default) it auto-approves on creation, preserving the Requisition→PO
|
||||
/// and RFQ→PO flows unchanged (docs/11 §3.3).
|
||||
/// When false (default) it is issued immediately into <c>PendingApproval</c>, same as
|
||||
/// submitting a Draft (docs/11 §3.3).
|
||||
/// </summary>
|
||||
public bool SaveAsDraft { get; set; }
|
||||
}
|
||||
@@ -49,6 +51,7 @@ public sealed class UpdatePurchaseOrderRequest
|
||||
{
|
||||
[Required] public int VendorId { get; set; }
|
||||
public int? RequisitionId { get; set; }
|
||||
public int BranchId { get; set; }
|
||||
[Required, MinLength(1)] public List<CreatePoLineInput> Lines { get; set; } = new();
|
||||
}
|
||||
|
||||
@@ -56,3 +59,8 @@ public sealed class CancelPurchaseOrderRequest
|
||||
{
|
||||
[StringLength(500)] public string? Reason { get; set; }
|
||||
}
|
||||
|
||||
public sealed class RejectPurchaseOrderRequest
|
||||
{
|
||||
[StringLength(500)] public string? Reason { get; set; }
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ namespace ERPCore.Dtos.Procurement;
|
||||
public sealed record RequisitionLineDto(int ReqLineId, int ItemId, decimal Qty, DateOnly? RequiredBy);
|
||||
|
||||
public sealed record RequisitionDto(
|
||||
int RequisitionId, string DocNo, RequisitionStatus Status, int RequestedBy,
|
||||
int RequisitionId, string DocNo, RequisitionStatus Status, int RequestedBy, int BranchId,
|
||||
DateTime CreatedAt, IReadOnlyList<RequisitionLineDto> Lines);
|
||||
|
||||
public sealed record RequisitionSummaryDto(
|
||||
int RequisitionId, string DocNo, RequisitionStatus Status, int RequestedBy, DateTime CreatedAt, int LineCount);
|
||||
int RequisitionId, string DocNo, RequisitionStatus Status, int RequestedBy, int BranchId, DateTime CreatedAt, int LineCount);
|
||||
|
||||
// Requests — server sets docNo, status, requestedBy (audit actor), timestamps ----
|
||||
|
||||
@@ -26,4 +26,7 @@ public sealed class CreateRequisitionLineInput
|
||||
public sealed class CreateRequisitionRequest
|
||||
{
|
||||
[Required, MinLength(1)] public List<CreateRequisitionLineInput> Lines { get; set; } = new();
|
||||
/// <summary>Optional — resolved via <see cref="Services.Interfaces.IBranchConfigService.ResolveBranchIdAsync"/>
|
||||
/// when branching is enabled; ignored (defaulted) otherwise.</summary>
|
||||
public int BranchId { get; set; }
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ namespace ERPCore.Dtos.Procurement;
|
||||
public sealed record RfqLineDto(int RfqLineId, int ItemId, decimal Qty);
|
||||
|
||||
public sealed record RfqDto(
|
||||
int RfqId, string DocNo, int RequisitionId, RfqStatus Status, IReadOnlyList<RfqLineDto> Lines);
|
||||
int RfqId, string DocNo, int RequisitionId, int BranchId, RfqStatus Status, IReadOnlyList<RfqLineDto> Lines);
|
||||
|
||||
/// <summary>Row shape for <c>GET /rfqs</c> — line/quotation counts instead of the lines themselves.</summary>
|
||||
public sealed record RfqSummaryDto(
|
||||
int RfqId, string DocNo, int RequisitionId, RfqStatus Status, int LineCount, int QuotationCount);
|
||||
int RfqId, string DocNo, int RequisitionId, int BranchId, RfqStatus Status, int LineCount, int QuotationCount);
|
||||
|
||||
public sealed record QuotationLineDto(int ItemId, decimal UnitPrice, int LeadDays);
|
||||
|
||||
|
||||
@@ -11,4 +11,4 @@ namespace ERPCore.Dtos.Rbac;
|
||||
/// entirely rather than merely restricting them by role.</summary>
|
||||
public sealed record MeResponseDto(
|
||||
string? RoleCode, string? RoleName, IReadOnlyList<string> NavCodes,
|
||||
bool IsAdmin, int? BranchId, string? BranchName, bool BranchingEnabled);
|
||||
bool IsAdmin, int? BranchId, string? BranchName, bool BranchingEnabled, bool WarehouseBranchingEnabled);
|
||||
|
||||
@@ -29,6 +29,22 @@ public sealed class AssignRolePermissionsRequest
|
||||
{
|
||||
public List<int> NavItemIds { get; set; } = new();
|
||||
public List<int> SubNavItemIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Optional per-nav/sub-nav-item action override, keyed by <c>NavItemId</c>/
|
||||
/// <c>SubNavItemId</c> and valued with a <see cref="RolePermissionAction"/> bitmask
|
||||
/// (e.g. <c>View|Create|Edit</c> = 7 to grant a module without Delete/Approve). An id
|
||||
/// present in <see cref="NavItemIds"/>/<see cref="SubNavItemIds"/> but absent here
|
||||
/// keeps today's default of <see cref="RolePermissionAction.All"/> — this only narrows,
|
||||
/// never grants access to an id that isn't also in those lists.
|
||||
/// </summary>
|
||||
public Dictionary<int, RolePermissionAction> NavItemActions { get; set; } = new();
|
||||
public Dictionary<int, RolePermissionAction> SubNavItemActions { get; set; } = new();
|
||||
}
|
||||
|
||||
public sealed record RolePermissionsDto(int RoleId, List<int> NavItemIds, List<int> SubNavItemIds);
|
||||
public sealed record RolePermissionsDto(
|
||||
int RoleId,
|
||||
List<int> NavItemIds,
|
||||
List<int> SubNavItemIds,
|
||||
Dictionary<int, RolePermissionAction> NavItemActions,
|
||||
Dictionary<int, RolePermissionAction> SubNavItemActions);
|
||||
|
||||
@@ -20,19 +20,21 @@ public sealed record SalesDayEndInvoiceSummaryDto(
|
||||
public sealed record SalesDayEndDto(
|
||||
int SalesDayEndId, string DocNo, int CashierUserId, DateOnly BusinessDate,
|
||||
int SlipCount, int BundleCount, decimal Subtotal, decimal DiscountTotal, decimal TaxTotal, decimal GrandTotal,
|
||||
decimal PaidTotal, decimal BalanceTotal,
|
||||
decimal CostOfGoodsSold, string? GlJournalNo, DateTime? GlPostedAt, int ClosedBy, DateTime ClosedAt,
|
||||
IReadOnlyList<string> SlipNumbers, IReadOnlyList<string> BundleNumbers, IReadOnlyList<SalesDayEndItemLineDto> ItemBreakdown,
|
||||
SalesDayEndInvoiceSummaryDto Invoices);
|
||||
|
||||
public sealed record SalesDayEndSummaryDto(
|
||||
int SalesDayEndId, string DocNo, int CashierUserId, DateOnly BusinessDate,
|
||||
int SlipCount, int BundleCount, decimal GrandTotal, string? GlJournalNo, DateTime ClosedAt);
|
||||
int SlipCount, int BundleCount, decimal GrandTotal, decimal PaidTotal, decimal BalanceTotal, string? GlJournalNo, DateTime ClosedAt);
|
||||
|
||||
/// <summary>What closing right now would include — call before <c>POST /sales-day-end</c> so the
|
||||
/// cashier can see the day's totals, and any still-Draft slips/bundles blocking the close.</summary>
|
||||
public sealed record SalesDayEndPreviewDto(
|
||||
int CashierUserId, DateOnly BusinessDate, bool AlreadyClosed,
|
||||
int SlipCount, int BundleCount, decimal Subtotal, decimal DiscountTotal, decimal TaxTotal, decimal GrandTotal,
|
||||
decimal PaidTotal, decimal BalanceTotal,
|
||||
IReadOnlyList<string> SlipNumbers, IReadOnlyList<string> BundleNumbers,
|
||||
IReadOnlyList<DraftSlipBlockingCloseDto> DraftSlipsBlockingClose,
|
||||
IReadOnlyList<DraftBundleBlockingCloseDto> DraftBundleSalesBlockingClose,
|
||||
|
||||
@@ -56,7 +56,9 @@ public sealed class CreateSalesInvoiceLineRequest
|
||||
[Range(0, 100)] public decimal DiscountPct { get; set; }
|
||||
[Range(0, double.MaxValue)] public decimal DiscountAmount { get; set; }
|
||||
[Range(0, double.MaxValue)] public decimal DiscountValue { get; set; }
|
||||
[Range(0, 100)] public decimal TaxPct { get; set; }
|
||||
/// <summary>Explicit override. Omit (null) to use the item's assigned TaxRate — see
|
||||
/// <see cref="Services.Interfaces.ISalesDomainService.ResolveLineTaxPctAsync"/>.</summary>
|
||||
[Range(0, 100)] public decimal? TaxPct { get; set; }
|
||||
public bool IsFreeIssue { get; set; }
|
||||
public int? ParentLineId { get; set; }
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ public sealed record SalesSlipLineDto(
|
||||
int SalesSlipLineId, int ItemId, string Description, decimal Qty, decimal FreeQty,
|
||||
int WarehouseId, decimal UnitPrice, decimal BaseCost, string PriceSource, decimal DiscountPct,
|
||||
decimal DiscountAmount, SalesDiscountMode DiscountMode, decimal NetUnitPrice, decimal LineTotal,
|
||||
decimal TaxPct, decimal TaxAmount, bool IsFreeIssue, int? ParentLineId);
|
||||
decimal TaxPct, decimal TaxAmount, bool IsFreeIssue, int? ParentLineId,
|
||||
int? BatchId, int? SerialId);
|
||||
|
||||
public sealed record SalesSlipTotalsDto(
|
||||
decimal Subtotal, decimal DiscountTotal, decimal FreeQtyTotal, decimal TaxTotal, decimal GrandTotal,
|
||||
@@ -54,9 +55,15 @@ public sealed class CreateSalesSlipLineRequest
|
||||
[Range(0, 100)] public decimal DiscountPct { get; set; }
|
||||
[Range(0, double.MaxValue)] public decimal DiscountAmount { get; set; }
|
||||
[Range(0, double.MaxValue)] public decimal DiscountValue { get; set; }
|
||||
[Range(0, 100)] public decimal TaxPct { get; set; }
|
||||
/// <summary>Explicit override. Omit (null) to use the item's assigned TaxRate — see
|
||||
/// <see cref="Services.Interfaces.ISalesDomainService.ResolveLineTaxPctAsync"/>.</summary>
|
||||
[Range(0, 100)] public decimal? TaxPct { get; set; }
|
||||
public bool IsFreeIssue { get; set; }
|
||||
public int? ParentLineId { get; set; }
|
||||
/// <summary>Pins the line to a specific batch (must belong to <see cref="ItemId"/>), consumed via FIFO.</summary>
|
||||
public int? BatchId { get; set; }
|
||||
/// <summary>Pins the line to a specific serial (must belong to <see cref="ItemId"/>); marked Sold on posting.</summary>
|
||||
public int? SerialId { get; set; }
|
||||
}
|
||||
|
||||
public sealed class CreateSalesSlipRequest
|
||||
@@ -65,6 +72,16 @@ public sealed class CreateSalesSlipRequest
|
||||
[Required] public int WarehouseId { get; set; }
|
||||
[Required] public int CashierUserId { get; set; }
|
||||
[Required, MinLength(1)] public List<CreateSalesSlipLineRequest> Lines { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// How much the customer actually paid at ring-up. Omit (or send null) for the default —
|
||||
/// fully paid, i.e. <c>PaidAmount == GrandTotal</c> and <c>BalanceAmount == 0</c> — matching
|
||||
/// every slip's behavior before partial payment existed. Must be between 0 and the computed
|
||||
/// GrandTotal; anything less than GrandTotal leaves the difference as BalanceAmount owed by
|
||||
/// the customer "on account," which Sales Day-End then splits between Cash and Accounts
|
||||
/// Receivable when it posts (see SalesDayEndService.CloseAsync).
|
||||
/// </summary>
|
||||
[Range(0, double.MaxValue)] public decimal? PaidAmount { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateSalesSlipRequest
|
||||
@@ -73,4 +90,7 @@ public sealed class UpdateSalesSlipRequest
|
||||
[Required] public int WarehouseId { get; set; }
|
||||
[Required] public int CashierUserId { get; set; }
|
||||
[Required, MinLength(1)] public List<CreateSalesSlipLineRequest> Lines { get; set; } = new();
|
||||
|
||||
/// <summary>See <see cref="CreateSalesSlipRequest.PaidAmount"/>.</summary>
|
||||
[Range(0, double.MaxValue)] public decimal? PaidAmount { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace ERPCore.Dtos.Search;
|
||||
|
||||
public enum GlobalSearchResultType
|
||||
{
|
||||
Item,
|
||||
PurchaseOrder,
|
||||
Invoice,
|
||||
Employee
|
||||
}
|
||||
|
||||
public sealed record GlobalSearchResultDto(
|
||||
GlobalSearchResultType Type,
|
||||
int Id,
|
||||
string Number,
|
||||
string Title,
|
||||
string? Subtitle);
|
||||
@@ -5,7 +5,9 @@ namespace ERPCore.Dtos.Stock;
|
||||
|
||||
// Responses (docs/11 §5.6) ------------------------------------------------------
|
||||
|
||||
public sealed record CountLineDto(int CountLineId, int ItemId, int? BinId, decimal SystemQty, decimal? CountedQty, decimal? Variance);
|
||||
public sealed record CountLineDto(
|
||||
int CountLineId, int ItemId, int? BinId, decimal SystemQty, decimal? CountedQty, decimal? Variance,
|
||||
int? BatchId, string? BatchNo, int? SerialId, string? SerialNo);
|
||||
|
||||
public sealed record CountDto(
|
||||
int CountId, string DocNo, int WarehouseId, int BranchId, CountType CountType, CountStatus Status,
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Dtos.Support;
|
||||
|
||||
public sealed class CreateSupportTicketRequest
|
||||
{
|
||||
[Required, MaxLength(200)]
|
||||
public string Subject { get; set; } = string.Empty;
|
||||
|
||||
[Required, MaxLength(2000)]
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed class AddSupportTicketMessageRequest
|
||||
{
|
||||
[Required, MaxLength(2000)]
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed class UpdateSupportTicketStatusRequest
|
||||
{
|
||||
[Required]
|
||||
public TicketStatus Status { get; set; }
|
||||
}
|
||||
|
||||
public sealed record SupportTicketMessageDto(
|
||||
int MessageId,
|
||||
int SenderUserId,
|
||||
string SenderName,
|
||||
bool IsFromAdmin,
|
||||
string Message,
|
||||
DateTime CreatedAt);
|
||||
|
||||
public sealed record SupportTicketSummaryDto(
|
||||
int TicketId,
|
||||
string Subject,
|
||||
TicketStatus Status,
|
||||
int CreatedBy,
|
||||
string CreatedByName,
|
||||
DateTime CreatedAt,
|
||||
int? UpdatedBy,
|
||||
DateTime? UpdatedAt,
|
||||
int MessageCount);
|
||||
|
||||
public sealed record SupportTicketDto(
|
||||
int TicketId,
|
||||
string Subject,
|
||||
TicketStatus Status,
|
||||
int CreatedBy,
|
||||
string CreatedByName,
|
||||
DateTime CreatedAt,
|
||||
int? UpdatedBy,
|
||||
string? UpdatedByName,
|
||||
DateTime? UpdatedAt,
|
||||
IReadOnlyList<SupportTicketMessageDto> Messages);
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Dtos.TaxRates;
|
||||
|
||||
public sealed record TaxRateDto(
|
||||
int TaxRateId, string Code, string Name, decimal Percentage, EntityStatus Status, DateTime CreatedAt, DateTime? UpdatedAt);
|
||||
|
||||
public sealed class CreateTaxRateRequest
|
||||
{
|
||||
[Required, StringLength(20)] public string Code { get; set; } = string.Empty;
|
||||
[Required, StringLength(100)] public string Name { get; set; } = string.Empty;
|
||||
[Range(0, 100)] public decimal Percentage { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateTaxRateRequest
|
||||
{
|
||||
[Required, StringLength(20)] public string Code { get; set; } = string.Empty;
|
||||
[Required, StringLength(100)] public string Name { get; set; } = string.Empty;
|
||||
[Range(0, 100)] public decimal Percentage { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateTaxRateStatusRequest
|
||||
{
|
||||
[Required, EnumDataType(typeof(EntityStatus))] public EntityStatus Status { get; set; }
|
||||
}
|
||||
@@ -7,6 +7,15 @@ public sealed record ManagedUserDto(
|
||||
int UserId, string Username, string DisplayName, string? Email, EntityStatus Status,
|
||||
int? RoleId, string? RoleCode, string? RoleName);
|
||||
|
||||
/// <summary>At least one identifier must be supplied — matches AuthHex's own OR-across-fields dedupe.</summary>
|
||||
public sealed class PurgeAuthHexIdentityRequest
|
||||
{
|
||||
public string? Email { get; set; }
|
||||
public string? MobileNumber { get; set; }
|
||||
public string? Nic { get; set; }
|
||||
public string? UserName { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a user in both backends: forwards to AuthHex's `registerUser` (source
|
||||
/// of truth for credentials), then mirrors the account into ERPCore's local
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace ERPCore.Dtos.Vendors;
|
||||
/// <summary>Vendor resource (docs/11-BACKEND-PHASE1.md §2.4).</summary>
|
||||
public sealed record VendorDto(
|
||||
int VendorId, string Code, string Name, string? Terms, string? TaxReg,
|
||||
string Currency, EntityStatus Status, DateTime CreatedAt, DateTime? UpdatedAt);
|
||||
string Currency, EntityStatus Status, int BranchId, DateTime CreatedAt, DateTime? UpdatedAt);
|
||||
|
||||
public sealed class CreateVendorRequest
|
||||
{
|
||||
@@ -15,6 +15,9 @@ public sealed class CreateVendorRequest
|
||||
[StringLength(50)] public string? Terms { get; set; }
|
||||
[StringLength(50)] public string? TaxReg { get; set; }
|
||||
[Required, StringLength(3, MinimumLength = 3)] public string Currency { get; set; } = "LKR";
|
||||
/// <summary>Optional — resolved via <see cref="Services.Interfaces.IBranchConfigService.ResolveBranchIdAsync"/>
|
||||
/// when branching is enabled; ignored (defaulted) otherwise.</summary>
|
||||
public int BranchId { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateVendorRequest
|
||||
@@ -24,6 +27,7 @@ public sealed class UpdateVendorRequest
|
||||
[StringLength(50)] public string? Terms { get; set; }
|
||||
[StringLength(50)] public string? TaxReg { get; set; }
|
||||
[Required, StringLength(3, MinimumLength = 3)] public string Currency { get; set; } = "LKR";
|
||||
public int BranchId { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateVendorStatusRequest
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ERPCore.Dtos.Warehouses;
|
||||
/// <summary>Warehouse resource (docs/11-BACKEND-PHASE1.md §2.5). <see cref="BranchId"/> is
|
||||
/// the anchor `docs/BRANCH_ISOLATION_PLAN.md` uses to branch-scope everything that carries
|
||||
/// a `warehouseId` (Sales, GRN, stock, ...) without a column on every one of those entities.</summary>
|
||||
public sealed record WarehouseDto(int WarehouseId, string Code, string Name, int BranchId, string? BranchName);
|
||||
public sealed record WarehouseDto(int WarehouseId, string Code, string Name, string? Address, string? Phone, int BranchId, string? BranchName);
|
||||
|
||||
/// <summary>Bin/location resource (docs/11 §2.5).</summary>
|
||||
public sealed record BinDto(int BinId, int WarehouseId, string Code, string? BinType);
|
||||
@@ -14,6 +14,17 @@ public sealed class CreateWarehouseRequest
|
||||
{
|
||||
[Required, StringLength(50)] public string Code { get; set; } = string.Empty;
|
||||
[Required, StringLength(200)] public string Name { get; set; } = string.Empty;
|
||||
[StringLength(300)] public string? Address { get; set; }
|
||||
[StringLength(30)] public string? Phone { get; set; }
|
||||
[Required] public int BranchId { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpdateWarehouseRequest
|
||||
{
|
||||
[Required, StringLength(50)] public string Code { get; set; } = string.Empty;
|
||||
[Required, StringLength(200)] public string Name { get; set; } = string.Empty;
|
||||
[StringLength(300)] public string? Address { get; set; }
|
||||
[StringLength(30)] public string? Phone { get; set; }
|
||||
[Required] public int BranchId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user