Added the get list of invoices API
This commit is contained in:
parent
b30369baa5
commit
5ff87cd870
6514
Marco.Pms.DataAccess/Migrations/20251013141456_Added_EInvoiceNumber_In_Invoice_Table.Designer.cs
generated
Normal file
6514
Marco.Pms.DataAccess/Migrations/20251013141456_Added_EInvoiceNumber_In_Invoice_Table.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,61 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Added_EInvoiceNumber_In_Invoice_Table : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "Amount",
|
||||||
|
table: "Invoices",
|
||||||
|
newName: "TaxAmount");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<double>(
|
||||||
|
name: "BasicAmount",
|
||||||
|
table: "Invoices",
|
||||||
|
type: "double",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0.0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "EInvoiceNumber",
|
||||||
|
table: "Invoices",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "MarkAsCompleted",
|
||||||
|
table: "Invoices",
|
||||||
|
type: "tinyint(1)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "BasicAmount",
|
||||||
|
table: "Invoices");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EInvoiceNumber",
|
||||||
|
table: "Invoices");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MarkAsCompleted",
|
||||||
|
table: "Invoices");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "TaxAmount",
|
||||||
|
table: "Invoices",
|
||||||
|
newName: "Amount");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -375,7 +375,7 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("char(36)");
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
b.Property<double>("Amount")
|
b.Property<double>("BasicAmount")
|
||||||
.HasColumnType("double");
|
.HasColumnType("double");
|
||||||
|
|
||||||
b.Property<DateTime>("ClientSubmitedDate")
|
b.Property<DateTime>("ClientSubmitedDate")
|
||||||
@ -391,6 +391,9 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("EInvoiceNumber")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
b.Property<DateTime>("ExceptedPaymentDate")
|
b.Property<DateTime>("ExceptedPaymentDate")
|
||||||
.HasColumnType("datetime(6)");
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
@ -404,9 +407,15 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
b.Property<bool>("IsActive")
|
b.Property<bool>("IsActive")
|
||||||
.HasColumnType("tinyint(1)");
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("MarkAsCompleted")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
b.Property<Guid>("ProjectId")
|
b.Property<Guid>("ProjectId")
|
||||||
.HasColumnType("char(36)");
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<double>("TaxAmount")
|
||||||
|
.HasColumnType("double");
|
||||||
|
|
||||||
b.Property<Guid>("TenantId")
|
b.Property<Guid>("TenantId")
|
||||||
.HasColumnType("char(36)");
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ namespace Marco.Pms.Model.Collection
|
|||||||
public string Title { get; set; } = default!;
|
public string Title { get; set; } = default!;
|
||||||
public string Description { get; set; } = default!;
|
public string Description { get; set; } = default!;
|
||||||
public string InvoiceNumber { get; set; } = default!;
|
public string InvoiceNumber { get; set; } = default!;
|
||||||
|
public string? EInvoiceNumber { get; set; }
|
||||||
public Guid ProjectId { get; set; }
|
public Guid ProjectId { get; set; }
|
||||||
|
|
||||||
[ValidateNever]
|
[ValidateNever]
|
||||||
@ -20,8 +21,10 @@ namespace Marco.Pms.Model.Collection
|
|||||||
public DateTime InvoiceDate { get; set; }
|
public DateTime InvoiceDate { get; set; }
|
||||||
public DateTime ClientSubmitedDate { get; set; }
|
public DateTime ClientSubmitedDate { get; set; }
|
||||||
public DateTime ExceptedPaymentDate { get; set; }
|
public DateTime ExceptedPaymentDate { get; set; }
|
||||||
public double Amount { get; set; }
|
public double BasicAmount { get; set; }
|
||||||
|
public double TaxAmount { get; set; }
|
||||||
public bool IsActive { get; set; } = true;
|
public bool IsActive { get; set; } = true;
|
||||||
|
public bool MarkAsCompleted { get; set; } = true;
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
public Guid CreatedById { get; set; }
|
public Guid CreatedById { get; set; }
|
||||||
|
|
||||||
|
@ -8,11 +8,13 @@ namespace Marco.Pms.Model.Dtos.Collection
|
|||||||
public required string Title { get; set; }
|
public required string Title { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
public required string InvoiceNumber { get; set; }
|
public required string InvoiceNumber { get; set; }
|
||||||
|
public string? EInvoiceNumber { get; set; }
|
||||||
public required Guid ProjectId { get; set; }
|
public required Guid ProjectId { get; set; }
|
||||||
public required DateTime InvoiceDate { get; set; }
|
public required DateTime InvoiceDate { get; set; }
|
||||||
public required DateTime ClientSubmitedDate { get; set; }
|
public required DateTime ClientSubmitedDate { get; set; }
|
||||||
public required DateTime ExceptedPaymentDate { get; set; }
|
public required DateTime ExceptedPaymentDate { get; set; }
|
||||||
public required double Amount { get; set; }
|
public double BasicAmount { get; set; }
|
||||||
|
public double TaxAmount { get; set; }
|
||||||
public List<FileUploadModel>? Attachments { get; set; }
|
public List<FileUploadModel>? Attachments { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,16 @@ namespace Marco.Pms.Model.ViewModels.Collection
|
|||||||
public string Title { get; set; } = default!;
|
public string Title { get; set; } = default!;
|
||||||
public string Description { get; set; } = default!;
|
public string Description { get; set; } = default!;
|
||||||
public string InvoiceNumber { get; set; } = default!;
|
public string InvoiceNumber { get; set; } = default!;
|
||||||
|
public string? EInvoiceNumber { get; set; }
|
||||||
public BasicProjectVM? Project { get; set; }
|
public BasicProjectVM? Project { get; set; }
|
||||||
public DateTime InvoiceDate { get; set; }
|
public DateTime InvoiceDate { get; set; }
|
||||||
public DateTime ClientSubmitedDate { get; set; }
|
public DateTime ClientSubmitedDate { get; set; }
|
||||||
public DateTime ExceptedPaymentDate { get; set; }
|
public DateTime ExceptedPaymentDate { get; set; }
|
||||||
public double Amount { get; set; }
|
public double BasicAmount { get; set; }
|
||||||
public bool IsActive { get; set; } = true;
|
public double TaxAmount { get; set; }
|
||||||
|
public double BalanceAmount { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public bool MarkAsCompleted { get; set; }
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||||
public DateTime? UpdatedAt { get; set; }
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
@ -44,18 +44,139 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
tenantId = userhelper.GetTenantId();
|
tenantId = userhelper.GetTenantId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("invoice/list")]
|
||||||
|
public async Task<IActionResult> GetInvoiceListAsync([FromQuery] string? searchString, [FromQuery] DateTime? fromDate, [FromQuery] DateTime? toDate, [FromQuery] int pageSize = 20, [FromQuery] int pageNumber = 1
|
||||||
|
, [FromQuery] bool isActive = true, [FromQuery] bool isPending = false)
|
||||||
|
{
|
||||||
|
_logger.LogInfo(
|
||||||
|
"Fetching invoice list: Page {PageNumber}, Size {PageSize}, Active={IsActive}, PendingOnly={IsPending}, Search='{SearchString}', From={From}, To={To}",
|
||||||
|
pageNumber, pageSize, isActive, isPending, searchString ?? "", fromDate?.Date ?? DateTime.MinValue, toDate?.Date ?? DateTime.MaxValue);
|
||||||
|
|
||||||
|
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
|
||||||
|
// Build base query with required includes and no tracking
|
||||||
|
var invoicesQuery = context.Invoices
|
||||||
|
.Include(i => i.Project)
|
||||||
|
.Include(i => i.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(i => i.UpdatedBy).ThenInclude(e => e!.JobRole)
|
||||||
|
.Where(i => i.IsActive == isActive && i.TenantId == tenantId)
|
||||||
|
.AsNoTracking(); // Disable change tracking for read-only query
|
||||||
|
|
||||||
|
// Apply date filter
|
||||||
|
if (fromDate.HasValue && toDate.HasValue)
|
||||||
|
{
|
||||||
|
var fromDateUtc = fromDate.Value.Date;
|
||||||
|
var toDateUtc = toDate.Value.Date.AddDays(1).AddTicks(-1); // End of day
|
||||||
|
invoicesQuery = invoicesQuery.Where(i => i.InvoiceDate >= fromDateUtc && i.InvoiceDate <= toDateUtc);
|
||||||
|
_logger.LogDebug("Applied date filter: {From} to {To}", fromDateUtc, toDateUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply search filter
|
||||||
|
if (!string.IsNullOrWhiteSpace(searchString))
|
||||||
|
{
|
||||||
|
invoicesQuery = invoicesQuery.Where(i => i.Title.Contains(searchString) || i.InvoiceNumber.Contains(searchString));
|
||||||
|
_logger.LogDebug("Applied search filter with term: {SearchString}", searchString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get total count before pagination
|
||||||
|
var totalEntites = await invoicesQuery.CountAsync();
|
||||||
|
_logger.LogDebug("Total matching invoices: {TotalCount}", totalEntites);
|
||||||
|
|
||||||
|
// Apply sorting and pagination
|
||||||
|
var invoices = await invoicesQuery
|
||||||
|
.OrderByDescending(i => i.InvoiceDate)
|
||||||
|
.Skip((pageNumber - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
if (!invoices.Any())
|
||||||
|
{
|
||||||
|
_logger.LogInfo("No invoices found for the given criteria.");
|
||||||
|
var emptyResponse = new
|
||||||
|
{
|
||||||
|
CurrentPage = pageNumber,
|
||||||
|
TotalPages = 0,
|
||||||
|
TotalEntites = 0,
|
||||||
|
Data = new List<InvoiceListVM>()
|
||||||
|
};
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(emptyResponse, "No invoices found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all related payment data in a single query
|
||||||
|
var invoiceIds = invoices.Select(i => i.Id).ToList();
|
||||||
|
var paymentGroups = await context.ReceivedInvoicePayments
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(rip => invoiceIds.Contains(rip.InvoiceId) && rip.TenantId == tenantId)
|
||||||
|
.GroupBy(rip => rip.InvoiceId)
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
InvoiceId = g.Key,
|
||||||
|
PaidAmount = g.Sum(rip => rip.Amount)
|
||||||
|
})
|
||||||
|
.ToDictionaryAsync(x => x.InvoiceId, x => x.PaidAmount);
|
||||||
|
|
||||||
|
_logger.LogDebug("Fetched payment data for {Count} invoices", paymentGroups.Count);
|
||||||
|
|
||||||
|
// Map and calculate balance in memory
|
||||||
|
var results = new List<InvoiceListVM>();
|
||||||
|
foreach (var invoice in invoices)
|
||||||
|
{
|
||||||
|
var totalAmount = invoice.BasicAmount + invoice.TaxAmount;
|
||||||
|
var paidAmount = paymentGroups.GetValueOrDefault(invoice.Id, 0);
|
||||||
|
var balanceAmount = totalAmount - paidAmount;
|
||||||
|
|
||||||
|
// Skip if filtering for pending invoices and balance is zero
|
||||||
|
if (isPending && balanceAmount <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var result = _mapper.Map<InvoiceListVM>(invoice);
|
||||||
|
result.BalanceAmount = balanceAmount;
|
||||||
|
results.Add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalPages = (int)Math.Ceiling((double)totalEntites / pageSize);
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
CurrentPage = pageNumber,
|
||||||
|
TotalPages = totalPages,
|
||||||
|
TotalEntites = totalEntites,
|
||||||
|
Data = results
|
||||||
|
};
|
||||||
|
|
||||||
|
_logger.LogInfo("Successfully returned {ResultCount} invoices out of {TotalCount} total", results.Count, totalEntites);
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(response, $"{results.Count} invoices fetched successfully"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpPost("invoice/create")]
|
[HttpPost("invoice/create")]
|
||||||
public async Task<IActionResult> CreateInvoiceAsync(InvoiceDto model)
|
public async Task<IActionResult> CreateInvoiceAsync(InvoiceDto model)
|
||||||
{
|
{
|
||||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
using var scope = _serviceScopeFactory.CreateScope();
|
//using var scope = _serviceScopeFactory.CreateScope();
|
||||||
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
//var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
_logger.LogInfo("Starting invoice creation for ProjectId: {ProjectId} by EmployeeId: {EmployeeId}",
|
_logger.LogInfo("Starting invoice creation for ProjectId: {ProjectId} by EmployeeId: {EmployeeId}",
|
||||||
model.ProjectId, loggedInEmployee.Id);
|
model.ProjectId, loggedInEmployee.Id);
|
||||||
|
|
||||||
|
if (model.InvoiceNumber.Length > 17)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Invoice Number {InvoiceNumber} is greater than 17 charater",
|
||||||
|
model.InvoiceNumber);
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse(
|
||||||
|
"Invoice Number {InvoiceNumber} is greater than 17 charater",
|
||||||
|
"Invoice Number {InvoiceNumber} is greater than 17 charater", 400));
|
||||||
|
}
|
||||||
|
|
||||||
// Validate date sequence
|
// Validate date sequence
|
||||||
|
if (model.InvoiceDate.Date > DateTime.UtcNow.Date)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Invoice date {InvoiceDate} cannot be in the future.",
|
||||||
|
model.InvoiceDate);
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse(
|
||||||
|
"Invoice date cannot be in the future",
|
||||||
|
"Invoice date cannot be in the future", 400));
|
||||||
|
}
|
||||||
if (model.InvoiceDate.Date > model.ClientSubmitedDate.Date)
|
if (model.InvoiceDate.Date > model.ClientSubmitedDate.Date)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Invoice date {InvoiceDate} is later than client submitted date {ClientSubmitedDate}",
|
_logger.LogWarning("Invoice date {InvoiceDate} is later than client submitted date {ClientSubmitedDate}",
|
||||||
@ -64,6 +185,14 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
"Invoice date is later than client submitted date",
|
"Invoice date is later than client submitted date",
|
||||||
"Invoice date is later than client submitted date", 400));
|
"Invoice date is later than client submitted date", 400));
|
||||||
}
|
}
|
||||||
|
if (model.ClientSubmitedDate.Date > DateTime.UtcNow.Date)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Client submited date {ClientSubmitedDate} cannot be in the future.",
|
||||||
|
model.InvoiceDate);
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse(
|
||||||
|
"Client submited date cannot be in the future",
|
||||||
|
"Client submited date cannot be in the future", 400));
|
||||||
|
}
|
||||||
if (model.ClientSubmitedDate.Date > model.ExceptedPaymentDate.Date)
|
if (model.ClientSubmitedDate.Date > model.ExceptedPaymentDate.Date)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Client submitted date {ClientSubmitedDate} is later than expected payment date {ExpectedPaymentDate}",
|
_logger.LogWarning("Client submitted date {ClientSubmitedDate} is later than expected payment date {ExpectedPaymentDate}",
|
||||||
@ -72,9 +201,17 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
"Client submitted date is later than expected payment date",
|
"Client submitted date is later than expected payment date",
|
||||||
"Client submitted date is later than expected payment date", 400));
|
"Client submitted date is later than expected payment date", 400));
|
||||||
}
|
}
|
||||||
|
if (model.ExceptedPaymentDate.Date < DateTime.UtcNow.Date)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Excepted Payment Date {ExceptedPaymentDate} cannot be in the future.",
|
||||||
|
model.ExceptedPaymentDate);
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse(
|
||||||
|
"Excepted Payment Date cannot be in the future",
|
||||||
|
"Excepted Payment Date cannot be in the future", 400));
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch project
|
// Fetch project
|
||||||
var project = await context.Projects
|
var project = await _context.Projects
|
||||||
.FirstOrDefaultAsync(p => p.Id == model.ProjectId && p.TenantId == tenantId);
|
.FirstOrDefaultAsync(p => p.Id == model.ProjectId && p.TenantId == tenantId);
|
||||||
if (project == null)
|
if (project == null)
|
||||||
{
|
{
|
||||||
@ -84,19 +221,20 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Begin transaction scope with async flow support
|
// Begin transaction scope with async flow support
|
||||||
await using var transaction = await context.Database.BeginTransactionAsync();
|
await using var transaction = await _context.Database.BeginTransactionAsync();
|
||||||
var invoice = new Invoice();
|
var invoice = new Invoice();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Map and create invoice
|
// Map and create invoice
|
||||||
invoice = _mapper.Map<Invoice>(model);
|
invoice = _mapper.Map<Invoice>(model);
|
||||||
invoice.IsActive = true;
|
invoice.IsActive = true;
|
||||||
|
invoice.MarkAsCompleted = false;
|
||||||
invoice.CreatedAt = DateTime.UtcNow;
|
invoice.CreatedAt = DateTime.UtcNow;
|
||||||
invoice.CreatedById = loggedInEmployee.Id;
|
invoice.CreatedById = loggedInEmployee.Id;
|
||||||
invoice.TenantId = tenantId;
|
invoice.TenantId = tenantId;
|
||||||
|
|
||||||
context.Invoices.Add(invoice);
|
_context.Invoices.Add(invoice);
|
||||||
await context.SaveChangesAsync(); // Save to generate invoice.Id
|
await _context.SaveChangesAsync(); // Save to generate invoice.Id
|
||||||
|
|
||||||
// Handle attachments
|
// Handle attachments
|
||||||
var documents = new List<Document>();
|
var documents = new List<Document>();
|
||||||
@ -143,9 +281,9 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
invoiceAttachments.Add(invoiceAttachment);
|
invoiceAttachments.Add(invoiceAttachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Documents.AddRange(documents);
|
_context.Documents.AddRange(documents);
|
||||||
context.InvoiceAttachments.AddRange(invoiceAttachments);
|
_context.InvoiceAttachments.AddRange(invoiceAttachments);
|
||||||
await context.SaveChangesAsync(); // Save attachments and mappings
|
await _context.SaveChangesAsync(); // Save attachments and mappings
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit transaction
|
// Commit transaction
|
||||||
@ -166,6 +304,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var response = _mapper.Map<InvoiceListVM>(invoice);
|
var response = _mapper.Map<InvoiceListVM>(invoice);
|
||||||
response.Project = _mapper.Map<BasicProjectVM>(project);
|
response.Project = _mapper.Map<BasicProjectVM>(project);
|
||||||
response.CreatedBy = _mapper.Map<BasicEmployeeVM>(loggedInEmployee);
|
response.CreatedBy = _mapper.Map<BasicEmployeeVM>(loggedInEmployee);
|
||||||
|
response.BalanceAmount = response.BasicAmount + response.TaxAmount;
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Invoice Created Successfully", 201));
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Invoice Created Successfully", 201));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user