price adjustment and stock adjustments
This commit is contained in:
@@ -26,4 +26,13 @@ public static class DocumentTypes
|
||||
|
||||
/// <summary>Cashier day-end close-out (Sales) — <c>DEND-2026-00001</c>.</summary>
|
||||
public const string SalesDayEnd = "DEND";
|
||||
|
||||
/// <summary>Business expense bill (Accounts) — <c>EXP-BR-001-2026-00001</c>.</summary>
|
||||
public const string Expense = "EXP";
|
||||
|
||||
/// <summary>Till cash deposited to a bank account (Accounts) — <c>BD-BR-001-2026-00001</c>.</summary>
|
||||
public const string BankDeposit = "BD";
|
||||
|
||||
/// <summary>Selling-price change request (Products) — <c>PADJ-2026-00001</c>.</summary>
|
||||
public const string PriceAdjustment = "PADJ";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Till cash taken to the bank (docs/BANK_DEPOSIT_MODULE_PLAN.md §4). Saving it posts a GL entry
|
||||
/// (Debit the bank account / Credit the cash account) and lowers the branch's cash in hand for
|
||||
/// <see cref="BusinessDate"/>. There is no draft: a wrong deposit is cancelled (the entry is
|
||||
/// reversed) and entered again. GL accounts have no local FK, so the account details are snapshots.
|
||||
/// </summary>
|
||||
public class BankDeposit
|
||||
{
|
||||
public int BankDepositId { get; set; }
|
||||
public string DocNo { get; set; } = string.Empty;
|
||||
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
/// <summary>The day whose cash is deposited — cash in hand and the day-end report group by this.</summary>
|
||||
public DateOnly BusinessDate { get; set; }
|
||||
/// <summary>The day the bank received it; the GL entry date.</summary>
|
||||
public DateOnly DepositDate { get; set; }
|
||||
|
||||
public decimal Amount { get; set; }
|
||||
|
||||
public long FromGlCashAccountId { get; set; }
|
||||
public string FromCashAccountCode { get; set; } = string.Empty;
|
||||
public string FromCashAccountName { get; set; } = string.Empty;
|
||||
|
||||
public long ToGlBankAccountId { get; set; }
|
||||
public string ToBankAccountCode { get; set; } = string.Empty;
|
||||
public string ToBankAccountName { get; set; } = string.Empty;
|
||||
public string? ToBankName { get; set; }
|
||||
public string? ToAccountNumber { get; set; }
|
||||
|
||||
public string? DepositSlipNo { get; set; }
|
||||
public string? DepositedBy { get; set; }
|
||||
public string? Remarks { get; set; }
|
||||
|
||||
public BankDepositStatus Status { get; set; } = BankDepositStatus.Posted;
|
||||
|
||||
public string? GlJournalNo { get; set; }
|
||||
public DateTime? GlPostedAt { get; set; }
|
||||
|
||||
public string? GlReversalJournalNo { get; set; }
|
||||
public string? CancelReason { get; set; }
|
||||
public int? CancelledBy { get; set; }
|
||||
public DateTime? CancelledAt { get; set; }
|
||||
|
||||
public int CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public uint RowVersion { get; set; }
|
||||
}
|
||||
@@ -25,6 +25,11 @@ public class BundleSale
|
||||
public decimal DiscountTotal { get; set; }
|
||||
public decimal TaxTotal { get; set; }
|
||||
public decimal GrandTotal { get; set; }
|
||||
|
||||
/// <summary>How the (always fully paid) <see cref="GrandTotal"/> was tendered:
|
||||
/// <c>CashAmount + CardAmount == GrandTotal</c>. Backfilled as all cash.</summary>
|
||||
public decimal CashAmount { get; set; }
|
||||
public decimal CardAmount { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// One approval decision on a document (docs/DUAL_APPROVAL_PLAN.md §4.1) — a row per decision, so
|
||||
/// the full trail survives. Polymorphic like the stock ledger: <see cref="DocType"/> +
|
||||
/// <see cref="DocId"/>, no FK. Doc types: <c>ADJ</c> (stock adjustment), <c>PADJ</c> (price adjustment).
|
||||
/// </summary>
|
||||
public class DocumentApproval
|
||||
{
|
||||
public int DocumentApprovalId { get; set; }
|
||||
public string DocType { get; set; } = string.Empty;
|
||||
public int DocId { get; set; }
|
||||
/// <summary>1 or 2.</summary>
|
||||
public int Level { get; set; }
|
||||
public ApprovalDecision Decision { get; set; }
|
||||
public int DecidedBy { get; set; }
|
||||
public User? Decider { get; set; }
|
||||
public DateTime DecidedAt { get; set; }
|
||||
public string? Comment { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Approval rules (docs/DUAL_APPROVAL_PLAN.md §7). Singleton row, edited under Settings → Approvals.
|
||||
/// Levels: 0 = no approval (applies on create), 1 = one approver, 2 = two different approvers.
|
||||
/// </summary>
|
||||
public class ApprovalConfig
|
||||
{
|
||||
public const int SingletonId = 1;
|
||||
|
||||
public int ApprovalConfigId { get; set; }
|
||||
|
||||
public int StockAdjustmentLevels { get; set; } = 2;
|
||||
/// <summary>With 2 levels: an adjustment whose stock value is below this needs only one approval. 0 = always two.</summary>
|
||||
public decimal StockAdjustmentLevel2ThresholdValue { get; set; }
|
||||
|
||||
public int PriceAdjustmentLevels { get; set; } = 2;
|
||||
/// <summary>With 2 levels: a change smaller than this percent (largest across its lines) needs only one approval. 0 = always two.</summary>
|
||||
public decimal PriceAdjustmentLevel2ThresholdPercent { get; set; }
|
||||
|
||||
/// <summary>Comma-separated role codes allowed to give the second approval; empty = anyone with the Approve action.</summary>
|
||||
public string? Level2RoleCodes { get; set; }
|
||||
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public int? UpdatedBy { get; set; }
|
||||
public uint RowVersion { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// One business expense bill (electricity, rent, …) outside procurement. Draft is editable;
|
||||
/// Post accrues it to GL (Debit the title's expense account / Credit Accrued Expenses);
|
||||
/// payments then settle the accrual in one or more installments (see
|
||||
/// ExpensePaymentService). Model: docs/EXPENSE_MODULE_PLAN.md §3.3.
|
||||
/// </summary>
|
||||
public class Expense
|
||||
{
|
||||
public int ExpenseId { get; set; }
|
||||
public string DocNo { get; set; } = string.Empty;
|
||||
|
||||
public int BranchId { get; set; }
|
||||
public Branch? Branch { get; set; }
|
||||
|
||||
public DateOnly ExpenseDate { get; set; }
|
||||
public DateOnly? DueDate { get; set; }
|
||||
|
||||
public int ExpenseCategoryId { get; set; }
|
||||
public ExpenseCategory? Category { get; set; }
|
||||
|
||||
public int ExpenseTitleId { get; set; }
|
||||
public ExpenseTitle? Title { get; set; }
|
||||
|
||||
public string? Payee { get; set; }
|
||||
public int? VendorId { get; set; }
|
||||
public Vendor? Vendor { get; set; }
|
||||
|
||||
public string? BillReference { get; set; }
|
||||
public string? Description { get; set; }
|
||||
/// <summary>Optional month the bill covers, as <c>yyyy-MM</c> (e.g. September's electricity).</summary>
|
||||
public string? PeriodMonth { get; set; }
|
||||
|
||||
public decimal Amount { get; set; }
|
||||
public decimal PaidAmount { get; set; }
|
||||
public decimal BalanceAmount { get; set; }
|
||||
|
||||
public ExpenseStatus Status { get; set; } = ExpenseStatus.Draft;
|
||||
public ExpensePaymentStatus PaymentStatus { get; set; } = ExpensePaymentStatus.Unpaid;
|
||||
|
||||
/// <summary>Snapshot of the title's GL expense account at post time.</summary>
|
||||
public string? GlExpenseAccountCode { get; set; }
|
||||
/// <summary>Journal number of the accrual entry posted on Post.</summary>
|
||||
public string? GlJournalNo { get; set; }
|
||||
public DateTime? GlPostedAt { get; set; }
|
||||
/// <summary>Journal number of the reversing entry posted on Cancel (Posted expenses only).</summary>
|
||||
public string? GlReversalJournalNo { get; set; }
|
||||
public string? CancelReason { get; set; }
|
||||
|
||||
public int CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<ExpensePayment> Payments { get; set; } = new List<ExpensePayment>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A payment against a Posted expense's balance (installments allowed). Every line of one
|
||||
/// payment submission shares the single GL journal entry that submission posted (Debit
|
||||
/// Accrued Expenses / Credit each selected cash-or-bank account). Mirrors
|
||||
/// <see cref="PurchaseInvoicePayment"/>.
|
||||
/// </summary>
|
||||
public class ExpensePayment
|
||||
{
|
||||
public int ExpensePaymentId { get; set; }
|
||||
|
||||
public int ExpenseId { get; set; }
|
||||
public Expense? Expense { get; set; }
|
||||
|
||||
public decimal Amount { get; set; }
|
||||
public DateTime PaymentDate { get; set; }
|
||||
public ExpensePaymentMethod PaymentMethod { get; set; }
|
||||
|
||||
/// <summary>GL's numeric id for the bank/cash account the payment was made from.</summary>
|
||||
public long GlBankAccountId { get; set; }
|
||||
/// <summary>Snapshot of the account's display name at payment time (GL account lists have no local FK).</summary>
|
||||
public string BankAccountName { get; set; } = string.Empty;
|
||||
|
||||
public string? ChequeNo { get; set; }
|
||||
public string? Reference { get; set; }
|
||||
public string? GlJournalNo { get; set; }
|
||||
|
||||
public int CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Top-level expense grouping (Utility, Rental, Salaries, Other). The four seeded rows are
|
||||
/// <see cref="IsSystem"/> — they can be deactivated but not renamed; admins can add more.
|
||||
/// Each category owns its <see cref="ExpenseTitle"/>s. Model: docs/EXPENSE_MODULE_PLAN.md §3.1.
|
||||
/// </summary>
|
||||
public class ExpenseCategory
|
||||
{
|
||||
public int ExpenseCategoryId { get; set; }
|
||||
public string Code { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public bool IsSystem { get; set; }
|
||||
public EntityStatus Status { get; set; } = EntityStatus.Active;
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<ExpenseTitle> Titles { get; set; } = new List<ExpenseTitle>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A specific expense under a category (Utility → Electricity, Water, …). Carries the GL
|
||||
/// expense account debited when an expense with this title is posted — snapshotted onto the
|
||||
/// expense at post time, so changing it later does not touch already-posted expenses.
|
||||
/// Model: docs/EXPENSE_MODULE_PLAN.md §3.2.
|
||||
/// </summary>
|
||||
public class ExpenseTitle
|
||||
{
|
||||
public int ExpenseTitleId { get; set; }
|
||||
|
||||
public int ExpenseCategoryId { get; set; }
|
||||
public ExpenseCategory? Category { get; set; }
|
||||
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string GlExpenseAccountCode { get; set; } = string.Empty;
|
||||
public bool IsSystem { get; set; }
|
||||
public EntityStatus Status { get; set; } = EntityStatus.Active;
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public uint RowVersion { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// A request to change items' selling prices (docs/DUAL_APPROVAL_PLAN.md §6). Nothing changes on the
|
||||
/// items until it is fully approved; then each line's new prices are written to its item and an
|
||||
/// <see cref="ItemPriceHistory"/> row is kept. <see cref="CreatedBy"/> is the requester.
|
||||
/// </summary>
|
||||
public class PriceAdjustment
|
||||
{
|
||||
public int PriceAdjustmentId { get; set; }
|
||||
public string DocNo { get; set; } = string.Empty;
|
||||
public string Reason { get; set; } = string.Empty;
|
||||
|
||||
public PriceAdjustmentStatus Status { get; set; } = PriceAdjustmentStatus.PendingApproval;
|
||||
public int RequiredApprovals { get; set; }
|
||||
|
||||
public int CreatedBy { get; set; }
|
||||
public User? Creator { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public int? ApprovedLevel1By { get; set; }
|
||||
public DateTime? ApprovedLevel1At { get; set; }
|
||||
public int? ApprovedLevel2By { get; set; }
|
||||
public DateTime? ApprovedLevel2At { get; set; }
|
||||
public int? RejectedBy { get; set; }
|
||||
public DateTime? RejectedAt { get; set; }
|
||||
public string? RejectReason { get; set; }
|
||||
public DateTime? CancelledAt { get; set; }
|
||||
/// <summary>When the new prices were written to the items.</summary>
|
||||
public DateTime? AppliedAt { get; set; }
|
||||
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<PriceAdjustmentLine> Lines { get; set; } = new List<PriceAdjustmentLine>();
|
||||
}
|
||||
|
||||
/// <summary>One item's change. The Old* values are the item's prices when the request was made —
|
||||
/// approval fails if the item has been repriced since (stale request).</summary>
|
||||
public class PriceAdjustmentLine
|
||||
{
|
||||
public int PriceAdjustmentLineId { get; set; }
|
||||
public int PriceAdjustmentId { get; set; }
|
||||
public PriceAdjustment? PriceAdjustment { get; set; }
|
||||
|
||||
public int ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
|
||||
public decimal? OldMinPrice { get; set; }
|
||||
public decimal? OldMaxPrice { get; set; }
|
||||
public decimal? OldFlatPrice { get; set; }
|
||||
public decimal? NewMinPrice { get; set; }
|
||||
public decimal? NewMaxPrice { get; set; }
|
||||
public decimal? NewFlatPrice { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>An applied selling-price change: what it was, what it became, and who approved it.</summary>
|
||||
public class ItemPriceHistory
|
||||
{
|
||||
public int ItemPriceHistoryId { get; set; }
|
||||
public int ItemId { get; set; }
|
||||
public Item? Item { get; set; }
|
||||
public int? PriceAdjustmentId { get; set; }
|
||||
public PriceAdjustment? PriceAdjustment { get; set; }
|
||||
|
||||
public decimal? OldMinPrice { get; set; }
|
||||
public decimal? OldMaxPrice { get; set; }
|
||||
public decimal? OldFlatPrice { get; set; }
|
||||
public decimal? NewMinPrice { get; set; }
|
||||
public decimal? NewMaxPrice { get; set; }
|
||||
public decimal? NewFlatPrice { get; set; }
|
||||
|
||||
public int RequestedBy { get; set; }
|
||||
public int? ApprovedLevel1By { get; set; }
|
||||
public int? ApprovedLevel2By { get; set; }
|
||||
public DateTime AppliedAt { get; set; }
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
|
||||
namespace ERPCore.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
@@ -21,6 +23,9 @@ public class SalesInvoicePayment
|
||||
/// <summary>Snapshot of the account's display name at payment time (GL account lists have no local FK).</summary>
|
||||
public string BankAccountName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>How the customer paid. Payments recorded before this existed were backfilled as Cash.</summary>
|
||||
public SalesPaymentMethod PaymentMethod { get; set; } = SalesPaymentMethod.Cash;
|
||||
|
||||
public string? Reference { get; set; }
|
||||
|
||||
/// <summary>Journal number of the real GL journal entry this payment posted.</summary>
|
||||
|
||||
@@ -27,6 +27,11 @@ public class SalesSlip
|
||||
public decimal PaidAmount { get; set; }
|
||||
public decimal BalanceAmount { get; set; }
|
||||
|
||||
/// <summary>How <see cref="PaidAmount"/> was tendered: <c>CashAmount + CardAmount == PaidAmount</c>.
|
||||
/// Slips from before the split existed were backfilled as all cash.</summary>
|
||||
public decimal CashAmount { get; set; }
|
||||
public decimal CardAmount { get; set; }
|
||||
|
||||
/// <summary>Set once this slip's business date is closed by <see cref="SalesDayEnd"/> — a closed slip is frozen (no further edits).</summary>
|
||||
public int? DayEndId { get; set; }
|
||||
public SalesDayEnd? DayEnd { get; set; }
|
||||
|
||||
@@ -37,5 +37,20 @@ public class StockAdjustment
|
||||
public string? GlJournalNo { get; set; }
|
||||
public DateTime? GlPostedAt { get; set; }
|
||||
|
||||
// --- Approval (docs/DUAL_APPROVAL_PLAN.md §5). CreatedBy is the requester. ---
|
||||
|
||||
/// <summary>Approvals this request needs (0 = posted on create, 1 or 2), fixed when it is made.</summary>
|
||||
public int RequiredApprovals { get; set; }
|
||||
public int? ApprovedLevel1By { get; set; }
|
||||
public DateTime? ApprovedLevel1At { get; set; }
|
||||
public int? ApprovedLevel2By { get; set; }
|
||||
public DateTime? ApprovedLevel2At { get; set; }
|
||||
public int? RejectedBy { get; set; }
|
||||
public DateTime? RejectedAt { get; set; }
|
||||
public string? RejectReason { get; set; }
|
||||
public DateTime? CancelledAt { get; set; }
|
||||
/// <summary>When stock actually moved — the ledger and GL use this, not <see cref="CreatedAt"/>.</summary>
|
||||
public DateTime? PostedAt { get; set; }
|
||||
|
||||
public ICollection<StockAdjustmentLine> Lines { get; set; } = new List<StockAdjustmentLine>();
|
||||
}
|
||||
|
||||
@@ -21,4 +21,12 @@ public class StockAdjustmentLine
|
||||
public Serial? Serial { get; set; }
|
||||
|
||||
public decimal QtyDelta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The serials named on the request, kept until it posts (JSON arrays): outbound serial ids
|
||||
/// to write off, inbound serial numbers found. Re-validated at posting, because a pending
|
||||
/// request moves nothing and the serials may have moved in the meantime.
|
||||
/// </summary>
|
||||
public string? RequestedSerialIds { get; set; }
|
||||
public string? RequestedSerialNos { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,13 +1,33 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Stock-adjustment lifecycle (docs/10 §B.8.1). Phase 1 auto-posts, so
|
||||
/// <see cref="PendingApproval"/> is reserved for the future threshold-approval
|
||||
/// workflow (FR-STK-07). Stored as a string.
|
||||
/// Stock-adjustment lifecycle (docs/DUAL_APPROVAL_PLAN.md §5.1). A new adjustment is a request
|
||||
/// (<see cref="PendingApproval"/>, then <see cref="PendingSecondApproval"/> when two approvals are
|
||||
/// required) and only moves stock when it becomes <see cref="Posted"/>. With approvals switched off
|
||||
/// (<c>ApprovalConfig.StockAdjustmentLevels = 0</c>) it posts on create, as before. Stored as a string.
|
||||
/// </summary>
|
||||
public enum AdjustmentStatus
|
||||
{
|
||||
Draft,
|
||||
PendingApproval,
|
||||
Posted
|
||||
Posted,
|
||||
PendingSecondApproval,
|
||||
Rejected,
|
||||
Cancelled
|
||||
}
|
||||
|
||||
/// <summary>Price-adjustment lifecycle — same request flow as <see cref="AdjustmentStatus"/>; <see cref="Approved"/> means applied.</summary>
|
||||
public enum PriceAdjustmentStatus
|
||||
{
|
||||
PendingApproval,
|
||||
PendingSecondApproval,
|
||||
Approved,
|
||||
Rejected,
|
||||
Cancelled
|
||||
}
|
||||
|
||||
public enum ApprovalDecision
|
||||
{
|
||||
Approved,
|
||||
Rejected
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>A deposit is posted as soon as it is saved; a wrong one is cancelled (GL reversed) and re-entered.</summary>
|
||||
public enum BankDepositStatus
|
||||
{
|
||||
Posted,
|
||||
Cancelled
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
public enum ExpenseStatus
|
||||
{
|
||||
Draft,
|
||||
Posted,
|
||||
Cancelled
|
||||
}
|
||||
|
||||
/// <summary>Settlement state of a Posted expense, derived from its paid/balance amounts.</summary>
|
||||
public enum ExpensePaymentStatus
|
||||
{
|
||||
Unpaid,
|
||||
PartiallyPaid,
|
||||
Paid
|
||||
}
|
||||
|
||||
public enum ExpensePaymentMethod
|
||||
{
|
||||
Cash,
|
||||
BankTransfer,
|
||||
Cheque,
|
||||
Card
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace ERPCore.Domain.Enums;
|
||||
|
||||
/// <summary>How a customer paid for a sale — recorded per invoice payment (and split into
|
||||
/// cash/card amounts on slips and bundle sales) so the Day-End Sales Report can break
|
||||
/// collections down by method. Mirrors <see cref="ExpensePaymentMethod"/>.</summary>
|
||||
public enum SalesPaymentMethod
|
||||
{
|
||||
Cash,
|
||||
Card,
|
||||
BankTransfer,
|
||||
Cheque
|
||||
}
|
||||
@@ -27,6 +27,18 @@ public sealed class StockAdjustmentCreatedNotificationModule;
|
||||
[NotificationModule("stock.transfer.created", "Stock Transfer Created", "Raised when a stock transfer is created.", 90)]
|
||||
public sealed class StockTransferCreatedNotificationModule;
|
||||
|
||||
[NotificationModule("stock.low", "Low Stock / Reorder Alert", "Raised when a sale, transfer or adjustment takes an item's stock at a warehouse to or below its reorder point.", 95)]
|
||||
public sealed class StockLowNotificationModule;
|
||||
|
||||
[NotificationModule("approval.pending", "Approval Needed", "Sent to the people who can approve a stock or price adjustment that is waiting for them.", 96)]
|
||||
public sealed class ApprovalPendingNotificationModule;
|
||||
|
||||
[NotificationModule("approval.approved", "Request Approved", "Sent to the requester when their stock or price adjustment is fully approved and applied.", 97)]
|
||||
public sealed class ApprovalApprovedNotificationModule;
|
||||
|
||||
[NotificationModule("approval.rejected", "Request Rejected", "Sent to the requester when their stock or price adjustment is rejected.", 98)]
|
||||
public sealed class ApprovalRejectedNotificationModule;
|
||||
|
||||
[NotificationModule("item.created", "Item Created", "Raised when an item master record is created.", 100)]
|
||||
public sealed class ItemCreatedNotificationModule;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user