Merge dev into feat-notification
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 12m21s
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 16m5s

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-10-20 17:19:51 +05:30
28 changed files with 7310 additions and 88 deletions
+29
View File
@@ -73,6 +73,7 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
public DbSet<SupplierPaymentGRN> SupplierPaymentGRNs { get; set; } public DbSet<SupplierPaymentGRN> SupplierPaymentGRNs { get; set; }
public DbSet<Notification> Notifications { get; set; } public DbSet<Notification> Notifications { get; set; }
public DbSet<NotificationRecipient> NotificationRecipients { get; set; } public DbSet<NotificationRecipient> NotificationRecipients { get; set; }
public DbSet<StoreCreditMovement> StoreCreditMovements { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
@@ -733,6 +734,34 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
.HasIndex(r => new { r.FK_NotificationId, r.FK_UserId }) .HasIndex(r => new { r.FK_NotificationId, r.FK_UserId })
.IsUnique(); .IsUnique();
// --- StoreCreditMovement ---
modelBuilder.Entity<StoreCreditMovement>()
.HasOne(m => m.Store)
.WithMany()
.HasForeignKey(m => m.FK_StoreId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<StoreCreditMovement>()
.HasOne(m => m.Invoice)
.WithMany()
.HasForeignKey(m => m.FK_InvoiceId)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(false);
modelBuilder.Entity<StoreCreditMovement>()
.HasOne(m => m.Payment)
.WithMany()
.HasForeignKey(m => m.FK_PaymentId)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(false);
modelBuilder.Entity<StoreCreditMovement>()
.Property(m => m.Amount).HasPrecision(18, 2);
modelBuilder.Entity<StoreCreditMovement>()
.HasIndex(m => new { m.FK_StoreId, m.OccurredAt });
Seed.RoleAndPermissionSeed.Apply(modelBuilder); Seed.RoleAndPermissionSeed.Apply(modelBuilder);
Seed.MasterDataSeed.Apply(modelBuilder); Seed.MasterDataSeed.Apply(modelBuilder);
Seed.OperationsDataSeed.Apply(modelBuilder); Seed.OperationsDataSeed.Apply(modelBuilder);
@@ -36,6 +36,22 @@ public class InvoiceController(InvoiceService service, ICurrentUserService curre
return result is null ? NotFound() : Ok(result); return result is null ? NotFound() : Ok(result);
} }
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateInvoiceRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
// (testbug.md #28) — fall back to the explicitly supplied user until that's fixed.
var userId = currentUser.UserId ?? request.CreatedByUserId;
if (userId is null) return BadRequest(new { error = "CreatedByUserId is required while auth is unavailable" });
try
{
var result = await service.CreateAsync(request, userId.Value, ct);
return CreatedAtAction(nameof(GetById), new { id = result.Id }, result);
}
catch (KeyNotFoundException) { return NotFound(); }
catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); }
}
[HttpPost("{id:guid}/print")] [HttpPost("{id:guid}/print")]
public async Task<IActionResult> Print(Guid id, [FromBody] PrintInvoiceRequest? request, CancellationToken ct) public async Task<IActionResult> Print(Guid id, [FromBody] PrintInvoiceRequest? request, CancellationToken ct)
{ {
+3 -1
View File
@@ -2,7 +2,7 @@
namespace Distribution.Features.Invoice; namespace Distribution.Features.Invoice;
public record CreateInvoiceRequest(Guid ShopPOId); public record CreateInvoiceRequest(Guid ShopPOId, Guid? CreatedByUserId = null);
public record InvoiceItemAdjustment(Guid ShopPOItemId, int AdjustedQuantity, string? Note = null); public record InvoiceItemAdjustment(Guid ShopPOItemId, int AdjustedQuantity, string? Note = null);
public record FinalizeInvoiceRequest(List<InvoiceItemAdjustment>? Adjustments = null, Guid? FinalizedByUserId = null); public record FinalizeInvoiceRequest(List<InvoiceItemAdjustment>? Adjustments = null, Guid? FinalizedByUserId = null);
public record PrintInvoiceRequest(Guid? PrintedByUserId = null); public record PrintInvoiceRequest(Guid? PrintedByUserId = null);
@@ -10,6 +10,7 @@ public record PrintInvoiceRequest(Guid? PrintedByUserId = null);
public record InvoiceResponse( public record InvoiceResponse(
Guid Id, Guid Id,
Guid ShopPOId, Guid ShopPOId,
Guid StoreId,
string StoreName, string StoreName,
InvoiceStatus Status, InvoiceStatus Status,
PaymentStatus PaymentStatus, PaymentStatus PaymentStatus,
@@ -19,6 +20,7 @@ public record InvoiceResponse(
DateTime? FinalizedAt, DateTime? FinalizedAt,
Guid? FinalizedBy, Guid? FinalizedBy,
decimal TotalAmount, decimal TotalAmount,
decimal PaidAmount,
bool IsActive, bool IsActive,
DateTime CreatedAt); DateTime CreatedAt);
@@ -21,6 +21,7 @@ public class InvoiceRepository(AppDBContext context) : IInvoiceRepository
public async Task<List<Models.Invoice>> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, PaymentStatus? paymentStatus, int page, int pageSize) => public async Task<List<Models.Invoice>> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, PaymentStatus? paymentStatus, int page, int pageSize) =>
await context.Invoices await context.Invoices
.Include(i => i.ShopPO).ThenInclude(p => p.Store) .Include(i => i.ShopPO).ThenInclude(p => p.Store)
.Include(i => i.Payments.Where(p => p.IsActive))
.Where(i => i.IsActive .Where(i => i.IsActive
&& (agentId == null || i.ShopPO.RaisedById == agentId) && (agentId == null || i.ShopPO.RaisedById == agentId)
&& (routeId == null || i.ShopPO.Store.FK_RouteId == routeId) && (routeId == null || i.ShopPO.Store.FK_RouteId == routeId)
@@ -1,4 +1,5 @@
using Distribution.Features.Stock; using Distribution.Features.ShopPO;
using Distribution.Features.Stock;
using Distribution.Infra.Authorization; using Distribution.Infra.Authorization;
using Distribution.Infra.UoW; using Distribution.Infra.UoW;
using Distribution.Models; using Distribution.Models;
@@ -7,16 +8,20 @@ namespace Distribution.Features.Invoice;
public class InvoiceService( public class InvoiceService(
IInvoiceRepository repo, IInvoiceRepository repo,
IShopPORepository shopPoRepo,
IUnitOfWork uow, IUnitOfWork uow,
ICurrentUserService currentUser) ICurrentUserService currentUser)
{ {
private static InvoiceResponse ToResponse(Models.Invoice i) => private static InvoiceResponse ToResponse(Models.Invoice i) =>
new(i.Id, i.FK_ShopPOId, new(i.Id, i.FK_ShopPOId,
i.ShopPO?.FK_StoreId ?? Guid.Empty,
i.ShopPO?.Store?.StoreName ?? string.Empty, i.ShopPO?.Store?.StoreName ?? string.Empty,
i.Status, i.PaymentStatus, i.CreatedBy, i.Status, i.PaymentStatus, i.CreatedBy,
i.PrintedAt, i.PrintedBy, i.PrintedAt, i.PrintedBy,
i.FinalizedAt, i.FinalizedBy, i.FinalizedAt, i.FinalizedBy,
i.TotalAmount, i.IsActive, i.CreatedAt); i.TotalAmount,
i.Payments?.Where(p => p.IsActive).Sum(p => p.Amount) ?? 0m,
i.IsActive, i.CreatedAt);
public async Task<InvoiceResponse?> GetByIdAsync(Guid id) public async Task<InvoiceResponse?> GetByIdAsync(Guid id)
{ {
@@ -39,6 +44,41 @@ public class InvoiceService(
return new OutstandingPaymentsResponse(count, outstanding); return new OutstandingPaymentsResponse(count, outstanding);
} }
public async Task<InvoiceResponse> CreateAsync(CreateInvoiceRequest request, Guid createdBy, CancellationToken ct = default)
{
var po = await shopPoRepo.GetByIdAsync(request.ShopPOId)
?? throw new KeyNotFoundException("Shop PO not found");
if (po.ConfirmedAt is null)
throw new InvalidOperationException("Shop PO must be confirmed before an invoice can be created");
if (po.Status == ShopPOStatus.Cancelled)
throw new InvalidOperationException("Cannot create an invoice for a cancelled Shop PO");
if (po.InvoiceId is not null)
throw new InvalidOperationException("An invoice already exists for this Shop PO");
var invoice = new Models.Invoice
{
FK_ShopPOId = po.Id,
Status = InvoiceStatus.Draft,
PaymentStatus = PaymentStatus.Pending,
CreatedBy = createdBy,
TotalAmount = po.TotalAmount
};
await uow.BeginAsync(ct);
try
{
await repo.AddAsync(invoice);
po.InvoiceId = invoice.Id;
shopPoRepo.Update(po);
await uow.CommitAsync(ct);
}
catch { await uow.RollbackAsync(ct); throw; }
var saved = await repo.GetByIdAsync(invoice.Id);
return ToResponse(saved!);
}
public async Task<InvoiceResponse> PrintAsync(Guid id, Guid printedBy, CancellationToken ct = default) public async Task<InvoiceResponse> PrintAsync(Guid id, Guid printedBy, CancellationToken ct = default)
{ {
var invoice = await repo.GetByIdAsync(id) var invoice = await repo.GetByIdAsync(id)
@@ -1,6 +1,7 @@
using Distribution.Features.BankAccount; using Distribution.Features.BankAccount;
using Distribution.Features.Invoice; using Distribution.Features.Invoice;
using Distribution.Features.ReceivedCheque; using Distribution.Features.ReceivedCheque;
using Distribution.Features.StoreCredit;
using Distribution.Infra.Authorization; using Distribution.Infra.Authorization;
using Distribution.Infra.UoW; using Distribution.Infra.UoW;
using Distribution.Models; using Distribution.Models;
@@ -12,6 +13,7 @@ public class PaymentService(
IInvoiceRepository invoiceRepo, IInvoiceRepository invoiceRepo,
IBankAccountRepository bankAccountRepo, IBankAccountRepository bankAccountRepo,
IReceivedChequeRepository receivedChequeRepo, IReceivedChequeRepository receivedChequeRepo,
IStoreCreditMovementRepository creditRepo,
IUnitOfWork uow, IUnitOfWork uow,
ICurrentUserService currentUser) ICurrentUserService currentUser)
{ {
@@ -34,12 +36,16 @@ public class PaymentService(
{ {
var invoice = await invoiceRepo.GetByIdAsync(invoiceId); var invoice = await invoiceRepo.GetByIdAsync(invoiceId);
if (invoice is null || !invoice.IsActive) return null; if (invoice is null || !invoice.IsActive) return null;
if (invoice.Status == InvoiceStatus.Finalized)
throw new InvalidOperationException("Cannot record a payment against a finalized invoice");
if (request.Amount <= 0) if (request.Amount <= 0)
throw new InvalidOperationException("Amount must be greater than zero"); throw new InvalidOperationException("Amount must be greater than zero");
var existingPaid = (await repo.GetByInvoiceIdAsync(invoiceId)).Sum(p => p.Amount);
var remaining = invoice.TotalAmount - existingPaid;
if (request.Amount > remaining)
throw new InvalidOperationException(
$"Amount exceeds the outstanding balance of {remaining:0.##}");
if (request.Method == PaymentMethod.Cheque && if (request.Method == PaymentMethod.Cheque &&
(string.IsNullOrWhiteSpace(request.ChequeNumber) || request.ChequeDate is null)) (string.IsNullOrWhiteSpace(request.ChequeNumber) || request.ChequeDate is null))
throw new InvalidOperationException("ChequeNumber and ChequeDate are required when Method is Cheque"); throw new InvalidOperationException("ChequeNumber and ChequeDate are required when Method is Cheque");
@@ -47,6 +53,19 @@ public class PaymentService(
if (request.Method == PaymentMethod.Cash && request.BankAccountId is null) if (request.Method == PaymentMethod.Cash && request.BankAccountId is null)
throw new InvalidOperationException("BankAccountId is required when Method is Cash"); throw new InvalidOperationException("BankAccountId is required when Method is Cash");
if (request.Method == PaymentMethod.Credit)
{
var store = invoice.ShopPO?.Store
?? throw new InvalidOperationException("Invoice is missing the owning store; cannot record a credit payment");
var currentOutstanding = await creditRepo.GetOutstandingForStoreAsync(store.Id);
if (currentOutstanding + request.Amount > store.CreditLimit)
{
var available = store.CreditLimit - currentOutstanding;
throw new InvalidOperationException(
$"Credit limit exceeded. Available credit: {available:0.##}");
}
}
Models.BankAccount? bankAccount = null; Models.BankAccount? bankAccount = null;
if (request.BankAccountId is not null) if (request.BankAccountId is not null)
{ {
@@ -107,9 +126,22 @@ public class PaymentService(
await repo.AddAsync(payment); await repo.AddAsync(payment);
var allPayments = await repo.GetByInvoiceIdAsync(invoiceId); if (request.Method == PaymentMethod.Credit)
var total = allPayments.Sum(p => p.Amount) + request.Amount; {
var movement = new StoreCreditMovement
{
FK_StoreId = invoice.ShopPO!.Store!.Id,
Direction = StoreCreditMovementDirection.Usage,
Amount = request.Amount,
FK_InvoiceId = invoice.Id,
FK_PaymentId = payment.Id,
OccurredAt = DateTime.Now,
RecordedBy = recorderId
};
await creditRepo.AddAsync(movement);
}
var total = existingPaid + request.Amount;
invoice.PaymentStatus = total == 0 invoice.PaymentStatus = total == 0
? PaymentStatus.Pending ? PaymentStatus.Pending
: total < invoice.TotalAmount : total < invoice.TotalAmount
@@ -30,6 +30,16 @@ public class ShopPOController(ShopPOService service, ICurrentUserService current
return result is null ? NotFound() : Ok(result); return result is null ? NotFound() : Ok(result);
} }
[HttpGet("confirmed-without-invoice")]
public async Task<IActionResult> GetConfirmedWithoutInvoice(
[FromQuery] Guid? agentId,
[FromQuery] Guid? routeId,
[FromQuery] Guid? shopId)
{
var result = await service.GetConfirmedWithoutInvoiceAsync(agentId, routeId, shopId);
return Ok(result);
}
[HttpPost] [HttpPost]
public async Task<IActionResult> Create(CreateShopPORequest request, CancellationToken ct) public async Task<IActionResult> Create(CreateShopPORequest request, CancellationToken ct)
{ {
@@ -65,6 +65,13 @@ public class ShopPOService(
return ToResponse(po, users); return ToResponse(po, users);
} }
public async Task<List<ShopPOResponse>> GetConfirmedWithoutInvoiceAsync(Guid? agentId, Guid? routeId, Guid? shopId)
{
var items = await repo.GetConfirmedWithoutInvoiceAsync(agentId, routeId, shopId);
var users = await repo.GetUserInfoAsync(items.SelectMany(UserIds));
return items.Select(p => ToResponse(p, users)).ToList();
}
public async Task<ShopPOResponse> CreateAsync(CreateShopPORequest request, Guid raisedById, CancellationToken ct = default) public async Task<ShopPOResponse> CreateAsync(CreateShopPORequest request, Guid raisedById, CancellationToken ct = default)
{ {
if (request.Items.Count == 0) if (request.Items.Count == 0)
+4 -2
View File
@@ -1,13 +1,14 @@
using Distribution.Features.Notifications; using Distribution.Features.Notifications;
using Distribution.Features.Scheme; using Distribution.Features.Scheme;
using Distribution.Features.Stock; using Distribution.Features.Stock;
using Distribution.Features.StoreCredit;
using Distribution.Infra.Authorization; using Distribution.Infra.Authorization;
using Distribution.Infra.UoW; using Distribution.Infra.UoW;
using Distribution.Models; using Distribution.Models;
namespace Distribution.Features.Store; namespace Distribution.Features.Store;
public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserService currentUser, IScopeAccessService scopeAccess, SchemeService schemeService, Route.IRouteRepository routeRepo, INotificationService notifications) public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserService currentUser, IScopeAccessService scopeAccess, SchemeService schemeService, Route.IRouteRepository routeRepo, INotificationService notifications, IStoreCreditMovementRepository creditRepo)
{ {
private const int GlobalScopeRoleLevel = 50; private const int GlobalScopeRoleLevel = 50;
private const int CreditApproverRoleLevel = 20; private const int CreditApproverRoleLevel = 20;
@@ -181,7 +182,8 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
var store = await repo.GetByIdAsync(id); var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null; if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null; if (!await HasStoreScopeAsync(id)) return null;
return new OutstandingBalanceResponse(store.Id, store.CreditLimit, store.OutstandingBalance, store.CreditLimit - store.OutstandingBalance); var outstanding = await creditRepo.GetOutstandingForStoreAsync(id);
return new OutstandingBalanceResponse(store.Id, store.CreditLimit, outstanding, store.CreditLimit - outstanding);
} }
public async Task<StoreResponse?> ClassifySegmentAsync(Guid id, ClassifySegmentRequest request, CancellationToken ct = default) public async Task<StoreResponse?> ClassifySegmentAsync(Guid id, ClassifySegmentRequest request, CancellationToken ct = default)
{ {
@@ -0,0 +1,11 @@
using Distribution.Models;
namespace Distribution.Features.StoreCredit;
public interface IStoreCreditMovementRepository
{
Task<decimal> GetOutstandingForStoreAsync(Guid storeId);
Task<List<StoreCreditMovement>> GetByStoreAsync(Guid storeId, int page, int pageSize);
Task<int> GetCountByStoreAsync(Guid storeId);
Task AddAsync(StoreCreditMovement movement);
}
@@ -0,0 +1,36 @@
using Distribution.Data;
using Distribution.Models;
using Microsoft.EntityFrameworkCore;
namespace Distribution.Features.StoreCredit;
public class StoreCreditMovementRepository(AppDBContext context) : IStoreCreditMovementRepository
{
public async Task<decimal> GetOutstandingForStoreAsync(Guid storeId)
{
var usage = await context.StoreCreditMovements
.Where(m => m.IsActive && m.FK_StoreId == storeId && m.Direction == StoreCreditMovementDirection.Usage)
.SumAsync(m => (decimal?)m.Amount) ?? 0m;
var settlements = await context.StoreCreditMovements
.Where(m => m.IsActive && m.FK_StoreId == storeId && m.Direction == StoreCreditMovementDirection.Settlement)
.SumAsync(m => (decimal?)m.Amount) ?? 0m;
return usage - settlements;
}
public async Task<List<StoreCreditMovement>> GetByStoreAsync(Guid storeId, int page, int pageSize) =>
await context.StoreCreditMovements
.Where(m => m.IsActive && m.FK_StoreId == storeId)
.OrderByDescending(m => m.OccurredAt)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
public async Task<int> GetCountByStoreAsync(Guid storeId) =>
await context.StoreCreditMovements
.CountAsync(m => m.IsActive && m.FK_StoreId == storeId);
public async Task AddAsync(StoreCreditMovement movement) =>
await context.StoreCreditMovements.AddAsync(movement);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,778 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class credittable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "StoreCreditMovements",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
FK_StoreId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Direction = table.Column<int>(type: "int", nullable: false),
Amount = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
FK_InvoiceId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
FK_PaymentId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
OccurredAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
RecordedBy = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
Notes = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_StoreCreditMovements", x => x.Id);
table.ForeignKey(
name: "FK_StoreCreditMovements_Invoices_FK_InvoiceId",
column: x => x.FK_InvoiceId,
principalTable: "Invoices",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_StoreCreditMovements_Payments_FK_PaymentId",
column: x => x.FK_PaymentId,
principalTable: "Payments",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_StoreCreditMovements_Stores_FK_StoreId",
column: x => x.FK_StoreId,
principalTable: "Stores",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("be712eda-98a5-4a30-820a-1737e84d1e4b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("47ea9420-d6a0-4376-a2b8-211639d95b27"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("369eed1f-df4c-4131-a3c6-ebbe63d2dc91"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("14b6944f-2d4a-4378-a974-c6fc0f9dfb81"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("14a01e0b-7be5-4c65-ae6a-899f9aa7ad28"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5d486ccd-3866-4e7d-8ef1-fb177fb637c1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d830e59b-f451-4bde-9a77-78daea5f9a61"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("096d3837-a649-4184-8987-2ea0dfa2d4a1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5e43bbde-689b-4d07-baf9-0764078b5586"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f317d30c-1644-44f0-b0aa-6bcf1fa66f44"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("31ffac6f-2aa8-48ee-bc87-213f35933de4"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fb525bc4-9f16-455a-bfd5-ca6f3e7ad141"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2388918f-6392-4384-b269-0a1469f5bf4c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7159012e-5f25-4881-b5e8-5300e382332e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cc4b2e82-ad42-4440-92ba-9b2100bb5f84"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6b15c133-ea0e-473d-b58a-7f140e9f03bf"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c2dd52a9-380f-479f-8e5e-6b56bfc4738f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bf5f6c7a-2fde-4a01-83f4-aacf91333c4c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("162a0346-c4c0-4c4e-96e9-aa8154d25b39"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5cc76807-25d1-45e5-9da3-cfd6d6f3ad7c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("51a2653e-4b1a-4f6f-80c2-f533b26109ea"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e2a382e2-d712-4a97-a7ec-cd6232d77a78"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b60260b5-70b0-4f9e-9ab9-ba4abbbdfb02"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a73fe794-383c-4157-89cf-227c4e487a6d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a9743e96-15b2-4c1d-b410-698cd6db0b7b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a94d92ab-66d8-4dd9-8ba3-c242eb450e68"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("9cb1a028-a98e-492a-aafc-70456fe46c96"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5bc99a62-f5d7-48fe-b25c-518e4774614c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("eceee678-5cee-4ee9-b16d-8d8d21fbb5ea"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3a049ed7-75b7-4b1d-b3bb-402ca77c350f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("aeaab85c-5b02-4bc2-b0e3-318c0f5b07d3"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b79800e0-baa6-4add-9374-7d1e2ed650e8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0da6bf0b-26ff-46b9-bb8c-f9c641b37a89"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ff84aeeb-93c0-465d-9a4a-8b686ba7bc75"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("921f8073-7a66-49bb-ae23-cf8fcde12c9c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bff05501-4988-4c8a-b61d-e32389e795a8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2c4f7432-e697-4d65-97df-069f8913a662"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("18d27746-3178-4c57-afd5-b75f0061637f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a5d1978b-c497-4314-857b-a7e3b8323a53"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("88300763-b8c3-4bd2-803b-df0e43bc691e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7aaad5a9-4497-429f-b3dc-9b59664e2e19"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2db130c1-4b6f-4719-b3bb-7bd8a0662d75"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("be349d14-38b5-4a13-a152-9ea055de26b1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5292e02d-9a7d-4a18-be14-86c2f3351cac"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("97021474-1218-4d21-9115-4b9b2726e38b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("56f68355-7b1b-49e4-829c-1a4d47fc93de"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3017c8cb-f9e4-41c8-ac2e-f03d23fe944a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("619a08e5-f6cb-4515-8b4d-a094d19277d8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cb8b4e96-7026-4485-8b52-3145b5289350"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f0f57dfd-21a5-4a0b-a77e-e641f00300fa"));
migrationBuilder.CreateIndex(
name: "IX_StoreCreditMovements_FK_InvoiceId",
table: "StoreCreditMovements",
column: "FK_InvoiceId");
migrationBuilder.CreateIndex(
name: "IX_StoreCreditMovements_FK_PaymentId",
table: "StoreCreditMovements",
column: "FK_PaymentId");
migrationBuilder.CreateIndex(
name: "IX_StoreCreditMovements_FK_StoreId_OccurredAt",
table: "StoreCreditMovements",
columns: new[] { "FK_StoreId", "OccurredAt" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "StoreCreditMovements");
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("30f658ac-2c92-4cd8-ad47-10b0def2699c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("42ab2c52-eaf8-4a17-b67a-ccd66569e56a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8afec825-27b3-4153-ad06-f8bcdbf93da8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4b427620-e99d-4068-a416-c3788d5bd9b5"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("361f44ef-1cd1-48a9-be4d-4c068aacef1e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("11fc03ae-92ee-4336-ae57-29aac731ad51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0b1f2b73-ef60-4634-864f-22a6c0cd1373"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2380abf3-2bcd-4a9f-b447-5f1685df2fc8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("240e4d6a-8306-40ba-aaec-8e05cd0347db"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cfde0aa6-e859-4f9c-8291-b0d886fcd4c9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("dae772c8-26ec-4b5c-8d7a-f3196510bf2c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3512c0a4-a5ae-4002-a779-7d3cc600ab61"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f9e2a348-159e-47a2-b7be-a60f0254873f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c8b4c181-5b08-45d2-818b-74bceeab78a8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8fb4ff4c-c5bd-4afd-a08e-02861d63cb7b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("edb3b711-d623-439d-811e-afaef8d0680d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f33e4c62-d69f-4a91-8b62-acbd5351ea2a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c7c9d16c-e343-43e9-9e27-f38f903a5d00"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f5f4760a-8a45-46ca-8093-743c95b0313f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c5434801-146a-4fd9-9c29-a1145e7f7f00"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6c085135-78a5-4e65-a380-ee090b07e2bb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bbde2785-a3df-4f81-bad1-0bc5afe5de57"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4421a0fb-bdd4-45a9-8dc0-d9b70f775e97"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("dba9dcb4-3b94-4ddc-89f3-552cfc109478"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d8f74160-c150-4d9c-aba6-e45e628c684e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("495fb68b-9f01-4538-9561-fefce0d39558"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3bdece9b-a798-4223-a23c-9c9dd10d042d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6fa616eb-99fe-46b9-8305-908765d037fd"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7a07148a-1327-4e97-befc-b2045eacad21"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("852e86d7-aa57-4a77-81c0-054f3fb4d7f7"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3b767929-c973-41fb-a340-4ee5feb65619"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("63619bbd-0352-41bd-9e1c-a3f7908fb5d2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f6b4c8bf-a9b3-4179-9f57-a8584678c0d1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bb47b8ca-f7cf-40fe-8945-fc532a439b53"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("52126271-ae3b-4b58-a9d2-50e2dd894087"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("981e3358-85bb-47fe-a1f5-3a3a02cf47b1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("749408da-fcee-458d-9144-8d8dee928ba0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c157857c-fb0e-41fd-a414-c0f57a44b120"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3217cdbc-76c9-4505-b9f3-23de91a6212b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("63526c52-18ba-40e0-9889-3bd3b7fc8161"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("260cf2fa-1ca6-4cd5-92ae-8c479a80e2f0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("130ab09c-8a36-4705-8235-9d00f75dd684"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("41794774-e919-4f4e-a42a-5ae408d3407f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2ff23d04-d1f6-4aa3-a48e-1c82bb9ad12a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d36c81c0-8e9b-41ea-8e09-464a327a16d2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6c51dfc1-63e0-46a6-b2bb-27c21c708b51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("076333d5-b1f3-4b89-86fd-5a61a4451c88"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7e834f3e-1424-4aaa-816e-d62da6df672b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("699fa06b-a7ff-4dbd-98a7-a29c2c361665"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("00df5735-54c6-4cdf-8e2c-a64cd90ede15"));
}
}
}
@@ -1,4 +1,4 @@
// <auto-generated /> // <auto-generated />
using System; using System;
using Distribution.Data; using Distribution.Data;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@@ -67,7 +67,7 @@ namespace Distribution.Migrations
b.HasIndex("AccountType", "AccountName") b.HasIndex("AccountType", "AccountName")
.IsUnique(); .IsUnique();
b.ToTable("BankAccounts"); b.ToTable("BankAccounts", (string)null);
b.HasData( b.HasData(
new new
@@ -104,7 +104,7 @@ namespace Distribution.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Brands"); b.ToTable("Brands", (string)null);
b.HasData( b.HasData(
new new
@@ -147,7 +147,7 @@ namespace Distribution.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Categories"); b.ToTable("Categories", (string)null);
b.HasData( b.HasData(
new new
@@ -223,7 +223,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_BankAccountId"); b.HasIndex("FK_BankAccountId");
b.ToTable("ChequeBooks"); b.ToTable("ChequeBooks", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.ChequePage", b => modelBuilder.Entity("Distribution.Models.ChequePage", b =>
@@ -311,7 +311,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ChequeBookId"); b.HasIndex("FK_ChequeBookId");
b.ToTable("ChequePages"); b.ToTable("ChequePages", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.Claim", b => modelBuilder.Entity("Distribution.Models.Claim", b =>
@@ -351,7 +351,7 @@ namespace Distribution.Migrations
b.HasIndex("SettledByUserId"); b.HasIndex("SettledByUserId");
b.ToTable("Claims"); b.ToTable("Claims", (string)null);
b.HasData( b.HasData(
new new
@@ -393,7 +393,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_SaleReturnId"); b.HasIndex("FK_SaleReturnId");
b.ToTable("CreditNotes"); b.ToTable("CreditNotes", (string)null);
b.HasData( b.HasData(
new new
@@ -452,7 +452,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_VehicleId"); b.HasIndex("FK_VehicleId");
b.ToTable("DeliveryRuns"); b.ToTable("DeliveryRuns", (string)null);
b.HasData( b.HasData(
new new
@@ -521,7 +521,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ShopPOId"); b.HasIndex("FK_ShopPOId");
b.ToTable("DeliveryTasks"); b.ToTable("DeliveryTasks", (string)null);
b.HasData( b.HasData(
new new
@@ -557,7 +557,7 @@ namespace Distribution.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("DriverComplianceConfigs"); b.ToTable("DriverComplianceConfigs", (string)null);
b.HasData( b.HasData(
new new
@@ -600,7 +600,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_UserId") b.HasIndex("FK_UserId")
.IsUnique(); .IsUnique();
b.ToTable("DriverProfiles"); b.ToTable("DriverProfiles", (string)null);
b.HasData( b.HasData(
new new
@@ -672,7 +672,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_WarehouseId"); b.HasIndex("FK_WarehouseId");
b.ToTable("GoodsReceipts"); b.ToTable("GoodsReceipts", (string)null);
b.HasData( b.HasData(
new new
@@ -744,7 +744,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_PurchaseOrderItemId"); b.HasIndex("FK_PurchaseOrderItemId");
b.ToTable("GoodsReceiptItems"); b.ToTable("GoodsReceiptItems", (string)null);
b.HasData( b.HasData(
new new
@@ -806,7 +806,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ItemBatchId"); b.HasIndex("FK_ItemBatchId");
b.ToTable("GoodsReceiptItemBatches"); b.ToTable("GoodsReceiptItemBatches", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.GoodsReceiptItemSerial", b => modelBuilder.Entity("Distribution.Models.GoodsReceiptItemSerial", b =>
@@ -833,7 +833,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ItemSerialNumberId"); b.HasIndex("FK_ItemSerialNumberId");
b.ToTable("GoodsReceiptItemSerials"); b.ToTable("GoodsReceiptItemSerials", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.Invoice", b => modelBuilder.Entity("Distribution.Models.Invoice", b =>
@@ -879,7 +879,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ShopPOId"); b.HasIndex("FK_ShopPOId");
b.ToTable("Invoices"); b.ToTable("Invoices", (string)null);
b.HasData( b.HasData(
new new
@@ -993,7 +993,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_SubCategoryId"); b.HasIndex("FK_SubCategoryId");
b.ToTable("Items"); b.ToTable("Items", (string)null);
b.HasData( b.HasData(
new new
@@ -1102,7 +1102,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ItemId", "BatchNumber"); b.HasIndex("FK_ItemId", "BatchNumber");
b.ToTable("ItemBatches"); b.ToTable("ItemBatches", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.ItemSerialNumber", b => modelBuilder.Entity("Distribution.Models.ItemSerialNumber", b =>
@@ -1147,7 +1147,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ItemId", "SerialNumber") b.HasIndex("FK_ItemId", "SerialNumber")
.IsUnique(); .IsUnique();
b.ToTable("ItemSerialNumbers"); b.ToTable("ItemSerialNumbers", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.LoadingSheet", b => modelBuilder.Entity("Distribution.Models.LoadingSheet", b =>
@@ -1184,7 +1184,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RideId"); b.HasIndex("FK_RideId");
b.ToTable("LoadingSheets"); b.ToTable("LoadingSheets", (string)null);
b.HasData( b.HasData(
new new
@@ -1238,7 +1238,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_WarehouseId"); b.HasIndex("FK_WarehouseId");
b.ToTable("LoadingSheetItems"); b.ToTable("LoadingSheetItems", (string)null);
b.HasData( b.HasData(
new new
@@ -1275,7 +1275,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ShopPOId"); b.HasIndex("FK_ShopPOId");
b.ToTable("LoadingSheetOrders"); b.ToTable("LoadingSheetOrders", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.Notification", b => modelBuilder.Entity("Distribution.Models.Notification", b =>
@@ -1418,7 +1418,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ReceivedChequeId"); b.HasIndex("FK_ReceivedChequeId");
b.ToTable("Payments"); b.ToTable("Payments", (string)null);
b.HasData( b.HasData(
new new
@@ -1496,7 +1496,7 @@ namespace Distribution.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Permissions"); b.ToTable("Permissions", (string)null);
b.HasData( b.HasData(
new new
@@ -1930,7 +1930,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RegionId"); b.HasIndex("FK_RegionId");
b.ToTable("PriceLists"); b.ToTable("PriceLists", (string)null);
b.HasData( b.HasData(
new new
@@ -1982,7 +1982,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_PriceListId", "FK_ItemId") b.HasIndex("FK_PriceListId", "FK_ItemId")
.IsUnique(); .IsUnique();
b.ToTable("PriceListItems"); b.ToTable("PriceListItems", (string)null);
b.HasData( b.HasData(
new new
@@ -2035,7 +2035,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_SupplierId"); b.HasIndex("FK_SupplierId");
b.ToTable("PurchaseOrders"); b.ToTable("PurchaseOrders", (string)null);
b.HasData( b.HasData(
new new
@@ -2097,7 +2097,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_PurchaseOrderId"); b.HasIndex("FK_PurchaseOrderId");
b.ToTable("PurchaseOrderItems"); b.ToTable("PurchaseOrderItems", (string)null);
b.HasData( b.HasData(
new new
@@ -2164,7 +2164,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_PurchaseOrderId"); b.HasIndex("FK_PurchaseOrderId");
b.ToTable("PurchaseReturns"); b.ToTable("PurchaseReturns", (string)null);
b.HasData( b.HasData(
new new
@@ -2204,7 +2204,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_PurchaseReturnId"); b.HasIndex("FK_PurchaseReturnId");
b.ToTable("PurchaseReturnItems"); b.ToTable("PurchaseReturnItems", (string)null);
b.HasData( b.HasData(
new new
@@ -2297,7 +2297,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_DepositBankAccountId"); b.HasIndex("FK_DepositBankAccountId");
b.ToTable("ReceivedCheques"); b.ToTable("ReceivedCheques", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.Region", b => modelBuilder.Entity("Distribution.Models.Region", b =>
@@ -2326,7 +2326,7 @@ namespace Distribution.Migrations
b.HasIndex("Code") b.HasIndex("Code")
.IsUnique(); .IsUnique();
b.ToTable("Regions"); b.ToTable("Regions", (string)null);
b.HasData( b.HasData(
new new
@@ -2372,7 +2372,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RegionId", "FK_AgencyUserId") b.HasIndex("FK_RegionId", "FK_AgencyUserId")
.IsUnique(); .IsUnique();
b.ToTable("RegionAgencyMaps"); b.ToTable("RegionAgencyMaps", (string)null);
b.HasData( b.HasData(
new new
@@ -2412,7 +2412,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RegionId", "Period") b.HasIndex("FK_RegionId", "Period")
.IsUnique(); .IsUnique();
b.ToTable("RegionalBudgets"); b.ToTable("RegionalBudgets", (string)null);
b.HasData( b.HasData(
new new
@@ -2453,7 +2453,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RegionId", "Period") b.HasIndex("FK_RegionId", "Period")
.IsUnique(); .IsUnique();
b.ToTable("RegionalTargets"); b.ToTable("RegionalTargets", (string)null);
b.HasData( b.HasData(
new new
@@ -2491,7 +2491,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RegionId") b.HasIndex("FK_RegionId")
.IsUnique(); .IsUnique();
b.ToTable("RegionalTaxRules"); b.ToTable("RegionalTaxRules", (string)null);
b.HasData( b.HasData(
new new
@@ -2525,7 +2525,7 @@ namespace Distribution.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Roles"); b.ToTable("Roles", (string)null);
b.HasData( b.HasData(
new new
@@ -2607,7 +2607,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_PermissionId"); b.HasIndex("FK_PermissionId");
b.ToTable("RolePermissions"); b.ToTable("RolePermissions", (string)null);
b.HasData( b.HasData(
new new
@@ -3049,7 +3049,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RegionId"); b.HasIndex("FK_RegionId");
b.ToTable("Routes"); b.ToTable("Routes", (string)null);
b.HasData( b.HasData(
new new
@@ -3146,7 +3146,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_UserId"); b.HasIndex("FK_UserId");
b.ToTable("RouteVisitLogs"); b.ToTable("RouteVisitLogs", (string)null);
b.HasData( b.HasData(
new new
@@ -3208,7 +3208,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ShopPOId"); b.HasIndex("FK_ShopPOId");
b.ToTable("SaleReturns"); b.ToTable("SaleReturns", (string)null);
b.HasData( b.HasData(
new new
@@ -3256,7 +3256,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_SaleReturnId"); b.HasIndex("FK_SaleReturnId");
b.ToTable("SaleReturnItems"); b.ToTable("SaleReturnItems", (string)null);
b.HasData( b.HasData(
new new
@@ -3286,7 +3286,7 @@ namespace Distribution.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("SaleRoutes"); b.ToTable("SaleRoutes", (string)null);
b.HasData( b.HasData(
new new
@@ -3366,7 +3366,7 @@ namespace Distribution.Migrations
b.HasIndex("RegionId"); b.HasIndex("RegionId");
b.ToTable("Schemes"); b.ToTable("Schemes", (string)null);
b.HasData( b.HasData(
new new
@@ -3424,7 +3424,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_SchemeId", "FK_ItemId") b.HasIndex("FK_SchemeId", "FK_ItemId")
.IsUnique(); .IsUnique();
b.ToTable("SchemeBundleComponents"); b.ToTable("SchemeBundleComponents", (string)null);
b.HasData( b.HasData(
new new
@@ -3474,7 +3474,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ShopPOId"); b.HasIndex("FK_ShopPOId");
b.ToTable("SchemeRedemptions"); b.ToTable("SchemeRedemptions", (string)null);
b.HasData( b.HasData(
new new
@@ -3540,7 +3540,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_StoreId"); b.HasIndex("FK_StoreId");
b.ToTable("ShopPOs"); b.ToTable("ShopPOs", (string)null);
b.HasData( b.HasData(
new new
@@ -3616,7 +3616,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ShopPOId"); b.HasIndex("FK_ShopPOId");
b.ToTable("ShopPOItems"); b.ToTable("ShopPOItems", (string)null);
b.HasData( b.HasData(
new new
@@ -3701,7 +3701,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ItemId", "LocationId", "FK_ItemBatchId", "FK_ItemSerialNumberId") b.HasIndex("FK_ItemId", "LocationId", "FK_ItemBatchId", "FK_ItemSerialNumberId")
.IsUnique(); .IsUnique();
b.ToTable("StockBalances"); b.ToTable("StockBalances", (string)null);
b.HasData( b.HasData(
new new
@@ -3786,7 +3786,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ItemSerialNumberId"); b.HasIndex("FK_ItemSerialNumberId");
b.ToTable("StockMovements"); b.ToTable("StockMovements", (string)null);
b.HasData( b.HasData(
new new
@@ -3887,7 +3887,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RouteId"); b.HasIndex("FK_RouteId");
b.ToTable("Stores"); b.ToTable("Stores", (string)null);
b.HasData( b.HasData(
new new
@@ -3992,6 +3992,54 @@ namespace Distribution.Migrations
}); });
}); });
modelBuilder.Entity("Distribution.Models.StoreCreditMovement", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("Direction")
.HasColumnType("int");
b.Property<Guid?>("FK_InvoiceId")
.HasColumnType("char(36)");
b.Property<Guid?>("FK_PaymentId")
.HasColumnType("char(36)");
b.Property<Guid>("FK_StoreId")
.HasColumnType("char(36)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<string>("Notes")
.HasColumnType("longtext");
b.Property<DateTime>("OccurredAt")
.HasColumnType("datetime(6)");
b.Property<Guid?>("RecordedBy")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("FK_InvoiceId");
b.HasIndex("FK_PaymentId");
b.HasIndex("FK_StoreId", "OccurredAt");
b.ToTable("StoreCreditMovements", (string)null);
});
modelBuilder.Entity("Distribution.Models.SubCategory", b => modelBuilder.Entity("Distribution.Models.SubCategory", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@@ -4018,7 +4066,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_CategoryId"); b.HasIndex("FK_CategoryId");
b.ToTable("SubCategories"); b.ToTable("SubCategories", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.Supplier", b => modelBuilder.Entity("Distribution.Models.Supplier", b =>
@@ -4045,7 +4093,7 @@ namespace Distribution.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Suppliers"); b.ToTable("Suppliers", (string)null);
b.HasData( b.HasData(
new new
@@ -4123,7 +4171,7 @@ namespace Distribution.Migrations
b.HasIndex("ResolvedByUserId"); b.HasIndex("ResolvedByUserId");
b.ToTable("SupplierClaims"); b.ToTable("SupplierClaims", (string)null);
b.HasData( b.HasData(
new new
@@ -4174,7 +4222,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_SupplierClaimId"); b.HasIndex("FK_SupplierClaimId");
b.ToTable("SupplierClaimItems"); b.ToTable("SupplierClaimItems", (string)null);
b.HasData( b.HasData(
new new
@@ -4234,7 +4282,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_SupplierId"); b.HasIndex("FK_SupplierId");
b.ToTable("SupplierPayments"); b.ToTable("SupplierPayments", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.SupplierPaymentGRN", b => modelBuilder.Entity("Distribution.Models.SupplierPaymentGRN", b =>
@@ -4265,7 +4313,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_SupplierPaymentId"); b.HasIndex("FK_SupplierPaymentId");
b.ToTable("SupplierPaymentGRNs"); b.ToTable("SupplierPaymentGRNs", (string)null);
}); });
modelBuilder.Entity("Distribution.Models.SysConfig", b => modelBuilder.Entity("Distribution.Models.SysConfig", b =>
@@ -4286,7 +4334,7 @@ namespace Distribution.Migrations
b.HasKey("Key"); b.HasKey("Key");
b.ToTable("SysConfigs"); b.ToTable("SysConfigs", (string)null);
b.HasData( b.HasData(
new new
@@ -4354,7 +4402,7 @@ namespace Distribution.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Uoms"); b.ToTable("Uoms", (string)null);
b.HasData( b.HasData(
new new
@@ -4399,7 +4447,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_ToUomId"); b.HasIndex("FK_ToUomId");
b.ToTable("UomConversions"); b.ToTable("UomConversions", (string)null);
b.HasData( b.HasData(
new new
@@ -4447,7 +4495,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RoleId"); b.HasIndex("FK_RoleId");
b.ToTable("Users"); b.ToTable("Users", (string)null);
b.HasData( b.HasData(
new new
@@ -4549,7 +4597,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RegionId"); b.HasIndex("FK_RegionId");
b.ToTable("UserRegionScopes"); b.ToTable("UserRegionScopes", (string)null);
b.HasData( b.HasData(
new new
@@ -4583,7 +4631,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_RouteId"); b.HasIndex("FK_RouteId");
b.ToTable("UserRouteScopes"); b.ToTable("UserRouteScopes", (string)null);
b.HasData( b.HasData(
new new
@@ -4617,7 +4665,7 @@ namespace Distribution.Migrations
b.HasIndex("FK_StoreId"); b.HasIndex("FK_StoreId");
b.ToTable("UserStoreScopes"); b.ToTable("UserStoreScopes", (string)null);
b.HasData( b.HasData(
new new
@@ -4660,7 +4708,7 @@ namespace Distribution.Migrations
b.HasIndex("DefaultWarehouseId"); b.HasIndex("DefaultWarehouseId");
b.ToTable("Vehicles"); b.ToTable("Vehicles", (string)null);
b.HasData( b.HasData(
new new
@@ -4715,7 +4763,7 @@ namespace Distribution.Migrations
b.HasIndex("VehicleId"); b.HasIndex("VehicleId");
b.ToTable("Warehouses"); b.ToTable("Warehouses", (string)null);
b.HasData( b.HasData(
new new
@@ -5505,6 +5553,31 @@ namespace Distribution.Migrations
b.Navigation("Route"); b.Navigation("Route");
}); });
modelBuilder.Entity("Distribution.Models.StoreCreditMovement", b =>
{
b.HasOne("Distribution.Models.Invoice", "Invoice")
.WithMany()
.HasForeignKey("FK_InvoiceId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("Distribution.Models.Payment", "Payment")
.WithMany()
.HasForeignKey("FK_PaymentId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("Distribution.Models.Store", "Store")
.WithMany()
.HasForeignKey("FK_StoreId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Invoice");
b.Navigation("Payment");
b.Navigation("Store");
});
modelBuilder.Entity("Distribution.Models.SubCategory", b => modelBuilder.Entity("Distribution.Models.SubCategory", b =>
{ {
b.HasOne("Distribution.Models.Category", "Category") b.HasOne("Distribution.Models.Category", "Category")
+2
View File
@@ -23,6 +23,8 @@ namespace Distribution.Models
public enum PaymentMethod { Cash, Cheque, Credit } public enum PaymentMethod { Cash, Cheque, Credit }
public enum StoreCreditMovementDirection { Usage, Settlement }
public enum EntryMode { RealTime, DayEndManual } public enum EntryMode { RealTime, DayEndManual }
public enum DeliveryTaskStatus { Pending, Delivered, PartiallyDelivered, Failed } public enum DeliveryTaskStatus { Pending, Delivered, PartiallyDelivered, Failed }
@@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Distribution.Models
{
public class StoreCreditMovement : Template
{
public Guid FK_StoreId { get; set; }
[ForeignKey("FK_StoreId")]
public Store? Store { get; set; }
public StoreCreditMovementDirection Direction { get; set; }
public decimal Amount { get; set; }
public Guid? FK_InvoiceId { get; set; }
[ForeignKey("FK_InvoiceId")]
public Invoice? Invoice { get; set; }
public Guid? FK_PaymentId { get; set; }
[ForeignKey("FK_PaymentId")]
public Payment? Payment { get; set; }
public DateTime OccurredAt { get; set; } = DateTime.Now;
public Guid? RecordedBy { get; set; }
public string? Notes { get; set; }
}
}
+1
View File
@@ -101,6 +101,7 @@ builder.Services.AddScoped<IBankAccountRepository, BankAccountRepository>();
builder.Services.AddScoped<IChequeBookRepository, ChequeBookRepository>(); builder.Services.AddScoped<IChequeBookRepository, ChequeBookRepository>();
builder.Services.AddScoped<IReceivedChequeRepository, ReceivedChequeRepository>(); builder.Services.AddScoped<IReceivedChequeRepository, ReceivedChequeRepository>();
builder.Services.AddScoped<ISupplierPaymentRepository, SupplierPaymentRepository>(); builder.Services.AddScoped<ISupplierPaymentRepository, SupplierPaymentRepository>();
builder.Services.AddScoped<Distribution.Features.StoreCredit.IStoreCreditMovementRepository, Distribution.Features.StoreCredit.StoreCreditMovementRepository>();
builder.Services.AddScoped<RegionService>(); builder.Services.AddScoped<RegionService>();
builder.Services.AddScoped<RouteService>(); builder.Services.AddScoped<RouteService>();
@@ -0,0 +1,84 @@
'use client'
import { useEffect, useState } from 'react'
import { HugeiconsIcon } from '@hugeicons/react'
import { ReceiptDollarIcon } from '@hugeicons/core-free-icons'
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
import { FieldDescription } from '@/components/ui/field'
import { toast } from '@/components/ui/toast'
import {
invoiceCreationMode as invoiceCreationModeApi,
DEFAULT_INVOICE_CREATION_MODE,
getApiError,
} from '@/lib/api/index'
import type { InvoiceCreationMode } from '@/lib/api/sys-config'
const MODE_LABELS: Record<InvoiceCreationMode, string> = {
ModeA: 'Auto on confirm',
ModeB: 'Separate step',
}
const MODE_HINTS: Record<InvoiceCreationMode, string> = {
ModeA: 'Confirming a Shop PO immediately creates a draft invoice.',
ModeB: 'Confirmation and invoice creation are two distinct actions.',
}
export function InvoiceCreationModeCard() {
const [loading, setLoading] = useState(true)
const [mode, setMode] = useState<InvoiceCreationMode>(DEFAULT_INVOICE_CREATION_MODE)
const [pending, setPending] = useState(false)
useEffect(() => {
invoiceCreationModeApi.get()
.then(setMode)
.catch(err => toast.add({ title: 'Failed to load invoice creation mode', description: getApiError(err), type: 'error' }))
.finally(() => setLoading(false))
}, [])
async function save(next: InvoiceCreationMode) {
if (next === mode) return
const previous = mode
setMode(next)
setPending(true)
try {
await invoiceCreationModeApi.set(next)
} catch (err) {
setMode(previous)
toast.add({ title: 'Failed to update invoice creation mode', description: getApiError(err), type: 'error' })
} finally {
setPending(false)
}
}
if (loading) return <p className="text-sm text-muted-foreground">Loading...</p>
return (
<Card className="h-full gap-3 rounded-3xl border-border/60 py-4">
<CardHeader className="border-b border-border/60 pb-3">
<div className="flex items-center gap-2.5">
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground">
<HugeiconsIcon icon={ReceiptDollarIcon} size={16} />
</div>
<div>
<CardTitle className="text-base">Invoice Creation</CardTitle>
<CardDescription className="text-xs">When invoices are created for a Shop PO</CardDescription>
</div>
</div>
</CardHeader>
<CardContent className="flex flex-col gap-2.5">
<ToggleGroup
variant="outline"
value={[mode]}
onValueChange={(v: string[]) => v[0] && save(v[0] as InvoiceCreationMode)}
disabled={pending}
className="w-full"
>
<ToggleGroupItem value="ModeA" className="flex-1">{MODE_LABELS.ModeA}</ToggleGroupItem>
<ToggleGroupItem value="ModeB" className="flex-1">{MODE_LABELS.ModeB}</ToggleGroupItem>
</ToggleGroup>
<FieldDescription className="text-xs leading-relaxed">{MODE_HINTS[mode]}</FieldDescription>
</CardContent>
</Card>
)
}
@@ -2,6 +2,7 @@
import { ProductCapabilitiesCard } from './_components/product-capabilities-card' import { ProductCapabilitiesCard } from './_components/product-capabilities-card'
import { GrnTaxCard } from './_components/grn-tax-card' import { GrnTaxCard } from './_components/grn-tax-card'
import { InvoiceCreationModeCard } from './_components/invoice-creation-mode-card'
export default function ConfigurationPage() { export default function ConfigurationPage() {
return ( return (
@@ -11,7 +12,6 @@ export default function ConfigurationPage() {
<p className="text-sm text-muted-foreground mt-0.5">System-wide settings, grouped by area</p> <p className="text-sm text-muted-foreground mt-0.5">System-wide settings, grouped by area</p>
</div> </div>
{/* 12-column grid: each card takes 6 columns so the two sit side by side; they stack on narrow screens. */}
<div className="grid grid-cols-12 items-stretch gap-6"> <div className="grid grid-cols-12 items-stretch gap-6">
<div className="col-span-12 flex lg:col-span-6 [&>*]:w-full"> <div className="col-span-12 flex lg:col-span-6 [&>*]:w-full">
<ProductCapabilitiesCard /> <ProductCapabilitiesCard />
@@ -19,6 +19,9 @@ export default function ConfigurationPage() {
<div className="col-span-12 flex lg:col-span-6 [&>*]:w-full"> <div className="col-span-12 flex lg:col-span-6 [&>*]:w-full">
<GrnTaxCard /> <GrnTaxCard />
</div> </div>
<div className="col-span-12 flex lg:col-span-6 [&>*]:w-full">
<InvoiceCreationModeCard />
</div>
</div> </div>
</div> </div>
) )
@@ -24,9 +24,12 @@ import {
items as itemsApi, items as itemsApi,
priceLists as priceListsApi, priceLists as priceListsApi,
users as usersApi, users as usersApi,
invoiceCreationMode as invoiceCreationModeApi,
DEFAULT_INVOICE_CREATION_MODE,
getApiError, getApiError,
getPaginatedItems, getPaginatedItems,
} from '@/lib/api/index' } from '@/lib/api/index'
import type { InvoiceCreationMode } from '@/lib/api/sys-config'
import type { ItemSummaryResponse, ShopPOResponse, UserResponse } from '@/types/api' import type { ItemSummaryResponse, ShopPOResponse, UserResponse } from '@/types/api'
const lineItemSchema = z.object({ const lineItemSchema = z.object({
@@ -56,6 +59,11 @@ export default function EditShopPOPage() {
const [usersList, setUsersList] = useState<UserResponse[]>([]) const [usersList, setUsersList] = useState<UserResponse[]>([])
const [confirmedByUserId, setConfirmedByUserId] = useState('') const [confirmedByUserId, setConfirmedByUserId] = useState('')
const [confirming, setConfirming] = useState(false) const [confirming, setConfirming] = useState(false)
const [mode, setMode] = useState<InvoiceCreationMode>(DEFAULT_INVOICE_CREATION_MODE)
useEffect(() => {
invoiceCreationModeApi.get().then(setMode).catch(() => {})
}, [])
const form = useForm<FormValues>({ const form = useForm<FormValues>({
resolver: zodResolver(schema), resolver: zodResolver(schema),
@@ -98,9 +106,14 @@ export default function EditShopPOPage() {
if (!po || !confirmedByUserId) return if (!po || !confirmedByUserId) return
setConfirming(true) setConfirming(true)
try { try {
const updated = await shopPosApi.confirm(po.id, confirmedByUserId) const updated = mode === 'ModeA'
? await shopPosApi.confirmAndCreateInvoice(po.id, confirmedByUserId)
: await shopPosApi.confirm(po.id, confirmedByUserId)
setPo(updated) setPo(updated)
toast.add({ title: 'Shop PO confirmed', type: 'success' }) toast.add({
title: mode === 'ModeA' ? 'Shop PO confirmed and invoice created' : 'Shop PO confirmed',
type: 'success',
})
} catch (err) { } catch (err) {
toast.add({ title: 'Failed to confirm Shop PO', description: getApiError(err), type: 'error' }) toast.add({ title: 'Failed to confirm Shop PO', description: getApiError(err), type: 'error' })
} finally { } finally {
@@ -21,7 +21,15 @@ import {
} from '@/components/ui/dialog' } from '@/components/ui/dialog'
import { FieldGroup } from '@/components/ui/field' import { FieldGroup } from '@/components/ui/field'
import { toast } from '@/components/ui/toast' import { toast } from '@/components/ui/toast'
import { shopPos as shopPosApi, users as usersApi, getApiError, getPaginatedItems } from '@/lib/api/index' import {
shopPos as shopPosApi,
users as usersApi,
invoiceCreationMode as invoiceCreationModeApi,
DEFAULT_INVOICE_CREATION_MODE,
getApiError,
getPaginatedItems,
} from '@/lib/api/index'
import type { InvoiceCreationMode } from '@/lib/api/sys-config'
import type { ShopPOResponse, UserResponse } from '@/types/api' import type { ShopPOResponse, UserResponse } from '@/types/api'
const schema = z.object({ const schema = z.object({
@@ -39,6 +47,7 @@ interface ConfirmShopPODialogProps {
export function ConfirmShopPODialog({ open, onClose, onSuccess, po }: ConfirmShopPODialogProps) { export function ConfirmShopPODialog({ open, onClose, onSuccess, po }: ConfirmShopPODialogProps) {
const [usersList, setUsersList] = useState<UserResponse[]>([]) const [usersList, setUsersList] = useState<UserResponse[]>([])
const [mode, setMode] = useState<InvoiceCreationMode>(DEFAULT_INVOICE_CREATION_MODE)
const form = useForm<FormValues>({ const form = useForm<FormValues>({
resolver: zodResolver(schema), resolver: zodResolver(schema),
@@ -51,14 +60,20 @@ export function ConfirmShopPODialog({ open, onClose, onSuccess, po }: ConfirmSho
usersApi.list() usersApi.list()
.then((res) => setUsersList(res)) .then((res) => setUsersList(res))
.catch((err) => toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' })) .catch((err) => toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' }))
invoiceCreationModeApi.get().then(setMode).catch(() => {})
}, [open]) }, [open])
if (!po) return null if (!po) return null
async function onSubmit(values: FormValues) { async function onSubmit(values: FormValues) {
try { try {
if (mode === 'ModeA') {
await shopPosApi.confirmAndCreateInvoice(po!.id, values.confirmedByUserId)
toast.add({ title: 'Shop PO confirmed and invoice created', type: 'success' })
} else {
await shopPosApi.confirm(po!.id, values.confirmedByUserId) await shopPosApi.confirm(po!.id, values.confirmedByUserId)
toast.add({ title: 'Shop PO confirmed', type: 'success' }) toast.add({ title: 'Shop PO confirmed', type: 'success' })
}
onSuccess() onSuccess()
onClose() onClose()
} catch (err) { } catch (err) {
@@ -71,7 +86,10 @@ export function ConfirmShopPODialog({ open, onClose, onSuccess, po }: ConfirmSho
<DialogContent className="sm:max-w-md"> <DialogContent className="sm:max-w-md">
<DialogHeader> <DialogHeader>
<DialogTitle>Confirm Shop PO</DialogTitle> <DialogTitle>Confirm Shop PO</DialogTitle>
<DialogDescription>{po.storeName} — Rs. {po.totalAmount.toLocaleString()}</DialogDescription> <DialogDescription>
{po.storeName} — Rs. {po.totalAmount.toLocaleString()}
{mode === 'ModeA' && ' · a draft invoice will be created'}
</DialogDescription>
</DialogHeader> </DialogHeader>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-6"> <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-6">
@@ -0,0 +1,142 @@
'use client'
import { useEffect, useState } from 'react'
import { useForm, zodResolver, z } from '@/lib/form'
import { FormField } from '@/components/shared/form-field'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog'
import { FieldGroup } from '@/components/ui/field'
import { toast } from '@/components/ui/toast'
import { invoices as invoicesApi, shopPos as shopPosApi, users as usersApi, getApiError } from '@/lib/api/index'
import type { ShopPOResponse, UserResponse } from '@/types/api'
const schema = z.object({
shopPOId: z.string().min(1, 'Shop PO is required'),
userId: z.string().min(1, 'User is required'),
})
type FormValues = z.infer<typeof schema>
interface CreateInvoiceDialogProps {
open: boolean
onClose: () => void
onSuccess: () => void
}
const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}`
const truncId = (id: string) => id.substring(0, 8)
export function CreateInvoiceDialog({ open, onClose, onSuccess }: CreateInvoiceDialogProps) {
const [pos, setPos] = useState<ShopPOResponse[]>([])
const [usersList, setUsersList] = useState<UserResponse[]>([])
const [loading, setLoading] = useState(false)
const form = useForm<FormValues>({
resolver: zodResolver(schema),
defaultValues: { shopPOId: '', userId: '' },
})
useEffect(() => {
if (!open) return
form.reset({ shopPOId: '', userId: '' })
setLoading(true)
Promise.all([
shopPosApi.confirmedWithoutInvoice(),
usersApi.list(),
])
.then(([posRes, usersRes]) => {
setPos(posRes)
setUsersList(usersRes)
})
.catch((err) => toast.add({ title: 'Failed to load data', description: getApiError(err), type: 'error' }))
.finally(() => setLoading(false))
}, [open])
async function onSubmit(values: FormValues) {
try {
await invoicesApi.create(values.shopPOId, values.userId)
toast.add({ title: 'Invoice created', type: 'success' })
onSuccess()
onClose()
} catch (err) {
toast.add({ title: 'Failed to create invoice', description: getApiError(err), type: 'error' })
}
}
return (
<Dialog open={open} onOpenChange={(v) => { if (!v) onClose() }}>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle>Create Invoice</DialogTitle>
<DialogDescription>Generate an invoice from a confirmed Shop PO that doesn&apos;t have one yet.</DialogDescription>
</DialogHeader>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-6">
<FieldGroup>
<FormField
control={form.control}
name="shopPOId"
label="Shop PO"
required
render={({ field }) => (
<Select value={field.value as string} onValueChange={field.onChange} disabled={loading || pos.length === 0}>
<SelectTrigger>
<SelectValue placeholder={loading ? 'Loading…' : pos.length === 0 ? 'No eligible Shop POs' : 'Select Shop PO...'} />
</SelectTrigger>
<SelectContent>
{pos.map((po) => (
<SelectItem key={po.id} value={po.id}>
{po.storeName} — {fmtAmount(po.totalAmount)} [{truncId(po.id)}]
</SelectItem>
))}
</SelectContent>
</Select>
)}
/>
<FormField
control={form.control}
name="userId"
label="Created By"
description="Temporary — required until auth resolves the logged-in user automatically."
required
render={({ field }) => (
<Select value={field.value as string} onValueChange={field.onChange}>
<SelectTrigger>
<SelectValue placeholder="Select user..." />
</SelectTrigger>
<SelectContent>
{usersList.map((user) => (
<SelectItem key={user.id} value={user.id}>{user.fullName}</SelectItem>
))}
</SelectContent>
</Select>
)}
/>
</FieldGroup>
<DialogFooter>
<Button type="button" variant="outline" onClick={onClose}>Cancel</Button>
<Button type="submit" disabled={form.formState.isSubmitting || pos.length === 0}>
{form.formState.isSubmitting ? 'Saving…' : 'Create Invoice'}
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
)
}
@@ -5,12 +5,15 @@ import { useState, useEffect, useCallback, useMemo } from 'react'
import { DataTable } from '@/components/shared/data-table' import { DataTable } from '@/components/shared/data-table'
import type { TableConfig } from '@/components/shared/data-table' import type { TableConfig } from '@/components/shared/data-table'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { toast } from '@/components/ui/toast' import { toast } from '@/components/ui/toast'
import { invoices as invoicesApi, getApiError, getPaginatedItems } from '@/lib/api/index' import { invoices as invoicesApi, invoiceCreationMode as invoiceCreationModeApi, DEFAULT_INVOICE_CREATION_MODE, getApiError, getPaginatedItems } from '@/lib/api/index'
import type { InvoiceCreationMode } from '@/lib/api/sys-config'
import type { InvoiceResponse, InvoiceStatus, PaymentStatus } from '@/types/api' import type { InvoiceResponse, InvoiceStatus, PaymentStatus } from '@/types/api'
import { OrderViewSheet } from './order-view-sheet' import { OrderViewSheet } from './order-view-sheet'
import { InvoiceActionDialog } from './invoice-action-dialog' import { InvoiceActionDialog } from './invoice-action-dialog'
import { CreateInvoiceDialog } from './create-invoice-dialog'
import { PaymentSheet } from '../../payments/_components/payment-sheet' import { PaymentSheet } from '../../payments/_components/payment-sheet'
const fmtDate = (v: string) => const fmtDate = (v: string) =>
@@ -44,6 +47,12 @@ export function OrdersClient() {
const [actionMode, setActionMode] = useState<'print' | 'finalize'>('print') const [actionMode, setActionMode] = useState<'print' | 'finalize'>('print')
const [paymentOpen, setPaymentOpen] = useState(false) const [paymentOpen, setPaymentOpen] = useState(false)
const [paymentInvoice, setPaymentInvoice] = useState<InvoiceResponse | null>(null) const [paymentInvoice, setPaymentInvoice] = useState<InvoiceResponse | null>(null)
const [createOpen, setCreateOpen] = useState(false)
const [mode, setMode] = useState<InvoiceCreationMode>(DEFAULT_INVOICE_CREATION_MODE)
useEffect(() => {
invoiceCreationModeApi.get().then(setMode).catch(() => {})
}, [])
const fetchData = useCallback(async (p: number, ps: number) => { const fetchData = useCallback(async (p: number, ps: number) => {
setLoading(true) setLoading(true)
@@ -178,6 +187,9 @@ export function OrdersClient() {
Billing documents generated from confirmed Shop POs Billing documents generated from confirmed Shop POs
</p> </p>
</div> </div>
{mode === 'ModeB' && (
<Button onClick={() => setCreateOpen(true)}>Create Invoice</Button>
)}
</div> </div>
<DataTable <DataTable
@@ -212,6 +224,12 @@ export function OrdersClient() {
invoices={paymentInvoice ? [paymentInvoice] : []} invoices={paymentInvoice ? [paymentInvoice] : []}
defaultInvoiceId={paymentInvoice?.id} defaultInvoiceId={paymentInvoice?.id}
/> />
<CreateInvoiceDialog
open={createOpen}
onClose={() => setCreateOpen(false)}
onSuccess={() => fetchData(page, pageSize)}
/>
</> </>
) )
} }
@@ -23,8 +23,8 @@ import {
} from '@/components/ui/dialog' } from '@/components/ui/dialog'
import { FieldGroup } from '@/components/ui/field' import { FieldGroup } from '@/components/ui/field'
import { toast } from '@/components/ui/toast' import { toast } from '@/components/ui/toast'
import { payments as paymentsApi, bankAccounts as bankAccountsApi, getApiError } from '@/lib/api/index' import { payments as paymentsApi, bankAccounts as bankAccountsApi, stores as storesApi, getApiError } from '@/lib/api/index'
import type { InvoiceResponse } from '@/types/api' import type { InvoiceResponse, OutstandingBalanceResponse } from '@/types/api'
import type { BankAccountResponse } from '@/types/payments' import type { BankAccountResponse } from '@/types/payments'
const schema = z const schema = z
@@ -67,6 +67,7 @@ const truncId = (id: string) => id.substring(0, 8)
export function PaymentSheet({ open, onClose, onSuccess, invoices, defaultInvoiceId }: PaymentSheetProps) { export function PaymentSheet({ open, onClose, onSuccess, invoices, defaultInvoiceId }: PaymentSheetProps) {
const [accounts, setAccounts] = useState<BankAccountResponse[]>([]) const [accounts, setAccounts] = useState<BankAccountResponse[]>([])
const [credit, setCredit] = useState<OutstandingBalanceResponse | null>(null)
const form = useForm<FormValues>({ const form = useForm<FormValues>({
resolver: zodResolver(schema), resolver: zodResolver(schema),
@@ -84,6 +85,16 @@ export function PaymentSheet({ open, onClose, onSuccess, invoices, defaultInvoic
}) })
const method = form.watch('method') const method = form.watch('method')
const invoiceId = form.watch('invoiceId')
const amount = form.watch('amount')
const selectedInvoice = invoices.find((inv) => inv.id === invoiceId)
const selectedStoreId = selectedInvoice?.storeId
const remaining = selectedInvoice ? selectedInvoice.totalAmount - selectedInvoice.paidAmount : 0
useEffect(() => {
if (!open || !selectedInvoice) return
form.setValue('amount', Number((selectedInvoice.totalAmount - selectedInvoice.paidAmount).toFixed(2)))
}, [open, selectedInvoice?.id])
useEffect(() => { useEffect(() => {
if (!open) return if (!open) return
@@ -101,10 +112,39 @@ export function PaymentSheet({ open, onClose, onSuccess, invoices, defaultInvoic
bankAccountsApi.list() bankAccountsApi.list()
.then(list => setAccounts(list.filter(a => a.isActive !== false))) .then(list => setAccounts(list.filter(a => a.isActive !== false)))
.catch(() => {}) .catch(() => {})
setCredit(null)
}, [open, defaultInvoiceId]) }, [open, defaultInvoiceId])
useEffect(() => {
if (!open || method !== 'Credit' || !selectedStoreId) {
setCredit(null)
return
}
let cancelled = false
storesApi.outstandingBalance(selectedStoreId)
.then((data) => { if (!cancelled) setCredit(data) })
.catch(() => { if (!cancelled) setCredit(null) })
return () => { cancelled = true }
}, [open, method, selectedStoreId])
async function onSubmit(values: FormValues) { async function onSubmit(values: FormValues) {
const { invoiceId, method, bankAccountId, chequeNumber, chequeDate, drawerBankName, accountHolderName, ...rest } = values const { invoiceId, method, bankAccountId, chequeNumber, chequeDate, drawerBankName, accountHolderName, ...rest } = values
if (selectedInvoice && values.amount > remaining) {
toast.add({
title: 'Amount exceeds outstanding balance',
description: `Outstanding: Rs. ${remaining.toLocaleString()}`,
type: 'error',
})
return
}
if (method === 'Credit' && credit && values.amount > credit.availableCredit) {
toast.add({
title: 'Credit limit exceeded',
description: `Available credit: Rs. ${credit.availableCredit.toLocaleString()}`,
type: 'error',
})
return
}
try { try {
await paymentsApi.create(invoiceId, { await paymentsApi.create(invoiceId, {
...rest, ...rest,
@@ -161,6 +201,7 @@ export function PaymentSheet({ open, onClose, onSuccess, invoices, defaultInvoic
name="amount" name="amount"
label="Amount" label="Amount"
required required
description={selectedInvoice ? `Outstanding: ${fmtAmount(remaining)}` : undefined}
render={({ field, invalid }) => ( render={({ field, invalid }) => (
<Input <Input
id="amount" id="amount"
@@ -172,7 +213,7 @@ export function PaymentSheet({ open, onClose, onSuccess, invoices, defaultInvoic
onChange={(e) => field.onChange(Number(e.target.value))} onChange={(e) => field.onChange(Number(e.target.value))}
onBlur={field.onBlur} onBlur={field.onBlur}
placeholder="0.00" placeholder="0.00"
aria-invalid={invalid} aria-invalid={invalid || (selectedInvoice ? amount > remaining : false)}
/> />
)} )}
/> />
@@ -196,6 +237,36 @@ export function PaymentSheet({ open, onClose, onSuccess, invoices, defaultInvoic
)} )}
/> />
{method === 'Credit' && selectedStoreId && (
<div className="rounded-md border bg-muted/40 p-3 text-sm">
{credit ? (
<div className="flex flex-col gap-1">
<div className="flex justify-between">
<span className="text-muted-foreground">Credit limit</span>
<span>{fmtAmount(credit.creditLimit)}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Currently used</span>
<span>{fmtAmount(credit.outstandingBalance)}</span>
</div>
<div className="flex justify-between font-medium">
<span>Available</span>
<span className={amount > credit.availableCredit ? 'text-destructive' : ''}>
{fmtAmount(credit.availableCredit)}
</span>
</div>
{amount > credit.availableCredit && (
<p className="text-destructive text-xs mt-1">
Amount exceeds available credit.
</p>
)}
</div>
) : (
<span className="text-muted-foreground">Loading credit info…</span>
)}
</div>
)}
{method === 'Cash' && ( {method === 'Cash' && (
<FormField <FormField
control={form.control} control={form.control}
+1 -1
View File
@@ -11,7 +11,7 @@ export { stock } from './stock'
export { productReports, stockReports, dashboardReports } from './reports' export { productReports, stockReports, dashboardReports } from './reports'
export { shopPos, invoices, payments } from './sales' export { shopPos, invoices, payments } from './sales'
export { saleReturns, claims, supplierClaims } from './returns-claims' export { saleReturns, claims, supplierClaims } from './returns-claims'
export { sysConfig, ITEM_TRACKING_KEYS, GRN_TAX_KEYS, grnTaxSettings, DEFAULT_GRN_TAX_SETTINGS } from './sys-config' export { sysConfig, ITEM_TRACKING_KEYS, GRN_TAX_KEYS, grnTaxSettings, DEFAULT_GRN_TAX_SETTINGS, invoiceCreationMode, INVOICE_CREATION_MODE_KEY, DEFAULT_INVOICE_CREATION_MODE } from './sys-config'
export { bankAccounts } from './bank-accounts' export { bankAccounts } from './bank-accounts'
export { chequeBooks, chequePages } from './cheques' export { chequeBooks, chequePages } from './cheques'
export { receivedCheques } from './received-cheques' export { receivedCheques } from './received-cheques'
+6
View File
@@ -48,6 +48,9 @@ export const shopPos = {
get: (id: string) => get: (id: string) =>
api.get<ShopPOResponse>(`/shop-pos/${id}`).then(r => r.data), api.get<ShopPOResponse>(`/shop-pos/${id}`).then(r => r.data),
confirmedWithoutInvoice: (params?: { agentId?: string; routeId?: string; shopId?: string }) =>
api.get<ShopPOResponse[]>('/shop-pos/confirmed-without-invoice', { params }).then(r => r.data),
create: (body: CreateShopPOBody) => create: (body: CreateShopPOBody) =>
api.post<ShopPOResponse>('/shop-pos', body).then(r => r.data), api.post<ShopPOResponse>('/shop-pos', body).then(r => r.data),
@@ -84,6 +87,9 @@ export const invoices = {
get: (id: string) => get: (id: string) =>
api.get<InvoiceResponse>(`/invoices/${id}`).then(r => r.data), api.get<InvoiceResponse>(`/invoices/${id}`).then(r => r.data),
create: (shopPOId: string, createdByUserId?: string | null) =>
api.post<InvoiceResponse>('/invoices', { shopPOId, createdByUserId }).then(r => r.data),
print: (id: string, printedByUserId?: string | null) => print: (id: string, printedByUserId?: string | null) =>
api.post<InvoiceResponse>(`/invoices/${id}/print`, { printedByUserId }).then(r => r.data), api.post<InvoiceResponse>(`/invoices/${id}/print`, { printedByUserId }).then(r => r.data),
+16
View File
@@ -72,3 +72,19 @@ export const grnTaxSettings = {
.getAll() .getAll()
.then(all => parseGrnTaxSettings(Object.fromEntries(all.map(c => [c.key, c.value])))), .then(all => parseGrnTaxSettings(Object.fromEntries(all.map(c => [c.key, c.value])))),
} }
// ─── Invoice creation mode (must match Distribution.Features.SysConfig.SysConfigService) ─────
export const INVOICE_CREATION_MODE_KEY = 'InvoiceCreationMode'
export type InvoiceCreationMode = 'ModeA' | 'ModeB'
export const DEFAULT_INVOICE_CREATION_MODE: InvoiceCreationMode = 'ModeB'
export const invoiceCreationMode = {
get: () =>
api.get<{ mode: InvoiceCreationMode }>('/sys-config/invoice-creation-mode').then(r => r.data.mode),
set: (mode: InvoiceCreationMode) =>
api.put('/sys-config/invoice-creation-mode', { mode }).then(r => r.data),
}
+2
View File
@@ -1004,6 +1004,7 @@ export interface ShopPOResponse {
export interface InvoiceResponse { export interface InvoiceResponse {
id: string id: string
shopPOId: string shopPOId: string
storeId: string
storeName: string storeName: string
status: InvoiceStatus status: InvoiceStatus
paymentStatus: PaymentStatus paymentStatus: PaymentStatus
@@ -1013,6 +1014,7 @@ export interface InvoiceResponse {
finalizedAt: string | null finalizedAt: string | null
finalizedBy: string | null finalizedBy: string | null
totalAmount: number totalAmount: number
paidAmount: number
isActive: boolean isActive: boolean
createdAt: string createdAt: string
} }