Added Finance related model and migrations

This commit is contained in:
ashutosh.nehete 2025-11-07 17:16:05 +05:30
parent a589f2af4b
commit f385a1b555
56 changed files with 10901 additions and 779 deletions

View File

@ -7,6 +7,7 @@ using Marco.Pms.Model.DocumentManager;
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Expenses;
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Forum;
using Marco.Pms.Model.Mail;
using Marco.Pms.Model.Master;
@ -106,6 +107,7 @@ namespace Marco.Pms.DataAccess.Data
public DbSet<Expenses> Expenses { get; set; }
public DbSet<ExpenseLog> ExpenseLogs { get; set; }
public DbSet<ExpensesTypeMaster> ExpensesTypeMaster { get; set; }
public DbSet<ExpenseCategoryMaster> ExpenseCategoryMasters { get; set; }
public DbSet<PaymentModeMatser> PaymentModeMatser { get; set; }
public DbSet<ExpensesStatusMaster> ExpensesStatusMaster { get; set; }
public DbSet<BillAttachments> BillAttachments { get; set; }
@ -113,6 +115,20 @@ namespace Marco.Pms.DataAccess.Data
public DbSet<ExpensesReimburseMapping> ExpensesReimburseMapping { get; set; }
public DbSet<StatusPermissionMapping> StatusPermissionMapping { get; set; }
public DbSet<ExpensesStatusMapping> ExpensesStatusMapping { get; set; }
public DbSet<PaymentRequest> PaymentRequests { get; set; }
public DbSet<PaymentRequestAttachment> PaymentRequestAttachments { get; set; }
public DbSet<RecurringPayment> RecurringPayments { get; set; }
public DbSet<AdvancePaymentTransaction> AdvancePaymentTransactions { get; set; }
public DbSet<RecurringPaymentStatus> RecurringPaymentStatus { get; set; }
public DbSet<StatusUpdateLog> StatusUpdateLogs { get; set; }
// Collection
public DbSet<Invoice> Invoices { get; set; }
public DbSet<InvoiceComment> InvoiceComments { get; set; }
public DbSet<InvoiceAttachment> InvoiceAttachments { get; set; }
public DbSet<ReceivedInvoicePayment> ReceivedInvoicePayments { get; set; }
public DbSet<PaymentAdjustmentHead> PaymentAdjustmentHeads { get; set; }
public DbSet<FCMTokenMapping> FCMTokenMappings { get; set; }
@ -135,13 +151,6 @@ namespace Marco.Pms.DataAccess.Data
public DbSet<ProjectServiceMapping> ProjectServiceMappings { get; set; }
public DbSet<ProjectOrgMapping> ProjectOrgMappings { get; set; }
// Collection
public DbSet<Invoice> Invoices { get; set; }
public DbSet<InvoiceComment> InvoiceComments { get; set; }
public DbSet<InvoiceAttachment> InvoiceAttachments { get; set; }
public DbSet<ReceivedInvoicePayment> ReceivedInvoicePayments { get; set; }
public DbSet<PaymentAdjustmentHead> PaymentAdjustmentHeads { get; set; }
public DbSet<PaymentDetail> PaymentDetails { get; set; }
public DbSet<TenantEnquire> TenantEnquires { get; set; }
@ -484,6 +493,64 @@ namespace Marco.Pms.DataAccess.Data
});
modelBuilder.Entity<CurrencyMaster>().HasData(
new CurrencyMaster
{
Id = Guid.Parse("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"),
CurrencyCode = "INR",
CurrencyName = "Indian Rupee",
Symbol = "₹",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("2f672568-a67b-4961-acb2-a8c7834e1762"),
CurrencyCode = "USD",
CurrencyName = "US Dollar",
Symbol = "$",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("4d1155bb-1448-4d97-a732-96c92eb99c45"),
CurrencyCode = "EUR",
CurrencyName = "Euro",
Symbol = "€",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("3e456237-ef06-4ea1-a261-188c9b0c6df6"),
CurrencyCode = "GBP",
CurrencyName = "Pound Sterling",
Symbol = "£",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("297e237a-56d3-48f6-b39d-ec3991dea8bf"),
CurrencyCode = "JPY",
CurrencyName = "Japanese Yen",
Symbol = "¥",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"),
CurrencyCode = "RUB",
CurrencyName = "Russian Ruble",
Symbol = "₽",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("b960166a-f7e9-49e3-bb4b-28511f126c08"),
CurrencyCode = "CNY",
CurrencyName = "Chinese Yuan (Renminbi)",
Symbol = "¥",
IsActive = true
}
);
modelBuilder.Entity<ExpensesStatusMaster>().HasData(
new ExpensesStatusMaster
@ -500,7 +567,7 @@ namespace Marco.Pms.DataAccess.Data
{
Id = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7"),
Name = "Review Pending",
DisplayName = "Submit",
DisplayName = "Submit for Review",
Description = "Reviewer is currently reviewing the expense.",
Color = "#696cff",
IsSystem = true,
@ -555,10 +622,27 @@ namespace Marco.Pms.DataAccess.Data
Color = "#71dd37",
IsSystem = true,
IsActive = true
},
new ExpensesStatusMaster
{
Id = Guid.Parse("b8586f67-dc19-49c3-b4af-224149efe1d3"),
Name = "Done",
DisplayName = "Create Expense",
Description = "Create new Expense.",
Color = "#0E9F6E",
IsSystem = true,
IsActive = true
}
);
modelBuilder.Entity<ExpensesStatusMapping>().HasData(
// processed to Done
new ExpensesStatusMapping
{
Id = Guid.Parse("a1cc95ed-b276-4a3e-9f00-0a249b522d64"),
StatusId = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95"),
NextStatusId = Guid.Parse("b8586f67-dc19-49c3-b4af-224149efe1d3")
},
// Process to processed
new ExpensesStatusMapping
{
@ -666,10 +750,17 @@ namespace Marco.Pms.DataAccess.Data
Id = Guid.Parse("214354e5-daad-4569-ad69-eb5bf4e87fbc"),
PermissionId = Guid.Parse("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"),
StatusId = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95")
},
// Done Permission Mapping
new StatusPermissionMapping
{
Id = Guid.Parse("de04b6c7-a5cd-4a61-88b0-b43b0008202e"),
PermissionId = Guid.Parse("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"),
StatusId = Guid.Parse("b8586f67-dc19-49c3-b4af-224149efe1d3")
});
modelBuilder.Entity<ExpensesTypeMaster>().HasData(
new ExpensesTypeMaster
modelBuilder.Entity<ExpenseCategoryMaster>().HasData(
new ExpenseCategoryMaster
{
Id = Guid.Parse("5e0c6227-d49d-41ff-9f1f-781f0aee2469"),
Name = "Procurement",
@ -679,7 +770,7 @@ namespace Marco.Pms.DataAccess.Data
IsAttachmentRequried = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.Parse("2de53163-0dbd-404b-8e60-1b02e6b4886a"),
Name = "Transport",
@ -689,7 +780,7 @@ namespace Marco.Pms.DataAccess.Data
IsAttachmentRequried = false,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.Parse("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"),
Name = "Travelling",
@ -699,7 +790,7 @@ namespace Marco.Pms.DataAccess.Data
IsAttachmentRequried = false,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.Parse("52484820-1b54-4865-8f0f-baa2b1d339b9"),
Name = "Mobilization",
@ -709,7 +800,7 @@ namespace Marco.Pms.DataAccess.Data
IsAttachmentRequried = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.Parse("fc59eb90-98ea-481c-b421-54bfa9e42d8f"),
Name = "Employee Welfare",
@ -719,7 +810,7 @@ namespace Marco.Pms.DataAccess.Data
IsAttachmentRequried = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.Parse("77013784-9324-4d8b-bd36-d6f928e68942"),
Name = "Maintenance & Utilities",
@ -729,7 +820,7 @@ namespace Marco.Pms.DataAccess.Data
IsAttachmentRequried = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.Parse("1e2d697a-76b4-4be8-bc66-87144561a1a0"),
Name = "Vendor/Supplier Payments",
@ -739,7 +830,7 @@ namespace Marco.Pms.DataAccess.Data
IsAttachmentRequried = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.Parse("4842fa61-64eb-4241-aebd-8282065af9f9"),
Name = "Compliance & Safety",
@ -757,32 +848,49 @@ namespace Marco.Pms.DataAccess.Data
Id = Guid.Parse("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"),
Name = "Cash",
Description = "Physical currency; still used for small or informal transactions.",
IsActive = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
IsActive = true
},
new PaymentModeMatser
{
Id = Guid.Parse("48d9b462-5d87-4dec-8dec-2bc943943172"),
Name = "Cheque",
Description = "Paper-based payment order; less common now due to processing delays and fraud risks.",
IsActive = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
IsActive = true
},
new PaymentModeMatser
{
Id = Guid.Parse("ed667353-8eea-4fd1-8750-719405932480"),
Name = "NetBanking",
Description = "Online banking portals used to transfer funds directly between accounts",
IsActive = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
IsActive = true
},
new PaymentModeMatser
{
Id = Guid.Parse("2e919e94-694c-41d9-9489-0a2b4208a027"),
Name = "UPI",
Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.",
IsActive = true,
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
IsActive = true
},
new PaymentModeMatser
{
Id = Guid.Parse("a820f240-5e9a-4ae9-9091-8a7aa7720cea"),
Name = "Credit card",
Description = "A credit card is a payment card that allows you to borrow funds from a financial institution to pay for goods and services",
IsActive = true
},
new PaymentModeMatser
{
Id = Guid.Parse("95697409-baf6-4f78-86ab-42d93d9569a8"),
Name = "Debit Card",
Description = "A debit card is a payment card that deducts funds directly from the cardholder's bank account when a purchase is made.",
IsActive = true
},
new PaymentModeMatser
{
Id = Guid.Parse("f67beee6-6763-4108-922c-03bd86b9178d"),
Name = "Advance Payment",
Description = "When a bill is paid using the amount received in advance from a company.",
IsActive = true
}
);
@ -1075,6 +1183,29 @@ namespace Marco.Pms.DataAccess.Data
}
);
modelBuilder.Entity<RecurringPaymentStatus>().HasData(
new RecurringPaymentStatus
{
Id = Guid.Parse("da462422-13b2-45cc-a175-910a225f6fc8"),
Name = "Active"
},
new RecurringPaymentStatus
{
Id = Guid.Parse("3ec864d2-8bf5-42fb-ba70-5090301dd816"),
Name = "De-Activated"
},
new RecurringPaymentStatus
{
Id = Guid.Parse("306856fb-5655-42eb-bf8b-808bb5e84725"),
Name = "Completed"
},
new RecurringPaymentStatus
{
Id = Guid.Parse("8bfc9346-e092-4a80-acbf-515ae1ef6868"),
Name = "Paused"
}
);
modelBuilder.Entity<Module>().HasData(
new Module
{
@ -1103,14 +1234,24 @@ namespace Marco.Pms.DataAccess.Data
Name = "Tenant",
Description = "Tenant Module",
Key = "504ec132-e6a9-422f-8f85-050602cfce05"
},
new Module
{
Id = new Guid("0a79687a-86d7-430d-a2d7-8b8603cc76a1"),
Name = "Finance",
Description = "Finance Module",
Key = "504ec132-e6a9-422f-8f85-050602cfce05"
});
modelBuilder.Entity<Feature>().HasData(
// Project Module
new Feature { Id = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), Description = "Manage Project", Name = "Project Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
new Feature { Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), Description = "Manage Tasks", Name = "Task Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
// Finance Module
new Feature { Id = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), Description = "Expense Management is the systematic process of tracking, controlling, and reporting business-related expenditures.", Name = "Expense Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
new Feature { Id = new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), Description = "Collection Management is a feature that enables organizations to track, organize, and manage the status and recovery of receivables or assets efficiently throughout their lifecycle, supporting systematic follow-up and resolution of outstanding accounts.", Name = "Collection Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
new Feature { Id = new Guid("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), Description = "Manage Tasks", Name = "Task Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
new Feature { Id = new Guid("86e80017-0698-4efe-93d0-806de67266e0"), Description = "Recurring Template Management is the automated creation and scheduling of repetitive tasks, processes, or transactions using predefined templates at set intervals to ensure consistent and efficient workflow execution without manual recreation each time.", Name = "Recurring Template Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
// Employee Module
new Feature { Id = new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), Description = "Manage Employee", Name = "Employee Management", ModuleId = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"), IsActive = true },
@ -1188,6 +1329,11 @@ namespace Marco.Pms.DataAccess.Data
new FeaturePermission { Id = new Guid("455187b4-fef1-41f9-b3d0-025d0b6302c3"), FeatureId = new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), IsEnabled = true, Name = "Edit Collection", Description = "Ability to modify collection properties, content, and access rights." },
new FeaturePermission { Id = new Guid("061d9ccd-85b4-4cb0-be06-2f9f32cebb72"), FeatureId = new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), IsEnabled = true, Name = "Add Payment", Description = " Enables entry and processing of payment transactions." },
// Recurring Template Management
new FeaturePermission { Id = new Guid("6382ea8b-aff2-4cd2-a48f-a652b35825d8"), FeatureId = new Guid("86e80017-0698-4efe-93d0-806de67266e0"), IsEnabled = true, Name = "Manage Recurring", Description = "Manage Recurring Template payment permission allows authorized users to set up, modify, and execute automated recurring payments using predefined templates, ensuring secure and controlled handling of repetitive financial transactions." },
new FeaturePermission { Id = new Guid("7ddf2fba-c44d-4fe3-b4ec-690ff70be2e3"), FeatureId = new Guid("86e80017-0698-4efe-93d0-806de67266e0"), IsEnabled = true, Name = "View All Recurring", Description = "The \"View All Recurring Template payment permission\" generally allows users to see and access all recurring payment templates in the system, enabling them to review, manage, and process recurring transactions efficiently." },
new FeaturePermission { Id = new Guid("e5d21efe-573d-4a16-a0f8-414d3e442e78"), FeatureId = new Guid("86e80017-0698-4efe-93d0-806de67266e0"), IsEnabled = true, Name = "View Self Recurring", Description = "View Self Recurring Template payment permission allows a user to view and access their own recurring payment templates without editing rights." },
// Organization Management Feature
new FeaturePermission { Id = new Guid("068cb3c1-49c5-4746-9f29-1fce16e820ac"), FeatureId = new Guid("6d4c82d6-dbce-48ab-b8b8-f785f4d8c914"), IsEnabled = true, Name = "Add Organization", Description = "Allow user to create new organization" },
new FeaturePermission { Id = new Guid("c1ae1363-ab8a-4bd9-a9d1-8c2c6083873a"), FeatureId = new Guid("6d4c82d6-dbce-48ab-b8b8-f785f4d8c914"), IsEnabled = true, Name = "Edit Organization", Description = "Allow the user to update the basic information of the organization" },
@ -1195,64 +1341,6 @@ namespace Marco.Pms.DataAccess.Data
);
modelBuilder.Entity<CurrencyMaster>().HasData(
new CurrencyMaster
{
Id = Guid.Parse("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"),
CurrencyCode = "INR",
CurrencyName = "Indian Rupee",
Symbol = "₹",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("2f672568-a67b-4961-acb2-a8c7834e1762"),
CurrencyCode = "USD",
CurrencyName = "US Dollar",
Symbol = "$",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("4d1155bb-1448-4d97-a732-96c92eb99c45"),
CurrencyCode = "EUR",
CurrencyName = "Euro",
Symbol = "€",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("3e456237-ef06-4ea1-a261-188c9b0c6df6"),
CurrencyCode = "GBP",
CurrencyName = "Pound Sterling",
Symbol = "£",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("297e237a-56d3-48f6-b39d-ec3991dea8bf"),
CurrencyCode = "JPY",
CurrencyName = "Japanese Yen",
Symbol = "¥",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"),
CurrencyCode = "RUB",
CurrencyName = "Russian Ruble",
Symbol = "₽",
IsActive = true
},
new CurrencyMaster
{
Id = Guid.Parse("b960166a-f7e9-49e3-bb4b-28511f126c08"),
CurrencyCode = "CNY",
CurrencyName = "Chinese Yuan (Renminbi)",
Symbol = "¥",
IsActive = true
}
);
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,950 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_Finance_Related_Tables : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Expenses_ExpensesTypeMaster_ExpensesTypeId",
table: "Expenses");
migrationBuilder.DropForeignKey(
name: "FK_PaymentModeMatser_Tenants_TenantId",
table: "PaymentModeMatser");
migrationBuilder.DropIndex(
name: "IX_PaymentModeMatser_TenantId",
table: "PaymentModeMatser");
migrationBuilder.DropIndex(
name: "IX_Expenses_ExpensesTypeId",
table: "Expenses");
migrationBuilder.DeleteData(
table: "ExpensesTypeMaster",
keyColumn: "Id",
keyValue: new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"));
migrationBuilder.DeleteData(
table: "ExpensesTypeMaster",
keyColumn: "Id",
keyValue: new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"));
migrationBuilder.DeleteData(
table: "ExpensesTypeMaster",
keyColumn: "Id",
keyValue: new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"));
migrationBuilder.DeleteData(
table: "ExpensesTypeMaster",
keyColumn: "Id",
keyValue: new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"));
migrationBuilder.DeleteData(
table: "ExpensesTypeMaster",
keyColumn: "Id",
keyValue: new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"));
migrationBuilder.DeleteData(
table: "ExpensesTypeMaster",
keyColumn: "Id",
keyValue: new Guid("77013784-9324-4d8b-bd36-d6f928e68942"));
migrationBuilder.DeleteData(
table: "ExpensesTypeMaster",
keyColumn: "Id",
keyValue: new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"));
migrationBuilder.DeleteData(
table: "ExpensesTypeMaster",
keyColumn: "Id",
keyValue: new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"));
migrationBuilder.DropColumn(
name: "TenantId",
table: "PaymentModeMatser");
migrationBuilder.AlterColumn<string>(
name: "ExpenseUId",
table: "Expenses",
type: "longtext",
nullable: true,
oldClrType: typeof(string),
oldType: "longtext")
.Annotation("MySql:CharSet", "utf8mb4")
.OldAnnotation("MySql:CharSet", "utf8mb4");
migrationBuilder.AddColumn<double>(
name: "BaseAmount",
table: "Expenses",
type: "double",
nullable: true);
migrationBuilder.AddColumn<Guid>(
name: "CurrencyId",
table: "Expenses",
type: "char(36)",
nullable: false,
defaultValue: new Guid("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"),
collation: "ascii_general_ci");
migrationBuilder.AddColumn<Guid>(
name: "ExpenseCategoryId",
table: "Expenses",
type: "char(36)",
nullable: false,
defaultValue: new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"),
collation: "ascii_general_ci");
migrationBuilder.AddColumn<Guid>(
name: "PaymentRequestId",
table: "Expenses",
type: "char(36)",
nullable: true,
collation: "ascii_general_ci");
migrationBuilder.AddColumn<double>(
name: "TDSPercentage",
table: "Expenses",
type: "double",
nullable: true);
migrationBuilder.AddColumn<double>(
name: "TaxAmount",
table: "Expenses",
type: "double",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "UIDPostfix",
table: "Expenses",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<string>(
name: "UIDPrefix",
table: "Expenses",
type: "longtext",
nullable: false)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AdvancePaymentTransactions",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
FinanceUIdPrefix = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
FinanceUIdPostfix = table.Column<int>(type: "int", nullable: false),
Title = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ProjectId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
EmployeeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Amount = table.Column<double>(type: "double", nullable: false),
CurrentBalance = table.Column<double>(type: "double", nullable: false),
PaidAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatedById = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_AdvancePaymentTransactions", x => x.Id);
table.ForeignKey(
name: "FK_AdvancePaymentTransactions_Employees_CreatedById",
column: x => x.CreatedById,
principalTable: "Employees",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AdvancePaymentTransactions_Employees_EmployeeId",
column: x => x.EmployeeId,
principalTable: "Employees",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AdvancePaymentTransactions_Projects_ProjectId",
column: x => x.ProjectId,
principalTable: "Projects",
principalColumn: "Id");
table.ForeignKey(
name: "FK_AdvancePaymentTransactions_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "ExpenseCategoryMasters",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
NoOfPersonsRequired = table.Column<bool>(type: "tinyint(1)", nullable: false),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsAttachmentRequried = table.Column<bool>(type: "tinyint(1)", nullable: false),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_ExpenseCategoryMasters", x => x.Id);
table.ForeignKey(
name: "FK_ExpenseCategoryMasters_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "RecurringPaymentStatus",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_RecurringPaymentStatus", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "StatusUpdateLogs",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
StatusId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
NextStatusId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
EntityId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Comment = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedById = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_StatusUpdateLogs", x => x.Id);
table.ForeignKey(
name: "FK_StatusUpdateLogs_Employees_UpdatedById",
column: x => x.UpdatedById,
principalTable: "Employees",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_StatusUpdateLogs_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "RecurringPayments",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Title = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
UIDPrefix = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
UIDPostfix = table.Column<int>(type: "int", nullable: false),
Payee = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
NotifyTo = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
CurrencyId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Amount = table.Column<double>(type: "double", nullable: false),
StrikeDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
LatestPRGeneratedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
ProjectId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
PaymentBufferDays = table.Column<int>(type: "int", nullable: false),
NumberOfIteration = table.Column<int>(type: "int", nullable: false),
ExpenseCategoryId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
StatusId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Frequency = table.Column<int>(type: "int", nullable: false),
IsVariable = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatedById = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
UpdatedById = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_RecurringPayments", x => x.Id);
table.ForeignKey(
name: "FK_RecurringPayments_CurrencyMaster_CurrencyId",
column: x => x.CurrencyId,
principalTable: "CurrencyMaster",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RecurringPayments_Employees_CreatedById",
column: x => x.CreatedById,
principalTable: "Employees",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RecurringPayments_Employees_UpdatedById",
column: x => x.UpdatedById,
principalTable: "Employees",
principalColumn: "Id");
table.ForeignKey(
name: "FK_RecurringPayments_ExpenseCategoryMasters_ExpenseCategoryId",
column: x => x.ExpenseCategoryId,
principalTable: "ExpenseCategoryMasters",
principalColumn: "Id");
table.ForeignKey(
name: "FK_RecurringPayments_Projects_ProjectId",
column: x => x.ProjectId,
principalTable: "Projects",
principalColumn: "Id");
table.ForeignKey(
name: "FK_RecurringPayments_RecurringPaymentStatus_StatusId",
column: x => x.StatusId,
principalTable: "RecurringPaymentStatus",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RecurringPayments_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "PaymentRequests",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Title = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
UIDPrefix = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
UIDPostfix = table.Column<int>(type: "int", nullable: false),
Payee = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
IsAdvancePayment = table.Column<bool>(type: "tinyint(1)", nullable: false),
CurrencyId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Amount = table.Column<double>(type: "double", nullable: false),
BaseAmount = table.Column<double>(type: "double", nullable: true),
TaxAmount = table.Column<double>(type: "double", nullable: true),
TDSPercentage = table.Column<double>(type: "double", nullable: true),
DueDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
ProjectId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
RecurringPaymentId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
ExpenseCategoryId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
ExpenseStatusId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
PaidTransactionId = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PaidAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
PaidById = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
IsExpenseCreated = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatedById = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
UpdatedById = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_PaymentRequests", x => x.Id);
table.ForeignKey(
name: "FK_PaymentRequests_CurrencyMaster_CurrencyId",
column: x => x.CurrencyId,
principalTable: "CurrencyMaster",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PaymentRequests_Employees_CreatedById",
column: x => x.CreatedById,
principalTable: "Employees",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PaymentRequests_Employees_PaidById",
column: x => x.PaidById,
principalTable: "Employees",
principalColumn: "Id");
table.ForeignKey(
name: "FK_PaymentRequests_Employees_UpdatedById",
column: x => x.UpdatedById,
principalTable: "Employees",
principalColumn: "Id");
table.ForeignKey(
name: "FK_PaymentRequests_ExpenseCategoryMasters_ExpenseCategoryId",
column: x => x.ExpenseCategoryId,
principalTable: "ExpenseCategoryMasters",
principalColumn: "Id");
table.ForeignKey(
name: "FK_PaymentRequests_ExpensesStatusMaster_ExpenseStatusId",
column: x => x.ExpenseStatusId,
principalTable: "ExpensesStatusMaster",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PaymentRequests_Projects_ProjectId",
column: x => x.ProjectId,
principalTable: "Projects",
principalColumn: "Id");
table.ForeignKey(
name: "FK_PaymentRequests_RecurringPayments_RecurringPaymentId",
column: x => x.RecurringPaymentId,
principalTable: "RecurringPayments",
principalColumn: "Id");
table.ForeignKey(
name: "FK_PaymentRequests_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "PaymentRequestAttachments",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
PaymentRequestId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
DocumentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_PaymentRequestAttachments", x => x.Id);
table.ForeignKey(
name: "FK_PaymentRequestAttachments_Documents_DocumentId",
column: x => x.DocumentId,
principalTable: "Documents",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PaymentRequestAttachments_PaymentRequests_PaymentRequestId",
column: x => x.PaymentRequestId,
principalTable: "PaymentRequests",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PaymentRequestAttachments_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "ExpenseCategoryMasters",
columns: new[] { "Id", "Description", "IsActive", "IsAttachmentRequried", "Name", "NoOfPersonsRequired", "TenantId" },
values: new object[,]
{
{ new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"), "Scheduled payments for external services or goods.", true, true, "Vendor/Supplier Payments", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"), "Vehicle fuel, logistics services and delivery of goods or personnel.", true, false, "Transport", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"), "Government fees, insurance, inspections and safety-related expenditures.", true, true, "Compliance & Safety", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"), "Site setup costs including equipment deployment and temporary infrastructure.", true, true, "Mobilization", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), "Materials, equipment and supplies purchased for site operations.", true, true, "Procurement", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("77013784-9324-4d8b-bd36-d6f928e68942"), "Machinery servicing, electricity, water, and temporary office needs.", true, true, "Maintenance & Utilities", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), "Delivery of personnel.", true, false, "Travelling", true, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", true, true, "Employee Welfare", true, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }
});
migrationBuilder.UpdateData(
table: "ExpensesStatusMaster",
keyColumn: "Id",
keyValue: new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"),
column: "DisplayName",
value: "Submit for Review");
migrationBuilder.InsertData(
table: "ExpensesStatusMaster",
columns: new[] { "Id", "Color", "Description", "DisplayName", "IsActive", "IsSystem", "Name" },
values: new object[] { new Guid("b8586f67-dc19-49c3-b4af-224149efe1d3"), "#0E9F6E", "Create new Expense.", "Create Expense", true, true, "Done" });
migrationBuilder.InsertData(
table: "Features",
columns: new[] { "Id", "Description", "IsActive", "ModuleId", "Name" },
values: new object[] { new Guid("86e80017-0698-4efe-93d0-806de67266e0"), "Recurring Template Management is the automated creation and scheduling of repetitive tasks, processes, or transactions using predefined templates at set intervals to ensure consistent and efficient workflow execution without manual recreation each time.", true, new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), "Recurring Template Management" });
migrationBuilder.InsertData(
table: "Modules",
columns: new[] { "Id", "Description", "Key", "Name" },
values: new object[] { new Guid("0a79687a-86d7-430d-a2d7-8b8603cc76a1"), "Finance Module", "504ec132-e6a9-422f-8f85-050602cfce05", "Finance" });
migrationBuilder.InsertData(
table: "PaymentModeMatser",
columns: new[] { "Id", "Description", "IsActive", "Name" },
values: new object[,]
{
{ new Guid("95697409-baf6-4f78-86ab-42d93d9569a8"), "A debit card is a payment card that deducts funds directly from the cardholder's bank account when a purchase is made.", true, "Debit Card" },
{ new Guid("a820f240-5e9a-4ae9-9091-8a7aa7720cea"), "A credit card is a payment card that allows you to borrow funds from a financial institution to pay for goods and services", true, "Credit card" },
{ new Guid("f67beee6-6763-4108-922c-03bd86b9178d"), "When a bill is paid using the amount received in advance from a company.", true, "Advance Payment" }
});
migrationBuilder.InsertData(
table: "RecurringPaymentStatus",
columns: new[] { "Id", "Name" },
values: new object[,]
{
{ new Guid("306856fb-5655-42eb-bf8b-808bb5e84725"), "Completed" },
{ new Guid("3ec864d2-8bf5-42fb-ba70-5090301dd816"), "De-Activated" },
{ new Guid("8bfc9346-e092-4a80-acbf-515ae1ef6868"), "Paused" },
{ new Guid("da462422-13b2-45cc-a175-910a225f6fc8"), "Active" }
});
migrationBuilder.InsertData(
table: "ExpensesStatusMapping",
columns: new[] { "Id", "NextStatusId", "StatusId" },
values: new object[] { new Guid("a1cc95ed-b276-4a3e-9f00-0a249b522d64"), new Guid("b8586f67-dc19-49c3-b4af-224149efe1d3"), new Guid("61578360-3a49-4c34-8604-7b35a3787b95") });
migrationBuilder.InsertData(
table: "FeaturePermissions",
columns: new[] { "Id", "Description", "FeatureId", "IsEnabled", "Name" },
values: new object[,]
{
{ new Guid("6382ea8b-aff2-4cd2-a48f-a652b35825d8"), "Manage Recurring Template payment permission allows authorized users to set up, modify, and execute automated recurring payments using predefined templates, ensuring secure and controlled handling of repetitive financial transactions.", new Guid("86e80017-0698-4efe-93d0-806de67266e0"), true, "Manage Recurring" },
{ new Guid("7ddf2fba-c44d-4fe3-b4ec-690ff70be2e3"), "The \"View All Recurring Template payment permission\" generally allows users to see and access all recurring payment templates in the system, enabling them to review, manage, and process recurring transactions efficiently.", new Guid("86e80017-0698-4efe-93d0-806de67266e0"), true, "View All Recurring" },
{ new Guid("e5d21efe-573d-4a16-a0f8-414d3e442e78"), "View Self Recurring Template payment permission allows a user to view and access their own recurring payment templates without editing rights.", new Guid("86e80017-0698-4efe-93d0-806de67266e0"), true, "View Self Recurring" }
});
migrationBuilder.InsertData(
table: "StatusPermissionMapping",
columns: new[] { "Id", "PermissionId", "StatusId" },
values: new object[] { new Guid("de04b6c7-a5cd-4a61-88b0-b43b0008202e"), new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), new Guid("b8586f67-dc19-49c3-b4af-224149efe1d3") });
migrationBuilder.CreateIndex(
name: "IX_Expenses_CurrencyId",
table: "Expenses",
column: "CurrencyId");
migrationBuilder.CreateIndex(
name: "IX_Expenses_ExpenseCategoryId",
table: "Expenses",
column: "ExpenseCategoryId");
migrationBuilder.CreateIndex(
name: "IX_Expenses_PaymentRequestId",
table: "Expenses",
column: "PaymentRequestId");
migrationBuilder.CreateIndex(
name: "IX_AdvancePaymentTransactions_CreatedById",
table: "AdvancePaymentTransactions",
column: "CreatedById");
migrationBuilder.CreateIndex(
name: "IX_AdvancePaymentTransactions_EmployeeId",
table: "AdvancePaymentTransactions",
column: "EmployeeId");
migrationBuilder.CreateIndex(
name: "IX_AdvancePaymentTransactions_ProjectId",
table: "AdvancePaymentTransactions",
column: "ProjectId");
migrationBuilder.CreateIndex(
name: "IX_AdvancePaymentTransactions_TenantId",
table: "AdvancePaymentTransactions",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_ExpenseCategoryMasters_TenantId",
table: "ExpenseCategoryMasters",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequestAttachments_DocumentId",
table: "PaymentRequestAttachments",
column: "DocumentId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequestAttachments_PaymentRequestId",
table: "PaymentRequestAttachments",
column: "PaymentRequestId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequestAttachments_TenantId",
table: "PaymentRequestAttachments",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_CreatedById",
table: "PaymentRequests",
column: "CreatedById");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_CurrencyId",
table: "PaymentRequests",
column: "CurrencyId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_ExpenseCategoryId",
table: "PaymentRequests",
column: "ExpenseCategoryId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_ExpenseStatusId",
table: "PaymentRequests",
column: "ExpenseStatusId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_PaidById",
table: "PaymentRequests",
column: "PaidById");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_ProjectId",
table: "PaymentRequests",
column: "ProjectId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_RecurringPaymentId",
table: "PaymentRequests",
column: "RecurringPaymentId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_TenantId",
table: "PaymentRequests",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_PaymentRequests_UpdatedById",
table: "PaymentRequests",
column: "UpdatedById");
migrationBuilder.CreateIndex(
name: "IX_RecurringPayments_CreatedById",
table: "RecurringPayments",
column: "CreatedById");
migrationBuilder.CreateIndex(
name: "IX_RecurringPayments_CurrencyId",
table: "RecurringPayments",
column: "CurrencyId");
migrationBuilder.CreateIndex(
name: "IX_RecurringPayments_ExpenseCategoryId",
table: "RecurringPayments",
column: "ExpenseCategoryId");
migrationBuilder.CreateIndex(
name: "IX_RecurringPayments_ProjectId",
table: "RecurringPayments",
column: "ProjectId");
migrationBuilder.CreateIndex(
name: "IX_RecurringPayments_StatusId",
table: "RecurringPayments",
column: "StatusId");
migrationBuilder.CreateIndex(
name: "IX_RecurringPayments_TenantId",
table: "RecurringPayments",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_RecurringPayments_UpdatedById",
table: "RecurringPayments",
column: "UpdatedById");
migrationBuilder.CreateIndex(
name: "IX_StatusUpdateLogs_TenantId",
table: "StatusUpdateLogs",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_StatusUpdateLogs_UpdatedById",
table: "StatusUpdateLogs",
column: "UpdatedById");
migrationBuilder.AddForeignKey(
name: "FK_Expenses_CurrencyMaster_CurrencyId",
table: "Expenses",
column: "CurrencyId",
principalTable: "CurrencyMaster",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Expenses_ExpenseCategoryMasters_ExpenseCategoryId",
table: "Expenses",
column: "ExpenseCategoryId",
principalTable: "ExpenseCategoryMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Expenses_PaymentRequests_PaymentRequestId",
table: "Expenses",
column: "PaymentRequestId",
principalTable: "PaymentRequests",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Expenses_CurrencyMaster_CurrencyId",
table: "Expenses");
migrationBuilder.DropForeignKey(
name: "FK_Expenses_ExpenseCategoryMasters_ExpenseCategoryId",
table: "Expenses");
migrationBuilder.DropForeignKey(
name: "FK_Expenses_PaymentRequests_PaymentRequestId",
table: "Expenses");
migrationBuilder.DropTable(
name: "AdvancePaymentTransactions");
migrationBuilder.DropTable(
name: "PaymentRequestAttachments");
migrationBuilder.DropTable(
name: "StatusUpdateLogs");
migrationBuilder.DropTable(
name: "PaymentRequests");
migrationBuilder.DropTable(
name: "RecurringPayments");
migrationBuilder.DropTable(
name: "ExpenseCategoryMasters");
migrationBuilder.DropTable(
name: "RecurringPaymentStatus");
migrationBuilder.DropIndex(
name: "IX_Expenses_CurrencyId",
table: "Expenses");
migrationBuilder.DropIndex(
name: "IX_Expenses_ExpenseCategoryId",
table: "Expenses");
migrationBuilder.DropIndex(
name: "IX_Expenses_PaymentRequestId",
table: "Expenses");
migrationBuilder.DeleteData(
table: "ExpensesStatusMapping",
keyColumn: "Id",
keyValue: new Guid("a1cc95ed-b276-4a3e-9f00-0a249b522d64"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("6382ea8b-aff2-4cd2-a48f-a652b35825d8"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("7ddf2fba-c44d-4fe3-b4ec-690ff70be2e3"));
migrationBuilder.DeleteData(
table: "FeaturePermissions",
keyColumn: "Id",
keyValue: new Guid("e5d21efe-573d-4a16-a0f8-414d3e442e78"));
migrationBuilder.DeleteData(
table: "Modules",
keyColumn: "Id",
keyValue: new Guid("0a79687a-86d7-430d-a2d7-8b8603cc76a1"));
migrationBuilder.DeleteData(
table: "PaymentModeMatser",
keyColumn: "Id",
keyValue: new Guid("95697409-baf6-4f78-86ab-42d93d9569a8"));
migrationBuilder.DeleteData(
table: "PaymentModeMatser",
keyColumn: "Id",
keyValue: new Guid("a820f240-5e9a-4ae9-9091-8a7aa7720cea"));
migrationBuilder.DeleteData(
table: "PaymentModeMatser",
keyColumn: "Id",
keyValue: new Guid("f67beee6-6763-4108-922c-03bd86b9178d"));
migrationBuilder.DeleteData(
table: "StatusPermissionMapping",
keyColumn: "Id",
keyValue: new Guid("de04b6c7-a5cd-4a61-88b0-b43b0008202e"));
migrationBuilder.DeleteData(
table: "ExpensesStatusMaster",
keyColumn: "Id",
keyValue: new Guid("b8586f67-dc19-49c3-b4af-224149efe1d3"));
migrationBuilder.DeleteData(
table: "Features",
keyColumn: "Id",
keyValue: new Guid("86e80017-0698-4efe-93d0-806de67266e0"));
migrationBuilder.DropColumn(
name: "BaseAmount",
table: "Expenses");
migrationBuilder.DropColumn(
name: "CurrencyId",
table: "Expenses");
migrationBuilder.DropColumn(
name: "ExpenseCategoryId",
table: "Expenses");
migrationBuilder.DropColumn(
name: "PaymentRequestId",
table: "Expenses");
migrationBuilder.DropColumn(
name: "TDSPercentage",
table: "Expenses");
migrationBuilder.DropColumn(
name: "TaxAmount",
table: "Expenses");
migrationBuilder.DropColumn(
name: "UIDPostfix",
table: "Expenses");
migrationBuilder.DropColumn(
name: "UIDPrefix",
table: "Expenses");
migrationBuilder.AddColumn<Guid>(
name: "TenantId",
table: "PaymentModeMatser",
type: "char(36)",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
collation: "ascii_general_ci");
migrationBuilder.UpdateData(
table: "Expenses",
keyColumn: "ExpenseUId",
keyValue: null,
column: "ExpenseUId",
value: "");
migrationBuilder.AlterColumn<string>(
name: "ExpenseUId",
table: "Expenses",
type: "longtext",
nullable: false,
oldClrType: typeof(string),
oldType: "longtext",
oldNullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
.OldAnnotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "ExpensesStatusMaster",
keyColumn: "Id",
keyValue: new Guid("6537018f-f4e9-4cb3-a210-6c3b2da999d7"),
column: "DisplayName",
value: "Submit");
migrationBuilder.InsertData(
table: "ExpensesTypeMaster",
columns: new[] { "Id", "Description", "IsActive", "IsAttachmentRequried", "Name", "NoOfPersonsRequired", "TenantId" },
values: new object[,]
{
{ new Guid("1e2d697a-76b4-4be8-bc66-87144561a1a0"), "Scheduled payments for external services or goods.", true, true, "Vendor/Supplier Payments", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("2de53163-0dbd-404b-8e60-1b02e6b4886a"), "Vehicle fuel, logistics services and delivery of goods or personnel.", true, false, "Transport", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("4842fa61-64eb-4241-aebd-8282065af9f9"), "Government fees, insurance, inspections and safety-related expenditures.", true, true, "Compliance & Safety", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("52484820-1b54-4865-8f0f-baa2b1d339b9"), "Site setup costs including equipment deployment and temporary infrastructure.", true, true, "Mobilization", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("5e0c6227-d49d-41ff-9f1f-781f0aee2469"), "Materials, equipment and supplies purchased for site operations.", true, true, "Procurement", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("77013784-9324-4d8b-bd36-d6f928e68942"), "Machinery servicing, electricity, water, and temporary office needs.", true, true, "Maintenance & Utilities", false, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"), "Delivery of personnel.", true, false, "Travelling", true, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
{ new Guid("fc59eb90-98ea-481c-b421-54bfa9e42d8f"), " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.", true, true, "Employee Welfare", true, new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }
});
migrationBuilder.UpdateData(
table: "PaymentModeMatser",
keyColumn: "Id",
keyValue: new Guid("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"),
column: "TenantId",
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
migrationBuilder.UpdateData(
table: "PaymentModeMatser",
keyColumn: "Id",
keyValue: new Guid("2e919e94-694c-41d9-9489-0a2b4208a027"),
column: "TenantId",
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
migrationBuilder.UpdateData(
table: "PaymentModeMatser",
keyColumn: "Id",
keyValue: new Guid("48d9b462-5d87-4dec-8dec-2bc943943172"),
column: "TenantId",
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
migrationBuilder.UpdateData(
table: "PaymentModeMatser",
keyColumn: "Id",
keyValue: new Guid("ed667353-8eea-4fd1-8750-719405932480"),
column: "TenantId",
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
migrationBuilder.CreateIndex(
name: "IX_PaymentModeMatser_TenantId",
table: "PaymentModeMatser",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_Expenses_ExpensesTypeId",
table: "Expenses",
column: "ExpensesTypeId");
migrationBuilder.AddForeignKey(
name: "FK_Expenses_ExpensesTypeMaster_ExpensesTypeId",
table: "Expenses",
column: "ExpensesTypeId",
principalTable: "ExpensesTypeMaster",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_PaymentModeMatser_Tenants_TenantId",
table: "PaymentModeMatser",
column: "TenantId",
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -5,7 +5,7 @@ namespace Marco.Pms.Model.Dtos.Expenses
public class CreateExpensesDto
{
public required Guid ProjectId { get; set; }
public required Guid ExpensesTypeId { get; set; }
public required Guid ExpenseCategoryId { get; set; }
public required Guid PaymentModeId { get; set; }
public required Guid PaidById { get; set; }
public DateTime TransactionDate { get; set; } = DateTime.Now;
@ -15,6 +15,7 @@ namespace Marco.Pms.Model.Dtos.Expenses
public string? GSTNumber { get; set; }
public required string SupplerName { get; set; }
public required double Amount { get; set; }
public Guid? CurrencyId { get; set; }
public int? NoOfPersons { get; set; } = 0;
public bool PreApproved { get; set; } = false;
public required List<FileUploadModel> BillAttachments { get; set; }

View File

@ -0,0 +1,22 @@
using Marco.Pms.Model.TenantModels;
namespace Marco.Pms.Model.Dtos.Expenses
{
public class CreateRecurringTemplateDto
{
public required string Title { get; set; }
public required string Description { get; set; }
public required string Payee { get; set; }
public required string NotifyTo { get; set; }
public required Guid CurrencyId { get; set; }
public required double Amount { get; set; }
public required DateTime StrikeDate { get; set; }
public Guid? ProjectId { get; set; }
public required int PaymentBufferDays { get; set; }
public required int NumberOfIteration { get; set; }
public required Guid ExpenseCategoryId { get; set; }
public required Guid StatusId { get; set; }
public required PLAN_FREQUENCY Frequency { get; set; }
public required bool IsVariable { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using Marco.Pms.Model.Utilities;
namespace Marco.Pms.Model.Dtos.Expenses
{
public class ExpenseConversionDto
{
public required Guid PaymentRequestId { get; set; }
public required Guid PaymentModeId { get; set; }
public string? Location { get; set; }
public string? GSTNumber { get; set; }
public List<FileUploadModel>? BillAttachments { get; set; }
}
}

View File

@ -5,6 +5,9 @@
public Guid ExpenseId { get; set; }
public Guid StatusId { get; set; }
public string? Comment { get; set; }
public double? TDSPercentage { get; set; }
public double? BaseAmount { get; set; }
public double? TaxAmount { get; set; }
public string? ReimburseTransactionId { get; set; }
public DateTime? ReimburseDate { get; set; }
public Guid? ReimburseById { get; set; }

View File

@ -0,0 +1,11 @@
namespace Marco.Pms.Model.Dtos.Expenses.Masters
{
public class ExpenseCategoryMasterDto
{
public Guid? Id { get; set; }
public required string Name { get; set; }
public required bool NoOfPersonsRequired { get; set; }
public required bool IsAttachmentRequried { get; set; }
public string? Description { get; set; }
}
}

View File

@ -0,0 +1,7 @@
namespace Marco.Pms.Model.Dtos.Expenses
{
public class PaymentRequestConversionDto
{
public required List<Guid> RecurringTemplateIds { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using Marco.Pms.Model.Utilities;
namespace Marco.Pms.Model.Dtos.Expenses
{
public class PaymentRequestDto
{
public Guid? Id { get; set; }
public required string Title { get; set; }
public required string Description { get; set; }
public required string Payee { get; set; }
public required Guid CurrencyId { get; set; }
public required double Amount { get; set; }
public required DateTime DueDate { get; set; }
public Guid? ProjectId { get; set; }
public required Guid ExpenseCategoryId { get; set; }
public bool IsAdvancePayment { get; set; }
public List<FileUploadModel>? BillAttachments { get; set; }
}
}

View File

@ -0,0 +1,15 @@
namespace Marco.Pms.Model.Dtos.Expenses
{
public class PaymentRequestRecordDto
{
public Guid PaymentRequestId { get; set; }
public Guid StatusId { get; set; }
public string? Comment { get; set; }
public string? PaidTransactionId { get; set; }
public double? TDSPercentage { get; set; }
public double? BaseAmount { get; set; }
public double? TaxAmount { get; set; }
public DateTime? PaidAt { get; set; }
public Guid? PaidById { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using Marco.Pms.Model.TenantModels;
namespace Marco.Pms.Model.Dtos.Expenses
{
public class UpdateRecurringTemplateDto
{
public Guid Id { get; set; }
public required string Title { get; set; }
public required string Description { get; set; }
public required string Payee { get; set; }
public required string NotifyTo { get; set; }
public required Guid CurrencyId { get; set; }
public required double Amount { get; set; }
public Guid? ProjectId { get; set; }
public required int PaymentBufferDays { get; set; }
public required int NumberOfIteration { get; set; }
public required Guid ExpenseCategoryId { get; set; }
public required Guid StatusId { get; set; }
public required PLAN_FREQUENCY Frequency { get; set; }
public required bool IsVariable { get; set; }
}
}

View File

@ -47,6 +47,10 @@
public static readonly Guid DownloadDocument = Guid.Parse("404373d0-860f-490e-a575-1c086ffbce1d");
public static readonly Guid VerifyDocument = Guid.Parse("13a1f30f-38d1-41bf-8e7a-b75189aab8e0");
public static readonly Guid ManageRecurring = Guid.Parse("6382ea8b-aff2-4cd2-a48f-a652b35825d8");
public static readonly Guid ViewAllRecurring = Guid.Parse("7ddf2fba-c44d-4fe3-b4ec-690ff70be2e3");
public static readonly Guid ViewSelfRecurring = Guid.Parse("e5d21efe-573d-4a16-a0f8-414d3e442e78");
public static readonly Guid CollectionAdmin = Guid.Parse("dbf17591-09fe-4c93-9e1a-12db8f5cc5de");
public static readonly Guid ViewCollection = Guid.Parse("c8d7eea5-4033-4aad-9ebe-76de49896830");
public static readonly Guid CreateCollection = Guid.Parse("b93141fd-dbd3-4051-8f57-bf25d18e3555");

View File

@ -0,0 +1,36 @@
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.Expenses
{
public class AdvancePaymentTransaction : TenantRelation
{
public Guid Id { get; set; }
public string FinanceUIdPrefix { get; set; } = default!;
public int FinanceUIdPostfix { get; set; }
public string Title { get; set; } = default!;
public Guid? ProjectId { get; set; }
[ValidateNever]
[ForeignKey("ProjectId")]
public Project? Project { get; set; }
public Guid EmployeeId { get; set; }
[ValidateNever]
[ForeignKey("EmployeeId")]
public Employee? Employee { get; set; }
public double Amount { get; set; }
public double CurrentBalance { get; set; }
public DateTime PaidAt { get; set; }
public DateTime CreatedAt { get; set; }
public Guid CreatedById { get; set; }
[ValidateNever]
[ForeignKey("CreatedById")]
public Employee? CreatedBy { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities;
@ -10,6 +11,8 @@ namespace Marco.Pms.Model.Expenses
public class Expenses : TenantRelation
{
public Guid Id { get; set; }
public string UIDPrefix { get; set; } = default!;
public int UIDPostfix { get; set; }
public Guid ProjectId { get; set; }
[ValidateNever]
@ -17,9 +20,15 @@ namespace Marco.Pms.Model.Expenses
public Project? Project { get; set; }
public Guid ExpensesTypeId { get; set; }
//[ValidateNever]
//[ForeignKey("ExpensesTypeId")]
//public ExpensesTypeMaster? ExpensesType { get; set; }
public Guid ExpenseCategoryId { get; set; }
[ValidateNever]
[ForeignKey("ExpensesTypeId")]
public ExpensesTypeMaster? ExpensesType { get; set; }
[ForeignKey("ExpenseCategoryId")]
public ExpenseCategoryMaster? ExpenseCategory { get; set; }
public Guid PaymentModeId { get; set; }
[ValidateNever]
@ -54,12 +63,25 @@ namespace Marco.Pms.Model.Expenses
public DateTime CreatedAt { get; set; }
public string? TransactionId { get; set; }
public string Description { get; set; } = string.Empty;
public string ExpenseUId { get; set; } = string.Empty;
public string? ExpenseUId { get; set; }
public string? Location { get; set; }
public string? GSTNumber { get; set; }
public string SupplerName { get; set; } = string.Empty;
public Guid CurrencyId { get; set; }
[ValidateNever]
[ForeignKey("CurrencyId")]
public CurrencyMaster? Currency { get; set; }
public double Amount { get; set; }
public double? BaseAmount { get; set; }
public double? TaxAmount { get; set; }
public double? TDSPercentage { get; set; }
public int? NoOfPersons { get; set; }
public Guid? PaymentRequestId { get; set; }
[ValidateNever]
[ForeignKey("PaymentRequestId")]
public PaymentRequest? PaymentRequest { get; set; }
public Guid StatusId { get; set; }
[ValidateNever]

View File

@ -0,0 +1,14 @@
using Marco.Pms.Model.Utilities;
namespace Marco.Pms.Model.Expenses.Masters
{
public class ExpenseCategoryMaster : TenantRelation
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public bool NoOfPersonsRequired { get; set; }
public string Description { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
public bool IsAttachmentRequried { get; set; } = true;
}
}

View File

@ -2,7 +2,7 @@
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.Expenses
namespace Marco.Pms.Model.Expenses.Masters
{
public class ExpensesStatusMapping
{

View File

@ -0,0 +1,8 @@
namespace Marco.Pms.Model.Expenses.Masters
{
public class RecurringPaymentStatus
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
}
}

View File

@ -3,7 +3,7 @@ using Marco.Pms.Model.Master;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.Expenses
namespace Marco.Pms.Model.Expenses.Masters
{
public class StatusPermissionMapping
{

View File

@ -0,0 +1,72 @@
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.Expenses
{
public class PaymentRequest : TenantRelation
{
public Guid Id { get; set; }
public string Title { get; set; } = default!;
public string Description { get; set; } = default!;
public string UIDPrefix { get; set; } = default!;
public int UIDPostfix { get; set; }
public string Payee { get; set; } = default!;
public bool IsAdvancePayment { get; set; }
public Guid CurrencyId { get; set; }
[ValidateNever]
[ForeignKey("CurrencyId")]
public CurrencyMaster? Currency { get; set; }
public double Amount { get; set; }
public double? BaseAmount { get; set; }
public double? TaxAmount { get; set; }
public double? TDSPercentage { get; set; }
public DateTime DueDate { get; set; }
public Guid? ProjectId { get; set; }
[ValidateNever]
[ForeignKey("ProjectId")]
public Project? Project { get; set; }
public Guid? RecurringPaymentId { get; set; }
[ValidateNever]
[ForeignKey("RecurringPaymentId")]
public RecurringPayment? RecurringPayment { get; set; }
public Guid? ExpenseCategoryId { get; set; }
[ValidateNever]
[ForeignKey("ExpenseCategoryId")]
public ExpenseCategoryMaster? ExpenseCategory { get; set; }
public Guid ExpenseStatusId { get; set; }
[ValidateNever]
[ForeignKey("ExpenseStatusId")]
public ExpensesStatusMaster? ExpenseStatus { get; set; }
public string? PaidTransactionId { get; set; }
public DateTime? PaidAt { get; set; }
public Guid? PaidById { get; set; }
[ValidateNever]
[ForeignKey("PaidById")]
public Employee? PaidBy { get; set; }
public bool IsExpenseCreated { get; set; } = false;
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public Guid CreatedById { get; set; }
[ValidateNever]
[ForeignKey("CreatedById")]
public Employee? CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public Guid? UpdatedById { get; set; }
[ValidateNever]
[ForeignKey("UpdatedById")]
public Employee? UpdatedBy { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using Marco.Pms.Model.DocumentManager;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.Expenses
{
public class PaymentRequestAttachment : TenantRelation
{
public Guid Id { get; set; }
public Guid PaymentRequestId { get; set; }
[ValidateNever]
[ForeignKey("PaymentRequestId")]
public PaymentRequest? PaymentRequest { get; set; }
public Guid DocumentId { get; set; }
[ValidateNever]
[ForeignKey("DocumentId")]
public Document? Document { get; set; }
}
}

View File

@ -0,0 +1,62 @@
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.Projects;
using Marco.Pms.Model.TenantModels;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.Expenses
{
public class RecurringPayment : TenantRelation
{
public Guid Id { get; set; }
public string Title { get; set; } = default!;
public string Description { get; set; } = default!;
public string UIDPrefix { get; set; } = default!;
public int UIDPostfix { get; set; }
public string Payee { get; set; } = default!;
public string NotifyTo { get; set; } = default!;
public Guid CurrencyId { get; set; }
[ValidateNever]
[ForeignKey("CurrencyId")]
public CurrencyMaster? Currency { get; set; }
public double Amount { get; set; }
public DateTime StrikeDate { get; set; }
public DateTime? LatestPRGeneratedAt { get; set; }
public Guid? ProjectId { get; set; }
[ValidateNever]
[ForeignKey("ProjectId")]
public Project? Project { get; set; }
public int PaymentBufferDays { get; set; }
public int NumberOfIteration { get; set; }
public Guid? ExpenseCategoryId { get; set; }
[ValidateNever]
[ForeignKey("ExpenseCategoryId")]
public ExpenseCategoryMaster? ExpenseCategory { get; set; }
public Guid StatusId { get; set; }
[ValidateNever]
[ForeignKey("StatusId")]
public RecurringPaymentStatus? Status { get; set; }
public PLAN_FREQUENCY Frequency { get; set; }
public bool IsVariable { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public Guid CreatedById { get; set; }
[ValidateNever]
[ForeignKey("CreatedById")]
public Employee? CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public Guid? UpdatedById { get; set; }
[ValidateNever]
[ForeignKey("UpdatedById")]
public Employee? UpdatedBy { get; set; }
}
}

View File

@ -6,6 +6,7 @@
public List<Guid>? StatusIds { get; set; }
public List<Guid>? CreatedByIds { get; set; }
public List<Guid>? PaidById { get; set; }
public List<Guid>? ExpenseCategoryIds { get; set; }
public bool IsTransactionDate { get; set; } = false;
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }

View File

@ -0,0 +1,14 @@
namespace Marco.Pms.Model.Filters
{
public class PaymentRequestFilter
{
public List<Guid>? ProjectIds { get; set; }
public List<Guid>? StatusIds { get; set; }
public List<Guid>? CreatedByIds { get; set; }
public List<Guid>? CurrencyIds { get; set; }
public List<Guid>? ExpenseCategoryIds { get; set; }
public List<string>? Payees { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
}

View File

@ -0,0 +1,14 @@
namespace Marco.Pms.Model.Filters
{
public class RecurringPaymentFilter
{
public List<Guid>? ProjectIds { get; set; }
public List<Guid>? StatusIds { get; set; }
public List<Guid>? CreatedByIds { get; set; }
public List<Guid>? CurrencyIds { get; set; }
public List<Guid>? ExpenseCategoryIds { get; set; }
public List<string>? Payees { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
}

View File

@ -1,8 +1,6 @@
using Marco.Pms.Model.Utilities;
namespace Marco.Pms.Model.Master
namespace Marco.Pms.Model.Master
{
public class PaymentModeMatser : TenantRelation
public class PaymentModeMatser
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;

View File

@ -0,0 +1,22 @@
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Utilities;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.Master
{
public class StatusUpdateLog : TenantRelation
{
public Guid Id { get; set; }
public Guid StatusId { get; set; }
public Guid NextStatusId { get; set; }
public Guid EntityId { get; set; }
public string? Comment { get; set; }
public DateTime UpdatedAt { get; set; }
public Guid UpdatedById { get; set; }
[ValidateNever]
[ForeignKey("UpdatedById")]
public Employee? UpdatedBy { get; set; }
}
}

View File

@ -7,5 +7,6 @@
public string ContentType { get; set; } = string.Empty;
public string S3Key { get; set; } = string.Empty;
public string ThumbS3Key { get; set; } = string.Empty;
public long FileSize { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using Marco.Pms.Model.MongoDBModels.Employees;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.MongoDBModels.Employees;
using Marco.Pms.Model.MongoDBModels.Masters;
using Marco.Pms.Model.MongoDBModels.Project;
@ -8,7 +9,7 @@ namespace Marco.Pms.Model.MongoDBModels.Expenses
{
public string Id { get; set; } = string.Empty;
public ProjectBasicMongoDB Project { get; set; } = new ProjectBasicMongoDB();
public ExpensesTypeMasterMongoDB ExpensesType { get; set; } = new ExpensesTypeMasterMongoDB();
public ExpenseCategoryMasterMongoDB ExpenseCategory { get; set; } = new ExpenseCategoryMasterMongoDB();
public PaymentModeMatserMongoDB PaymentMode { get; set; } = new PaymentModeMatserMongoDB();
public BasicEmployeeMongoDB PaidBy { get; set; } = new BasicEmployeeMongoDB();
public BasicEmployeeMongoDB CreatedBy { get; set; } = new BasicEmployeeMongoDB();
@ -19,8 +20,12 @@ namespace Marco.Pms.Model.MongoDBModels.Expenses
public DateTime CreatedAt { get; set; }
public DateTime ExpireAt { get; set; } = DateTime.UtcNow.Date.AddDays(1);
public string SupplerName { get; set; } = string.Empty;
public string? ExpenseUId { get; set; }
public double Amount { get; set; }
public CurrencyMaster? Currency { get; set; }
public double? BaseAmount { get; set; }
public double? TaxAmount { get; set; }
public string? PaymentRequestUID { get; set; }
public string? ExpenseUId { get; set; }
public ExpensesStatusMasterMongoDB Status { get; set; } = new ExpensesStatusMasterMongoDB();
public List<ExpensesStatusMasterMongoDB> NextStatus { get; set; } = new List<ExpensesStatusMasterMongoDB>();
public bool PreApproved { get; set; } = false;

View File

@ -0,0 +1,11 @@
namespace Marco.Pms.Model.MongoDBModels.Masters
{
public class ExpenseCategoryMasterMongoDB
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public bool NoOfPersonsRequired { get; set; }
public string Description { get; set; } = string.Empty;
public string TenantId { get; set; } = string.Empty;
}
}

View File

@ -10,6 +10,6 @@
public enum PLAN_FREQUENCY
{
MONTHLY = 0, QUARTERLY = 1, HALF_YEARLY = 2, YEARLY = 3
MONTHLY = 0, QUARTERLY = 1, HALF_YEARLY = 2, YEARLY = 3, DAILY = 4, WEEKLY = 5
}
}

View File

@ -0,0 +1,21 @@
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Projects;
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class AdvancePaymentTransactionVM
{
public Guid Id { get; set; }
public string? FinanceUId { get; set; }
public string? Title { get; set; }
public BasicProjectVM? Project { get; set; }
public BasicEmployeeVM? Employee { get; set; }
public double Amount { get; set; }
public double CurrentBalance { get; set; }
public DateTime PaidAt { get; set; }
public DateTime CreatedAt { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class BasicPaymentRequestVM
{
public Guid Id { get; set; }
public string? PaymentRequestUID { get; set; }
public double Amount { get; set; }
}
}

View File

@ -0,0 +1,10 @@
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class BasicRecurringPaymentVM
{
public Guid Id { get; set; }
public string? RecurringPaymentUID { get; set; }
public double Amount { get; set; }
public bool IsVariable { get; set; }
}
}

View File

@ -1,4 +1,6 @@
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Expenses.Masters;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Model.ViewModels.Projects;
@ -8,20 +10,21 @@ namespace Marco.Pms.Model.ViewModels.Expanses
{
public Guid Id { get; set; }
public ProjectInfoVM? Project { get; set; }
public ExpensesTypeMasterVM? ExpensesType { get; set; }
public ExpenseCategoryMasterVM? ExpenseCategory { get; set; }
public PaymentModeMatserVM? PaymentMode { get; set; }
public BasicEmployeeVM? PaidBy { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; }
//public BasicEmployeeVM? ReviewedBy { get; set; }
//public BasicEmployeeVM? ApprovedBy { get; set; }
//public BasicEmployeeVM? ProcessedBy { get; set; }
public DateTime TransactionDate { get; set; }
public DateTime CreatedAt { get; set; }
public string SupplerName { get; set; } = string.Empty;
public string? ExpenseUId { get; set; }
public string? PaymentRequestUID { get; set; }
public string Description { get; set; } = string.Empty;
public string TransactionId { get; set; } = string.Empty;
public double Amount { get; set; }
public CurrencyMaster? Currency { get; set; }
public double? BaseAmount { get; set; }
public double? TaxAmount { get; set; }
public ExpensesStatusMasterVM? Status { get; set; }
public List<ExpensesStatusMasterVM>? NextStatus { get; set; }
public bool PreApproved { get; set; } = false;

View File

@ -0,0 +1,11 @@
namespace Marco.Pms.Model.ViewModels.Expenses.Masters
{
public class ExpenseCategoryMasterVM
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public bool NoOfPersonsRequired { get; set; }
public bool IsAttachmentRequried { get; set; }
public string Description { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,12 @@
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class PaymentRequestAttachmentVM
{
public Guid Id { get; set; }
public string? FileName { get; set; }
public string? Url { get; set; }
public string? ThumbUrl { get; set; }
public long FileSize { get; set; }
public string? ContentType { get; set; }
}
}

View File

@ -0,0 +1,39 @@
using Marco.Pms.Model.Master;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Expenses.Masters;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Model.ViewModels.Projects;
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class PaymentRequestDetailsVM
{
public Guid Id { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public string? PaymentRequestUID { get; set; }
public string? Payee { get; set; }
public CurrencyMaster? Currency { get; set; }
public double Amount { get; set; }
public double? BaseAmount { get; set; }
public double? TaxAmount { get; set; }
public DateTime DueDate { get; set; }
public BasicProjectVM? Project { get; set; }
public BasicRecurringPaymentVM? RecurringPayment { get; set; }
public ExpenseCategoryMasterVM? ExpenseCategory { get; set; }
public ExpensesStatusMasterVM? ExpenseStatus { get; set; }
public string? PaidTransactionId { get; set; }
public DateTime? PaidAt { get; set; }
public BasicEmployeeVM? PaidBy { get; set; }
public bool IsAdvancePayment { get; set; }
public DateTime CreatedAt { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; }
public DateTime UpdatedAt { get; set; }
public BasicEmployeeVM? UpdatedBy { get; set; }
public List<ExpensesStatusMasterVM>? NextStatus { get; set; }
public List<PaymentRequestUpdateLog>? UpdateLogs { get; set; }
public List<PaymentRequestAttachmentVM>? Attachments { get; set; }
public bool IsActive { get; set; }
public bool IsExpenseCreated { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Master;
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class PaymentRequestUpdateLog
{
public Guid Id { get; set; }
public ExpensesStatusMasterVM? Status { get; set; }
public ExpensesStatusMasterVM? NextStatus { get; set; }
public string? Comment { get; set; }
public DateTime UpdatedAt { get; set; }
public BasicEmployeeVM? UpdatedBy { get; set; }
}
}

View File

@ -0,0 +1,29 @@
using Marco.Pms.Model.Master;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Expenses.Masters;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Model.ViewModels.Projects;
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class PaymentRequestVM
{
public Guid Id { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public BasicRecurringPaymentVM? RecurringPayment { get; set; }
public string? PaymentRequestUID { get; set; }
public string? Payee { get; set; }
public CurrencyMaster? Currency { get; set; }
public double Amount { get; set; }
public DateTime DueDate { get; set; }
public BasicProjectVM? Project { get; set; }
public ExpenseCategoryMasterVM? ExpenseCategory { get; set; }
public ExpensesStatusMasterVM? ExpenseStatus { get; set; }
public bool IsAdvancePayment { get; set; }
public DateTime CreatedAt { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; }
public bool IsActive { get; set; }
public bool IsExpenseCreated { get; set; }
}
}

View File

@ -0,0 +1,36 @@
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.TenantModels;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Expenses.Masters;
using Marco.Pms.Model.ViewModels.Projects;
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class RecurringPaymentDetailsVM
{
public Guid Id { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public string? RecurringPaymentUID { get; set; }
public string? Payee { get; set; }
public List<BasicEmployeeVM>? NotifyTo { get; set; }
public CurrencyMaster? Currency { get; set; }
public double Amount { get; set; }
public DateTime StrikeDate { get; set; }
public DateTime? LatestPRGeneratedAt { get; set; }
public BasicProjectVM? Project { get; set; }
public int PaymentBufferDays { get; set; }
public int NumberOfIteration { get; set; }
public List<BasicPaymentRequestVM>? PaymentRequests { get; set; }
public ExpenseCategoryMasterVM? ExpenseCategory { get; set; }
public RecurringPaymentStatus? Status { get; set; }
public PLAN_FREQUENCY Frequency { get; set; }
public bool IsVariable { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public BasicEmployeeVM? UpdatedBy { get; set; }
}
}

View File

@ -0,0 +1,33 @@
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.TenantModels;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Expenses.Masters;
using Marco.Pms.Model.ViewModels.Projects;
namespace Marco.Pms.Model.ViewModels.Expenses
{
public class RecurringPaymentVM
{
public Guid Id { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public string? RecurringPaymentUId { get; set; }
public string? Payee { get; set; }
public string? NotifyTo { get; set; }
public CurrencyMaster? Currency { get; set; }
public double Amount { get; set; }
public DateTime StrikeDate { get; set; }
public DateTime? LatestPRGeneratedAt { get; set; }
public BasicProjectVM? Project { get; set; }
public int PaymentBufferDays { get; set; }
public int NumberOfIteration { get; set; }
public ExpenseCategoryMasterVM? ExpenseCategory { get; set; }
public RecurringPaymentStatus? Status { get; set; }
public PLAN_FREQUENCY Frequency { get; set; }
public bool IsVariable { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; }
}
}

View File

@ -60,7 +60,7 @@ namespace MarcoBMS.Services.Controllers
{
var user = await _context.ApplicationUsers
.FirstOrDefaultAsync(u => u.Email == loginDto.Username || u.PhoneNumber == loginDto.Username);
.FirstOrDefaultAsync(u => u.Email == loginDto.Username || u.UserName == loginDto.Username);
if (user == null)
{
@ -104,9 +104,13 @@ namespace MarcoBMS.Services.Controllers
return NotFound(ApiResponse<object>.ErrorResponse("Username not found", "Username not found", 404));
}
var tenants = await _context.Tenants.Where(t => t.OrganizationId == emp.OrganizationId).ToListAsync();
var tenant = tenants.OrderBy(t => t.OnBoardingDate).FirstOrDefault();
// Generate tokens
var token = _refreshTokenService.GenerateJwtToken(user.UserName, emp.TenantId ?? Guid.Empty, emp.OrganizationId, _jwtSettings);
var refreshToken = await _refreshTokenService.CreateRefreshToken(user.Id, emp.TenantId.ToString(), emp.OrganizationId, _jwtSettings);
var token = _refreshTokenService.GenerateJwtToken(user.UserName, tenant?.Id ?? Guid.Empty, emp.OrganizationId, _jwtSettings);
var refreshToken = await _refreshTokenService.CreateRefreshToken(user.Id, tenant?.Id.ToString(), emp.OrganizationId, _jwtSettings);
_logger.LogInfo("User login successful - UserId: {UserId}", user.Id);
return Ok(ApiResponse<object>.SuccessResponse(new
@ -202,12 +206,17 @@ namespace MarcoBMS.Services.Controllers
}
_logger.LogInfo("Successfully found employee details for tenant ID: {TenantId}", emp.TenantId ?? Guid.Empty);
var tenants = await _context.Tenants.Where(t => t.OrganizationId == emp.OrganizationId).ToListAsync();
var tenant = tenants.OrderBy(t => t.OnBoardingDate).FirstOrDefault();
// Generate JWT token
var token = _refreshTokenService.GenerateJwtToken(user.UserName, emp.TenantId ?? Guid.Empty, emp.OrganizationId, _jwtSettings);
var token = _refreshTokenService.GenerateJwtToken(user.UserName, tenant?.Id ?? Guid.Empty, emp.OrganizationId, _jwtSettings);
// Generate a new refresh token and store it in the database.
_logger.LogInfo("Generating and storing Refresh Token for user: {Username}", user.UserName);
var refreshToken = await _refreshTokenService.CreateRefreshToken(user.Id, emp.TenantId.ToString(), emp.OrganizationId, _jwtSettings);
var refreshToken = await _refreshTokenService.CreateRefreshToken(user.Id, tenant?.Id.ToString(), emp.OrganizationId, _jwtSettings);
// Fetch MPIN Token
var mpinToken = await _context.MPINDetails.FirstOrDefaultAsync(p => p.UserId == Guid.Parse(user.Id));
@ -265,31 +274,32 @@ namespace MarcoBMS.Services.Controllers
}
string? tokenType = claimsPrincipal.FindFirst("token_type")?.Value;
string? tokenTenantId = claimsPrincipal.FindFirst("TenantId")?.Value;
string? tokenUserId = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
// Validate essential claims
if (string.IsNullOrWhiteSpace(tokenType) || string.IsNullOrWhiteSpace(tokenTenantId) || string.IsNullOrWhiteSpace(tokenUserId))
if (string.IsNullOrWhiteSpace(tokenType) || string.IsNullOrWhiteSpace(tokenUserId))
{
_logger.LogWarning("MPIN token claims are incomplete");
return Unauthorized(ApiResponse<object>.ErrorResponse("Invalid token claims", "MPIN token does not match your identity", 401));
}
Guid tenantId = Guid.Parse(tokenTenantId);
// Fetch employee by ID and tenant
var requestEmployee = await _context.Employees
.Include(e => e.ApplicationUser)
.FirstOrDefaultAsync(e => e.Id == verifyMPIN.EmployeeId && e.TenantId == tenantId && e.ApplicationUserId == tokenUserId && e.IsActive);
.FirstOrDefaultAsync(e => e.Id == verifyMPIN.EmployeeId && e.HasApplicationAccess && e.ApplicationUserId == tokenUserId && e.IsActive);
if (requestEmployee == null || string.IsNullOrWhiteSpace(requestEmployee.ApplicationUserId))
{
_logger.LogWarning("Employee not found or invalid for verification - EmployeeId: {EmployeeId}", verifyMPIN.EmployeeId);
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request", "Provided invalid employee information", 400));
}
var tenants = await _context.Tenants.Where(t => t.OrganizationId == requestEmployee.OrganizationId).ToListAsync();
var tenant = tenants.OrderBy(t => t.OnBoardingDate).FirstOrDefault();
Guid tenantId = tenant?.Id ?? Guid.Empty;
// Validate that the token belongs to the same employee making the request
if (requestEmployee.ApplicationUserId != tokenUserId || tokenType != "mpin")
if (requestEmployee.ApplicationUserId != tokenUserId || tokenType != "mpin" || tenantId == Guid.Empty)
{
_logger.LogWarning("Token identity does not match employee info - EmployeeId: {EmployeeId}", requestEmployee.Id);
return Unauthorized(ApiResponse<object>.ErrorResponse("Unauthorized", "MPIN token does not match your identity", 401));
@ -402,7 +412,9 @@ namespace MarcoBMS.Services.Controllers
//var accessToken = _refreshTokenService.GenerateJwtTokenWithOrganization(requestEmployee.ApplicationUser?.UserName, requestEmployee.OrganizationId, _jwtSettings);
//var refreshToken = await _refreshTokenService.CreateRefreshTokenWithOrganization(requestEmployee.ApplicationUserId, requestEmployee.OrganizationId, _jwtSettings);
var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.OrganizationId == requestEmployee.OrganizationId);
var tenants = await _context.Tenants.Where(t => t.OrganizationId == requestEmployee.OrganizationId).ToListAsync();
var tenant = tenants.OrderBy(t => t.OnBoardingDate).FirstOrDefault();
var accessToken = _refreshTokenService.GenerateJwtToken(requestEmployee.ApplicationUser?.UserName,
tenant?.Id ?? Guid.Empty, requestEmployee.OrganizationId, _jwtSettings);

View File

@ -772,7 +772,7 @@ namespace Marco.Pms.Services.Controllers
baseQuery = baseQuery.Where(e => e.ProjectId == projectId);
if (categoryId.HasValue)
baseQuery = baseQuery.Where(e => e.ExpensesTypeId == categoryId);
baseQuery = baseQuery.Where(e => e.ExpenseCategoryId == categoryId);
// Single server-side group/aggregate by project
var report = await baseQuery
@ -851,10 +851,10 @@ namespace Marco.Pms.Services.Controllers
// Project to a minimal shape before grouping to avoid loading navigation graphs
// Group by expense type name; adjust to the correct key if ExpensesCategory is an enum or navigation
var query = baseQuery
.Where(e => e.ExpensesType != null)
.Where(e => e.ExpenseCategory != null)
.Select(e => new
{
ExpenseTypeName = e.ExpensesType!.Name, // If enum, use e.ExpensesCategory.ToString()
ExpenseTypeName = e.ExpenseCategory!.Name, // If enum, use e.ExpensesCategory.ToString()
Amount = e.Amount,
StatusId = e.StatusId
})

View File

@ -1,5 +1,4 @@
using Marco.Pms.Model.Dtos.Expenses;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Helpers;
using Microsoft.AspNetCore.Authorization;
@ -29,6 +28,7 @@ namespace Marco.Pms.Services.Controllers
tenantId = userHelper.GetTenantId();
}
#region =================================================================== Expense Functions ===================================================================
/// <summary>
/// Retrieves a paginated list of expenses based on user permissions and optional filters.
@ -46,11 +46,11 @@ namespace Marco.Pms.Services.Controllers
return StatusCode(response.StatusCode, response);
}
[HttpGet("details/{id}")]
public async Task<IActionResult> GetExpenseDetails(Guid id)
[HttpGet("details/{id?}")]
public async Task<IActionResult> GetExpenseDetails(Guid? id, [FromQuery] string? expenseUId)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _expensesService.GetExpenseDetailsAsync(id, loggedInEmployee, tenantId);
var response = await _expensesService.GetExpenseDetailsAsync(id, expenseUId, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
@ -122,5 +122,7 @@ namespace Marco.Pms.Services.Controllers
return StatusCode(response.StatusCode, response);
}
#endregion
}
}

View File

@ -2,6 +2,7 @@
using Marco.Pms.Model.Dtos.Activities;
using Marco.Pms.Model.Dtos.Collection;
using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Dtos.Expenses.Masters;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Forum;
using Marco.Pms.Model.Mapper;
@ -37,6 +38,30 @@ namespace Marco.Pms.Services.Controllers
tenantId = userHelper.GetTenantId();
}
#region =================================================================== Recurring Payment Status APIs ===================================================================
[HttpGet("recurring-status/list")]
public async Task<IActionResult> GetRecurringPaymentStatus()
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.GetRecurringPaymentStatusAsync(loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Currency APIs ===================================================================
[HttpGet("currencies/list")]
public async Task<IActionResult> GetCurrency()
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.GetCurrencyAsync(loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Organization Type APIs ===================================================================
[HttpGet("organization-type/list")]
@ -821,37 +846,37 @@ namespace Marco.Pms.Services.Controllers
}
#endregion
#region =================================================================== Expenses Type APIs ===================================================================
#region =================================================================== Expenses Category APIs ===================================================================
[HttpGet("expenses-types")]
public async Task<IActionResult> GetExpenseTypeList([FromQuery] bool isActive = true)
[HttpGet("expenses-categories")]
public async Task<IActionResult> GetExpenseCategoryList([FromQuery] bool isActive = true)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.GetExpenseTypeListAsync(loggedInEmployee, tenantId, isActive);
var response = await _masterService.GetExpenseCategoryListAsync(loggedInEmployee, tenantId, isActive);
return StatusCode(response.StatusCode, response);
}
[HttpPost("expenses-type")]
public async Task<IActionResult> CreateExpenseType([FromBody] ExpensesTypeMasterDto dto)
[HttpPost("expenses-category")]
public async Task<IActionResult> CreateExpenseCategory([FromBody] ExpenseCategoryMasterDto dto)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.CreateExpenseTypeAsync(dto, loggedInEmployee, tenantId);
var response = await _masterService.CreateExpenseCategoryAsync(dto, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpPut("expenses-type/edit/{id}")]
public async Task<IActionResult> UpdateExpenseType(Guid id, [FromBody] ExpensesTypeMasterDto dto)
[HttpPut("expenses-category/edit/{id}")]
public async Task<IActionResult> UpdateExpenseCategory(Guid id, [FromBody] ExpenseCategoryMasterDto dto)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.UpdateExpenseTypeAsync(id, dto, loggedInEmployee, tenantId);
var response = await _masterService.UpdateExpenseCategoryAsync(id, dto, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpDelete("expenses-type/delete/{id}")]
public async Task<IActionResult> DeleteExpenseType(Guid id, [FromQuery] bool isActive = false)
[HttpDelete("expenses-category/delete/{id}")]
public async Task<IActionResult> DeleteExpenseCategory(Guid id, [FromQuery] bool isActive = false)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.DeleteExpenseTypeAsync(id, isActive, loggedInEmployee, tenantId);
var response = await _masterService.DeleteExpenseCategoryAsync(id, isActive, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}

View File

@ -1202,11 +1202,9 @@ namespace Marco.Pms.Services.Controllers
}
if (features.Modules?.Expense?.Enabled ?? false)
{
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
var paymentModeMatser = _masteData.GetPaymentModesData(tenant.Id);
var expenseCategoryMaster = _masteData.GetExpenseCategoryData(tenant.Id);
_context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
_context.PaymentModeMatser.AddRange(paymentModeMatser);
_context.ExpenseCategoryMasters.AddRange(expenseCategoryMaster);
}
await _context.SaveChangesAsync();
@ -1535,33 +1533,14 @@ namespace Marco.Pms.Services.Controllers
}
if (features.Modules?.Expense?.Enabled ?? false)
{
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
var paymentModeMatser = _masteData.GetPaymentModesData(tenant.Id);
var expenseCategoryMaster = _masteData.GetExpenseCategoryData(tenant.Id);
var expensesTypeTask = Task.Run(async () =>
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
var expensesTypeNames = expensesTypeMaster.Select(et => et.Name).ToList();
return await _context.ExpensesTypeMaster.AnyAsync(et => expensesTypeNames.Contains(et.Name) && et.TenantId == tenant.Id);
});
var paymentModeTask = Task.Run(async () =>
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
var paymentModeNames = paymentModeMatser.Select(py => py.Name).ToList();
return await _context.PaymentModeMatser.AnyAsync(py => paymentModeNames.Contains(py.Name) && py.TenantId == tenant.Id);
});
var expenseCategoryNames = expenseCategoryMaster.Select(et => et.Name).ToList();
var expenseCategoryExist = await context.ExpensesTypeMaster.AnyAsync(et => expenseCategoryNames.Contains(et.Name) && et.TenantId == tenant.Id);
await Task.WhenAll(expensesTypeTask, paymentModeTask);
var expensesTypeExist = expensesTypeTask.Result;
var paymentModeExist = paymentModeTask.Result;
if (!expensesTypeExist)
if (!expenseCategoryExist)
{
context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
}
if (!paymentModeExist)
{
context.PaymentModeMatser.AddRange(paymentModeMatser);
context.ExpenseCategoryMasters.AddRange(expenseCategoryMaster);
}
}

View File

@ -1154,7 +1154,7 @@ namespace Marco.Pms.Services.Helpers
var expenseIds = model.Select(m => m.Id).ToList();
var projectIds = model.Select(m => m.ProjectId).ToList();
var statusIds = model.Select(m => m.StatusId).ToList();
var expensesTypeIds = model.Select(m => m.ExpensesTypeId).ToList();
var expenseCategoryIds = model.Select(m => m.ExpenseCategoryId).ToList();
var paymentModeIds = model.Select(m => m.PaymentModeId).ToList();
var createdByIds = model.Select(m => m.CreatedById).ToList();
var reviewedByIds = model.Select(m => m.ReviewedById).ToList();
@ -1192,15 +1192,15 @@ namespace Marco.Pms.Services.Helpers
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().Where(e => processedByIds.Contains(e.Id) && e.TenantId == tenantId).ToListAsync();
});
var expenseTypeTask = Task.Run(async () =>
var expenseCategoryTask = Task.Run(async () =>
{
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.ExpensesTypeMaster.AsNoTracking().Where(et => expensesTypeIds.Contains(et.Id) && et.TenantId == tenantId).ToListAsync();
return await dbContext.ExpenseCategoryMasters.AsNoTracking().Where(et => expenseCategoryIds.Contains(et.Id) && et.TenantId == tenantId).ToListAsync();
});
var paymentModeTask = Task.Run(async () =>
{
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.PaymentModeMatser.AsNoTracking().Where(pm => paymentModeIds.Contains(pm.Id) && pm.TenantId == tenantId).ToListAsync();
return await dbContext.PaymentModeMatser.AsNoTracking().Where(pm => paymentModeIds.Contains(pm.Id)).ToListAsync();
});
var statusMappingTask = Task.Run(async () =>
{
@ -1250,11 +1250,11 @@ namespace Marco.Pms.Services.Helpers
});
// Await all prerequisite checks at once.
await Task.WhenAll(projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, reviewedByTask, approvedByTask,
await Task.WhenAll(projectTask, expenseCategoryTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, reviewedByTask, approvedByTask,
processedByTask, statusTask, billAttachmentsTask);
var projects = projectTask.Result;
var expenseTypes = expenseTypeTask.Result;
var expenseCategories = expenseCategoryTask.Result;
var paymentModes = paymentModeTask.Result;
var statusMappings = statusMappingTask.Result;
var paidBys = paidByTask.Result;
@ -1283,7 +1283,7 @@ namespace Marco.Pms.Services.Helpers
response.NextStatus = statusMappings.Where(s => s.StatusId == m.StatusId).Select(s => _mapper.Map<List<ExpensesStatusMasterMongoDB>>(s.NextStatus)).FirstOrDefault() ?? new List<ExpensesStatusMasterMongoDB>();
response.PaymentMode = paymentModes.Where(pm => pm.Id == m.PaymentModeId).Select(pm => _mapper.Map<PaymentModeMatserMongoDB>(pm)).FirstOrDefault() ?? new PaymentModeMatserMongoDB();
response.ExpensesType = expenseTypes.Where(et => et.Id == m.ExpensesTypeId).Select(et => _mapper.Map<ExpensesTypeMasterMongoDB>(et)).FirstOrDefault() ?? new ExpensesTypeMasterMongoDB();
response.ExpenseCategory = expenseCategories.Where(et => et.Id == m.ExpenseCategoryId).Select(et => _mapper.Map<ExpenseCategoryMasterMongoDB>(et)).FirstOrDefault() ?? new ExpenseCategoryMasterMongoDB();
response.Documents = billAttachments.Where(ba => ba.ExpensesId == m.Id).Select(ba => ba.Documents).FirstOrDefault() ?? new List<DocumentMongoDB>();
return response;
}).ToList();
@ -1322,15 +1322,15 @@ namespace Marco.Pms.Services.Helpers
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.Employees.Include(e => e.JobRole).AsNoTracking().FirstOrDefaultAsync(e => e.Id == model.ProcessedById && e.TenantId == tenantId);
});
var expenseTypeTask = Task.Run(async () =>
var expenseCategoryTask = Task.Run(async () =>
{
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.ExpensesTypeMaster.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.ExpensesTypeId && et.TenantId == tenantId);
return await dbContext.ExpenseCategoryMasters.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.ExpenseCategoryId && et.TenantId == tenantId);
});
var paymentModeTask = Task.Run(async () =>
{
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.PaymentModeMatser.AsNoTracking().FirstOrDefaultAsync(pm => pm.Id == model.PaymentModeId && pm.TenantId == tenantId);
return await dbContext.PaymentModeMatser.AsNoTracking().FirstOrDefaultAsync(pm => pm.Id == model.PaymentModeId);
});
var statusMappingTask = Task.Run(async () =>
{
@ -1379,11 +1379,11 @@ namespace Marco.Pms.Services.Helpers
});
// Await all prerequisite checks at once.
await Task.WhenAll(projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, reviewedByTask, approvedByTask,
await Task.WhenAll(projectTask, expenseCategoryTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, reviewedByTask, approvedByTask,
processedByTask, statusTask, billAttachmentsTask);
var project = projectTask.Result;
var expenseType = expenseTypeTask.Result;
var expenseCategory = expenseCategoryTask.Result;
var paymentMode = paymentModeTask.Result;
var statusMapping = statusMappingTask.Result;
var paidBy = paidByTask.Result;
@ -1413,7 +1413,7 @@ namespace Marco.Pms.Services.Helpers
response.Status = _mapper.Map<ExpensesStatusMasterMongoDB>(status);
}
response.PaymentMode = _mapper.Map<PaymentModeMatserMongoDB>(paymentMode);
response.ExpensesType = _mapper.Map<ExpensesTypeMasterMongoDB>(expenseType);
response.ExpenseCategory = _mapper.Map<ExpenseCategoryMasterMongoDB>(expenseCategory);
if (billAttachment != null) response.Documents = billAttachment.Documents;
return response;

View File

@ -10,6 +10,7 @@ using Marco.Pms.Model.Dtos.Directory;
using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Dtos.Employees;
using Marco.Pms.Model.Dtos.Expenses;
using Marco.Pms.Model.Dtos.Expenses.Masters;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Dtos.Organization;
using Marco.Pms.Model.Dtos.Project;
@ -17,6 +18,7 @@ using Marco.Pms.Model.Dtos.Tenant;
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Expenses;
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.MongoDBModels;
using Marco.Pms.Model.MongoDBModels.Employees;
@ -34,6 +36,7 @@ using Marco.Pms.Model.ViewModels.DocumentManager;
using Marco.Pms.Model.ViewModels.Employee;
using Marco.Pms.Model.ViewModels.Expanses;
using Marco.Pms.Model.ViewModels.Expenses;
using Marco.Pms.Model.ViewModels.Expenses.Masters;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Model.ViewModels.Organization;
using Marco.Pms.Model.ViewModels.Projects;
@ -223,6 +226,8 @@ namespace Marco.Pms.Services.MappingProfiles
opt => opt.MapFrom(src => Guid.Parse(src.JobRoleId ?? "")));
#endregion
#region ======================================================= Finance =======================================================
#region ======================================================= Expenses =======================================================
CreateMap<Expenses, ExpenseList>();
@ -252,6 +257,7 @@ namespace Marco.Pms.Services.MappingProfiles
dest => dest.Id,
opt => opt.MapFrom(src => Guid.Parse(src.Id)));
CreateMap<Expenses, ExpenseDetailsVM>();
CreateMap<ExpenseDetailsMongoDB, ExpenseDetailsVM>()
.ForMember(
dest => dest.Id,
@ -259,6 +265,34 @@ namespace Marco.Pms.Services.MappingProfiles
#endregion
#region ======================================================= Payment Request =======================================================
CreateMap<PaymentRequestDto, PaymentRequest>();
CreateMap<PaymentRequest, PaymentRequestVM>();
CreateMap<PaymentRequest, PaymentRequestDetailsVM>();
CreateMap<PaymentRequest, BasicPaymentRequestVM>()
.ForMember(
dest => dest.PaymentRequestUID,
opt => opt.MapFrom(src => $"{src.UIDPrefix}/{src.UIDPostfix:D5}"));
CreateMap<Document, PaymentRequestAttachmentVM>();
#endregion
#region ======================================================= Recurring Request =======================================================
CreateMap<CreateRecurringTemplateDto, RecurringPayment>();
CreateMap<UpdateRecurringTemplateDto, RecurringPayment>();
CreateMap<RecurringPayment, RecurringPaymentVM>();
CreateMap<RecurringPayment, RecurringPaymentDetailsVM>()
.ForMember(
dest => dest.RecurringPaymentUID,
opt => opt.MapFrom(src => $"{src.UIDPrefix}/{src.UIDPostfix:D5}"))
.ForMember(
dest => dest.NotifyTo,
opt => opt.MapFrom(src => new List<BasicEmployeeVM>()));
CreateMap<RecurringPayment, BasicRecurringPaymentVM>()
.ForMember(
dest => dest.RecurringPaymentUID,
opt => opt.MapFrom(src => $"{src.UIDPrefix}/{src.UIDPostfix:D5}"));
#endregion
#region ======================================================= Collection =======================================================
CreateMap<InvoiceDto, Invoice>();
CreateMap<Invoice, InvoiceListVM>();
@ -272,6 +306,10 @@ namespace Marco.Pms.Services.MappingProfiles
CreateMap<InvoiceAttachment, InvoiceAttachmentVM>();
#endregion
CreateMap<AdvancePaymentTransaction, AdvancePaymentTransactionVM>();
#endregion
#region ======================================================= Master =======================================================
CreateMap<FeaturePermission, FeaturePermissionVM>();
@ -325,17 +363,17 @@ namespace Marco.Pms.Services.MappingProfiles
#endregion
#region ======================================================= Expenses Type Master =======================================================
#region ======================================================= Expenses Category Master =======================================================
CreateMap<ExpensesTypeMasterDto, ExpensesTypeMaster>()
CreateMap<ExpenseCategoryMasterDto, ExpenseCategoryMaster>()
.ForMember(
dest => dest.Id,
// Explicitly and safely convert nullable Guid to non-nullable Guid
opt => opt.MapFrom(src => src.Id ?? Guid.Empty)
);
CreateMap<ExpensesTypeMaster, ExpensesTypeMasterVM>();
CreateMap<ExpenseCategoryMaster, ExpenseCategoryMasterVM>();
CreateMap<ExpensesTypeMaster, ExpensesTypeMasterMongoDB>()
CreateMap<ExpenseCategoryMaster, ExpenseCategoryMasterMongoDB>()
.ForMember(
dest => dest.Id,
opt => opt.MapFrom(src => src.Id.ToString()))
@ -343,7 +381,7 @@ namespace Marco.Pms.Services.MappingProfiles
dest => dest.TenantId,
opt => opt.MapFrom(src => src.TenantId.ToString()));
CreateMap<ExpensesTypeMasterMongoDB, ExpensesTypeMasterVM>()
CreateMap<ExpenseCategoryMasterMongoDB, ExpenseCategoryMasterVM>()
.ForMember(
dest => dest.Id,
opt => opt.MapFrom(src => Guid.Parse(src.Id)));
@ -384,10 +422,7 @@ namespace Marco.Pms.Services.MappingProfiles
CreateMap<PaymentModeMatser, PaymentModeMatserMongoDB>()
.ForMember(
dest => dest.Id,
opt => opt.MapFrom(src => src.Id.ToString()))
.ForMember(
dest => dest.TenantId,
opt => opt.MapFrom(src => src.TenantId.ToString()));
opt => opt.MapFrom(src => src.Id.ToString()));
CreateMap<PaymentModeMatserMongoDB, PaymentModeMatserVM>()
.ForMember(

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
using Marco.Pms.Model.Forum;
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Forum;
using Marco.Pms.Model.Master;
namespace Marco.Pms.Services.Service
@ -211,11 +212,11 @@ namespace Marco.Pms.Services.Service
}
};
}
public List<ExpensesTypeMaster> GetExpensesTypeesData(Guid tenantId)
public List<ExpenseCategoryMaster> GetExpenseCategoryData(Guid tenantId)
{
return new List<ExpensesTypeMaster>
return new List<ExpenseCategoryMaster>
{
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.NewGuid(),
Name = "Procurement",
@ -225,7 +226,7 @@ namespace Marco.Pms.Services.Service
IsAttachmentRequried = true,
TenantId = tenantId
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.NewGuid(),
Name = "Transport",
@ -235,7 +236,7 @@ namespace Marco.Pms.Services.Service
IsAttachmentRequried = false,
TenantId = tenantId
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.NewGuid(),
Name = "Travelling",
@ -245,7 +246,7 @@ namespace Marco.Pms.Services.Service
IsAttachmentRequried = false,
TenantId = tenantId
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.NewGuid(),
Name = "Mobilization",
@ -255,7 +256,7 @@ namespace Marco.Pms.Services.Service
IsAttachmentRequried = true,
TenantId = tenantId
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.NewGuid(),
Name = "Employee Welfare",
@ -265,7 +266,7 @@ namespace Marco.Pms.Services.Service
IsAttachmentRequried = true,
TenantId = tenantId
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.NewGuid(),
Name = "Maintenance & Utilities",
@ -275,7 +276,7 @@ namespace Marco.Pms.Services.Service
IsAttachmentRequried = true,
TenantId = tenantId
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.NewGuid(),
Name = "Vendor/Supplier Payments",
@ -285,7 +286,7 @@ namespace Marco.Pms.Services.Service
IsAttachmentRequried = true,
TenantId = tenantId
},
new ExpensesTypeMaster
new ExpenseCategoryMaster
{
Id = Guid.NewGuid(),
Name = "Compliance & Safety",
@ -297,44 +298,6 @@ namespace Marco.Pms.Services.Service
}
};
}
public List<PaymentModeMatser> GetPaymentModesData(Guid tenantId)
{
return new List<PaymentModeMatser>
{
new PaymentModeMatser
{
Id = Guid.NewGuid(),
Name = "Cash",
Description = "Physical currency; still used for small or informal transactions.",
IsActive = true,
TenantId = tenantId
},
new PaymentModeMatser
{
Id = Guid.NewGuid(),
Name = "Cheque",
Description = "Paper-based payment order; less common now due to processing delays and fraud risks.",
IsActive = true,
TenantId = tenantId
},
new PaymentModeMatser
{
Id = Guid.NewGuid(),
Name = "NetBanking",
Description = "Online banking portals used to transfer funds directly between accounts",
IsActive = true,
TenantId = tenantId
},
new PaymentModeMatser
{
Id = Guid.NewGuid(),
Name = "UPI",
Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.",
IsActive = true,
TenantId = tenantId
}
};
}
public List<object> GetData(Guid tenantId)
{
return new List<object>

View File

@ -7,19 +7,21 @@ using Marco.Pms.Model.DocumentManager;
using Marco.Pms.Model.Dtos.Activities;
using Marco.Pms.Model.Dtos.Collection;
using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Dtos.Expenses.Masters;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Expenses.Masters;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.MongoDBModels.Utility;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Collection;
using Marco.Pms.Model.ViewModels.DocumentManager;
using Marco.Pms.Model.ViewModels.Expenses.Masters;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Service;
using Microsoft.CodeAnalysis;
using Microsoft.EntityFrameworkCore;
namespace Marco.Pms.Services.Service
@ -52,6 +54,53 @@ namespace Marco.Pms.Services.Service
_updateLogHelper = updateLogHelper ?? throw new ArgumentNullException(nameof(updateLogHelper));
}
#region =================================================================== Recurring Payment Status APIs ===================================================================
public async Task<ApiResponse<object>> GetRecurringPaymentStatusAsync(Employee loggedInEmployee, Guid tenantId)
{
_logger.LogDebug("GetRecurringPaymentStatusAsync called");
try
{
// Step 1: Fetch global recurring payment status
var status = await _context.RecurringPaymentStatus.OrderBy(rps => rps.Name).ToListAsync();
_logger.LogInfo("Fetched {Count} recurring payment status records for tenantId: {TenantId}", status.Count, tenantId);
return ApiResponse<object>.SuccessResponse(status, $"{status.Count} record(s) of recurring payment status fetched successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching recurring payment status");
return ApiResponse<object>.ErrorResponse("An error occurred while fetching recurring payment status", ex.Message, 500);
}
}
#endregion
#region =================================================================== Currency APIs ===================================================================
public async Task<ApiResponse<object>> GetCurrencyAsync(Employee loggedInEmployee, Guid tenantId)
{
_logger.LogDebug("GetCurrencyAsync called");
try
{
// Step 1: Fetch global currencies
var currencies = await _context.CurrencyMaster.OrderBy(ot => ot.CurrencyName).ToListAsync();
_logger.LogInfo("Fetched {Count} currency records for tenantId: {TenantId}", currencies.Count, tenantId);
return ApiResponse<object>.SuccessResponse(currencies, $"{currencies.Count} record(s) of currency fetched successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching currency");
return ApiResponse<object>.ErrorResponse("An error occurred while fetching currency", ex.Message, 500);
}
}
#endregion
#region =================================================================== Organization Type APIs ===================================================================
public async Task<ApiResponse<object>> GetOrganizationTypesAsync(Employee loggedInEmployee, Guid tenantId)
@ -2044,59 +2093,59 @@ namespace Marco.Pms.Services.Service
#endregion
#region =================================================================== Expenses Type APIs ===================================================================
#region =================================================================== Expenses Category APIs ===================================================================
public async Task<ApiResponse<object>> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive)
public async Task<ApiResponse<object>> GetExpenseCategoryListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive)
{
try
{
// Featching the list of Expenses Type.
var typeList = await _context.ExpensesTypeMaster.Where(et => et.TenantId == tenantId && et.IsActive == isActive).ToListAsync();
var response = _mapper.Map<List<ExpensesTypeMasterVM>>(typeList);
// Featching the list of Expenses Category.
var categories = await _context.ExpenseCategoryMasters.Where(et => et.TenantId == tenantId && et.IsActive == isActive).ToListAsync();
var response = _mapper.Map<List<ExpenseCategoryMasterVM>>(categories);
_logger.LogInfo("{Count} records of expense type have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, $"{response.Count} records of expense type have been fetched successfully.", 200);
_logger.LogInfo("{Count} records of expense category have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, $"{response.Count} records of expense category have been fetched successfully.", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occured while fetching list of expense type list by employee {EmployeeId}", loggedInEmployee.Id);
_logger.LogError(ex, "Error occured while fetching list of expense category list by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
public async Task<ApiResponse<object>> CreateExpenseTypeAsync(ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId)
public async Task<ApiResponse<object>> CreateExpenseCategoryAsync(ExpenseCategoryMasterDto model, Employee loggedInEmployee, Guid tenantId)
{
try
{
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES TYPE MASTER.", loggedInEmployee.Id);
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES CATEGORY MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
var expensesType = _mapper.Map<ExpensesTypeMaster>(model);
expensesType.TenantId = tenantId;
var expensesCategory = _mapper.Map<ExpenseCategoryMaster>(model);
expensesCategory.TenantId = tenantId;
_context.ExpensesTypeMaster.Add(expensesType);
_context.ExpenseCategoryMasters.Add(expensesCategory);
await _context.SaveChangesAsync();
_logger.LogInfo("New Expense Type {ExpensesTypeId} was added by employee {EmployeeId}", expensesType.Id, loggedInEmployee.Id);
_logger.LogInfo("New Expense Category {ExpensesCategoryId} was added by employee {EmployeeId}", expensesCategory.Id, loggedInEmployee.Id);
var response = _mapper.Map<ExpensesTypeMasterVM>(expensesType);
return ApiResponse<object>.SuccessResponse(response, "Expense type craeted Successfully", 201);
var response = _mapper.Map<ExpenseCategoryMasterVM>(expensesCategory);
return ApiResponse<object>.SuccessResponse(response, "Expense category craeted Successfully", 201);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while adding new expense type by employee {EmployeeId}", loggedInEmployee.Id);
_logger.LogError(dbEx, "Database Exception occured while adding new expense category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while adding new expense type by employee {EmployeeId}", loggedInEmployee.Id);
_logger.LogError(ex, "Exception occured while adding new expense category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
public async Task<ApiResponse<object>> UpdateExpenseTypeAsync(Guid id, ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId)
public async Task<ApiResponse<object>> UpdateExpenseCategoryAsync(Guid id, ExpenseCategoryMasterDto model, Employee loggedInEmployee, Guid tenantId)
{
try
{
@ -2104,7 +2153,7 @@ namespace Marco.Pms.Services.Service
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES TYPE MASTER.", loggedInEmployee.Id);
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES CATEGORY MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
@ -2115,52 +2164,52 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.ErrorResponse("Invalid Data", "User has send invalid payload", 400);
}
var expensesType = await _context.ExpensesTypeMaster.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.Id.Value && et.TenantId == tenantId);
var expenseCategory = await _context.ExpenseCategoryMasters.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.Id.Value && et.TenantId == tenantId);
// Checking if expense type exists
if (expensesType == null)
// Checking if expense category exists
if (expenseCategory == null)
{
_logger.LogWarning("Employee {EmployeeId} tries to update expense type, but not found in database", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Expense Type not found", "Expense Type not found", 404);
_logger.LogWarning("Employee {EmployeeId} tries to update expense category, but not found in database", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Expense Category not found", "Expense Category not found", 404);
}
// Mapping ExpensesTypeMaster to BsonDocument
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(expensesType);
// Mapping ExpenseCategoryMaster to BsonDocument
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(expenseCategory);
// Mapping ExpensesTypeMasterDto to ExpensesTypeMaster
_mapper.Map(model, expensesType);
// Mapping ExpenseCategoryMasterDto to ExpenseCategoryMaster
_mapper.Map(model, expenseCategory);
_context.ExpensesTypeMaster.Update(expensesType);
_context.ExpenseCategoryMasters.Update(expenseCategory);
await _context.SaveChangesAsync();
_logger.LogInfo("Expense Type {ExpensesTypeId} was updated by employee {EmployeeId}", expensesType.Id, loggedInEmployee.Id);
_logger.LogInfo("Expense Category {ExpensesCategoryId} was updated by employee {EmployeeId}", expenseCategory.Id, loggedInEmployee.Id);
// Saving the old entity in mongoDB
await _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject
{
EntityId = expensesType.Id.ToString(),
EntityId = expenseCategory.Id.ToString(),
UpdatedById = loggedInEmployee.Id.ToString(),
OldObject = existingEntityBson,
UpdatedAt = DateTime.UtcNow
}, "ExpensesTypeMasterModificationLog");
}, "ExpensesCategoryMasterModificationLog");
// Mapping ExpensesTypeMaster to ExpensesTypeMasterVM
var response = _mapper.Map<ExpensesTypeMasterVM>(expensesType);
return ApiResponse<object>.SuccessResponse(response, "Expense type updated Successfully", 200);
// Mapping ExpenseCategoryMaster to ExpenseCategoryMasterVM
var response = _mapper.Map<ExpenseCategoryMasterVM>(expenseCategory);
return ApiResponse<object>.SuccessResponse(response, "Expense category updated Successfully", 200);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while updating expense type by employee {EmployeeId}", loggedInEmployee.Id);
_logger.LogError(dbEx, "Database Exception occured while updating expense category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while updating expense type by employee {EmployeeId}", loggedInEmployee.Id);
_logger.LogError(ex, "Exception occured while updating expense category by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
public async Task<ApiResponse<object>> DeleteExpenseTypeAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId)
public async Task<ApiResponse<object>> DeleteExpenseCategoryAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId)
{
string action = isActive ? "restore" : "delete";
try
@ -2169,49 +2218,49 @@ namespace Marco.Pms.Services.Service
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
if (!hasManagePermission)
{
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES TYPE MASTER.", loggedInEmployee.Id);
_logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPANSES CATEGORY MASTER.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
var expensesType = await _context.ExpensesTypeMaster.FirstOrDefaultAsync(et => et.Id == id && et.TenantId == tenantId);
var expenseCategory = await _context.ExpenseCategoryMasters.FirstOrDefaultAsync(et => et.Id == id && et.TenantId == tenantId);
// Checking if expense type exists
if (expensesType == null)
// Checking if expense category exists
if (expenseCategory == null)
{
_logger.LogWarning("Employee {EmployeeId} tries to {Action} expense type, but not found in database", loggedInEmployee.Id, action);
return ApiResponse<object>.ErrorResponse("Expense Type not found", "Expense Type not found", 404);
_logger.LogWarning("Employee {EmployeeId} tries to {Action} expense category, but not found in database", loggedInEmployee.Id, action);
return ApiResponse<object>.ErrorResponse("Expense Category not found", "Expense Category not found", 404);
}
// Mapping ExpensesTypeMaster to BsonDocument
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(expensesType);
// Mapping ExpenseCategoryMaster to BsonDocument
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(expenseCategory);
expensesType.IsActive = isActive;
expenseCategory.IsActive = isActive;
await _context.SaveChangesAsync();
_logger.LogInfo("Expense Type {ExpensesTypeId} was {Action}d by employee {EmployeeId}", expensesType.Id, action, loggedInEmployee.Id);
_logger.LogInfo("Expense Category {ExpensesCategoryId} was {Action}d by employee {EmployeeId}", expenseCategory.Id, action, loggedInEmployee.Id);
// Saving the old entity in mongoDB
await _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject
{
EntityId = expensesType.Id.ToString(),
EntityId = expenseCategory.Id.ToString(),
UpdatedById = loggedInEmployee.Id.ToString(),
OldObject = existingEntityBson,
UpdatedAt = DateTime.UtcNow
}, "ExpensesTypeMasterModificationLog");
}, "ExpensesCategoryMasterModificationLog");
// Mapping ExpensesTypeMaster to ExpensesTypeMasterVM
var response = _mapper.Map<ExpensesTypeMasterVM>(expensesType);
return ApiResponse<object>.SuccessResponse(response, $"Expense type {action}d Successfully", 200);
// Mapping ExpenseCategoryMaster to ExpenseCategoryMasterVM
var response = _mapper.Map<ExpenseCategoryMasterVM>(expenseCategory);
return ApiResponse<object>.SuccessResponse(response, $"Expense category {action}d Successfully", 200);
}
catch (DbUpdateException dbEx)
{
_logger.LogError(dbEx, "Database Exception occured while {Action}ing expense type by employee {EmployeeId}", action, loggedInEmployee.Id);
_logger.LogError(dbEx, "Database Exception occured while {Action}ing expense category by employee {EmployeeId}", action, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occured while {Action}ing expense type by employee {EmployeeId}", action, loggedInEmployee.Id);
_logger.LogError(ex, "Exception occured while {Action}ing expense category by employee {EmployeeId}", action, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
@ -2259,7 +2308,7 @@ namespace Marco.Pms.Services.Service
try
{
// Featching the list of Payment Modes.
var paymentModes = await _context.PaymentModeMatser.Where(pm => pm.TenantId == tenantId && pm.IsActive == isActive).ToListAsync();
var paymentModes = await _context.PaymentModeMatser.Where(pm => pm.IsActive == isActive).ToListAsync();
var response = _mapper.Map<List<PaymentModeMatserVM>>(paymentModes);
_logger.LogInfo("{Count} records of payment modes have been fetched successfully by employee {EmployeeId}", response.Count, loggedInEmployee.Id);
@ -2284,7 +2333,6 @@ namespace Marco.Pms.Services.Service
}
// Mapping the DTO to PaymentModeMatser Model
var paymentMode = _mapper.Map<PaymentModeMatser>(model);
paymentMode.TenantId = tenantId;
_context.PaymentModeMatser.Add(paymentMode);
await _context.SaveChangesAsync();
@ -2325,7 +2373,7 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.ErrorResponse("Invalid Data", "User has send invalid payload", 400);
}
var paymentMode = await _context.PaymentModeMatser.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.Id.Value && et.TenantId == tenantId);
var paymentMode = await _context.PaymentModeMatser.AsNoTracking().FirstOrDefaultAsync(et => et.Id == model.Id.Value);
// Checking if Payment Mode exists
if (paymentMode == null)
@ -2383,7 +2431,7 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403);
}
var paymentMode = await _context.PaymentModeMatser.FirstOrDefaultAsync(et => et.Id == id && et.TenantId == tenantId);
var paymentMode = await _context.PaymentModeMatser.FirstOrDefaultAsync(et => et.Id == id);
// Checking if Payment Mode exists
if (paymentMode == null)

View File

@ -6,13 +6,18 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
{
public interface IExpensesService
{
#region =================================================================== Expenses Functions ===================================================================
Task<ApiResponse<object>> GetExpensesListAsync(Employee loggedInEmployee, Guid tenantId, string? searchString, string? filter, int pageSize, int pageNumber);
Task<ApiResponse<object>> GetExpenseDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetExpenseDetailsAsync(Guid? id, string? expenseUId, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetSupplerNameListAsync(Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetFilterObjectAsync(Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateExpenseAsync(CreateExpensesDto dto, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> ChangeStatusAsync(ExpenseRecordDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateExpanseAsync(Guid id, UpdateExpensesDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteExpanseAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
#endregion
}
}

View File

@ -1,6 +1,7 @@
using Marco.Pms.Model.Dtos.Activities;
using Marco.Pms.Model.Dtos.Collection;
using Marco.Pms.Model.Dtos.DocumentManager;
using Marco.Pms.Model.Dtos.Expenses.Masters;
using Marco.Pms.Model.Dtos.Master;
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Utilities;
@ -9,8 +10,17 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
{
public interface IMasterService
{
#region =================================================================== Organization Type APIs ===================================================================
#region =================================================================== Recurring Payment Status APIs ===================================================================
Task<ApiResponse<object>> GetRecurringPaymentStatusAsync(Employee loggedInEmployee, Guid tenantId);
#endregion
#region =================================================================== Currency APIs ===================================================================
Task<ApiResponse<object>> GetCurrencyAsync(Employee loggedInEmployee, Guid tenantId);
#endregion
#region =================================================================== Organization Type APIs ===================================================================
Task<ApiResponse<object>> GetOrganizationTypesAsync(Employee loggedInEmployee, Guid tenantId);
#endregion
@ -71,11 +81,11 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task<ApiResponse<object>> DeleteWorkStatus(Guid id, Employee loggedInEmployee, Guid tenantId);
#endregion
#region =================================================================== Expenses Type APIs ===================================================================
Task<ApiResponse<object>> GetExpenseTypeListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive);
Task<ApiResponse<object>> CreateExpenseTypeAsync(ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateExpenseTypeAsync(Guid id, ExpensesTypeMasterDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteExpenseTypeAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
#region =================================================================== Expenses Category APIs ===================================================================
Task<ApiResponse<object>> GetExpenseCategoryListAsync(Employee loggedInEmployee, Guid tenantId, bool isActive);
Task<ApiResponse<object>> CreateExpenseCategoryAsync(ExpenseCategoryMasterDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateExpenseCategoryAsync(Guid id, ExpenseCategoryMasterDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteExpenseCategoryAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
#endregion

View File

@ -521,11 +521,9 @@ namespace Marco.Pms.Services.Service
}
if (features.Modules?.Expense?.Enabled ?? false)
{
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
var paymentModeMatser = _masteData.GetPaymentModesData(tenant.Id);
var expenseCategoryMaster = _masteData.GetExpenseCategoryData(tenant.Id);
_context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
_context.PaymentModeMatser.AddRange(paymentModeMatser);
_context.ExpenseCategoryMasters.AddRange(expenseCategoryMaster);
}
await _context.SaveChangesAsync();
@ -805,33 +803,14 @@ namespace Marco.Pms.Services.Service
}
if (features.Modules?.Expense?.Enabled ?? false)
{
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
var paymentModeMatser = _masteData.GetPaymentModesData(tenant.Id);
var expenseCategoryMaster = _masteData.GetExpenseCategoryData(tenant.Id);
var expensesTypeTask = Task.Run(async () =>
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
var expensesTypeNames = expensesTypeMaster.Select(et => et.Name).ToList();
return await _context.ExpensesTypeMaster.AnyAsync(et => expensesTypeNames.Contains(et.Name) && et.TenantId == tenant.Id);
});
var paymentModeTask = Task.Run(async () =>
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
var paymentModeNames = paymentModeMatser.Select(py => py.Name).ToList();
return await _context.PaymentModeMatser.AnyAsync(py => paymentModeNames.Contains(py.Name) && py.TenantId == tenant.Id);
});
var expensesTypeNames = expenseCategoryMaster.Select(et => et.Name).ToList();
var expenseCategoryExist = await context.ExpenseCategoryMasters.AnyAsync(et => expensesTypeNames.Contains(et.Name) && et.TenantId == tenant.Id);
await Task.WhenAll(expensesTypeTask, paymentModeTask);
var expensesTypeExist = expensesTypeTask.Result;
var paymentModeExist = paymentModeTask.Result;
if (!expensesTypeExist)
if (!expenseCategoryExist)
{
context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
}
if (!paymentModeExist)
{
context.PaymentModeMatser.AddRange(paymentModeMatser);
context.ExpenseCategoryMasters.AddRange(expenseCategoryMaster);
}
}