Compare commits
58 Commits
main
...
Ashutosh_T
| Author | SHA1 | Date | |
|---|---|---|---|
| eccb87ebb4 | |||
| e1d6434fc6 | |||
| faa47c40b2 | |||
| e7edc2f45c | |||
| e821724e83 | |||
| e3b418560b | |||
| 18cd1efafa | |||
| b4677aacf3 | |||
| 68aec35028 | |||
| a684556cff | |||
| ee48d7372a | |||
| c3b93022fd | |||
| 7e634e3a47 | |||
| e94210a341 | |||
| 918f856632 | |||
| 663d94093c | |||
| dc83aa72a6 | |||
| ef597b2bb7 | |||
| 4acc61f03a | |||
| c47b0da7b8 | |||
| d180d5d60e | |||
| 60eefa78c0 | |||
| b1af96b923 | |||
| 629c4541d6 | |||
| e93408c00d | |||
| 16e509ccbd | |||
| 8a4a056c2d | |||
| f6e8a0d5e2 | |||
| 0561e356d8 | |||
| e2ee3f325c | |||
| 6441103e30 | |||
| d380dfebd2 | |||
| 658fa8cd23 | |||
| 3afdad29b2 | |||
| 8f463ce90d | |||
| 590476a8aa | |||
| 548e714ea9 | |||
| 91f4305995 | |||
| 7e15c517ac | |||
| 9332d9cc0b | |||
| 541ed28bd2 | |||
| 0e1d20156f | |||
| 87c5de87a1 | |||
| 5eda1773b7 | |||
| b3f54962ab | |||
| 040e7df32b | |||
| 0066e20c43 | |||
| 7659eadd00 | |||
| 824381bb49 | |||
| 207a44acd7 | |||
| 7775f58d69 | |||
| 91be729b41 | |||
| 0bd57d29d8 | |||
| b442bb4bbc | |||
| ca3e47c1e6 | |||
| 061512d501 | |||
| 71cc442054 | |||
| bab03a8e47 |
@ -1,6 +1,7 @@
|
|||||||
using Marco.Pms.Model.Activities;
|
using Marco.Pms.Model.Activities;
|
||||||
using Marco.Pms.Model.AttendanceModule;
|
using Marco.Pms.Model.AttendanceModule;
|
||||||
using Marco.Pms.Model.Authentication;
|
using Marco.Pms.Model.Authentication;
|
||||||
|
using Marco.Pms.Model.Collection;
|
||||||
using Marco.Pms.Model.Directory;
|
using Marco.Pms.Model.Directory;
|
||||||
using Marco.Pms.Model.DocumentManager;
|
using Marco.Pms.Model.DocumentManager;
|
||||||
using Marco.Pms.Model.Employees;
|
using Marco.Pms.Model.Employees;
|
||||||
@ -10,6 +11,7 @@ using Marco.Pms.Model.Forum;
|
|||||||
using Marco.Pms.Model.Mail;
|
using Marco.Pms.Model.Mail;
|
||||||
using Marco.Pms.Model.Master;
|
using Marco.Pms.Model.Master;
|
||||||
using Marco.Pms.Model.OrganizationModel;
|
using Marco.Pms.Model.OrganizationModel;
|
||||||
|
using Marco.Pms.Model.PaymentGetway;
|
||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
using Marco.Pms.Model.Roles;
|
using Marco.Pms.Model.Roles;
|
||||||
using Marco.Pms.Model.TenantModels;
|
using Marco.Pms.Model.TenantModels;
|
||||||
@ -104,6 +106,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
public DbSet<Expenses> Expenses { get; set; }
|
public DbSet<Expenses> Expenses { get; set; }
|
||||||
public DbSet<ExpenseLog> ExpenseLogs { get; set; }
|
public DbSet<ExpenseLog> ExpenseLogs { get; set; }
|
||||||
public DbSet<ExpensesTypeMaster> ExpensesTypeMaster { get; set; }
|
public DbSet<ExpensesTypeMaster> ExpensesTypeMaster { get; set; }
|
||||||
|
public DbSet<ExpenseCategoryMaster> ExpenseCategoryMasters { get; set; }
|
||||||
public DbSet<PaymentModeMatser> PaymentModeMatser { get; set; }
|
public DbSet<PaymentModeMatser> PaymentModeMatser { get; set; }
|
||||||
public DbSet<ExpensesStatusMaster> ExpensesStatusMaster { get; set; }
|
public DbSet<ExpensesStatusMaster> ExpensesStatusMaster { get; set; }
|
||||||
public DbSet<BillAttachments> BillAttachments { get; set; }
|
public DbSet<BillAttachments> BillAttachments { get; set; }
|
||||||
@ -111,6 +114,12 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
public DbSet<ExpensesReimburseMapping> ExpensesReimburseMapping { get; set; }
|
public DbSet<ExpensesReimburseMapping> ExpensesReimburseMapping { get; set; }
|
||||||
public DbSet<StatusPermissionMapping> StatusPermissionMapping { get; set; }
|
public DbSet<StatusPermissionMapping> StatusPermissionMapping { get; set; }
|
||||||
public DbSet<ExpensesStatusMapping> ExpensesStatusMapping { 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<StatusUpdateLog> StatusUpdateLogs { get; set; }
|
||||||
|
|
||||||
public DbSet<FCMTokenMapping> FCMTokenMappings { get; set; }
|
public DbSet<FCMTokenMapping> FCMTokenMappings { get; set; }
|
||||||
|
|
||||||
@ -133,6 +142,16 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
public DbSet<ProjectServiceMapping> ProjectServiceMappings { get; set; }
|
public DbSet<ProjectServiceMapping> ProjectServiceMappings { get; set; }
|
||||||
public DbSet<ProjectOrgMapping> ProjectOrgMappings { 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; }
|
||||||
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
@ -657,8 +676,8 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
StatusId = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95")
|
StatusId = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95")
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity<ExpensesTypeMaster>().HasData(
|
modelBuilder.Entity<ExpenseCategoryMaster>().HasData(
|
||||||
new ExpensesTypeMaster
|
new ExpenseCategoryMaster
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("5e0c6227-d49d-41ff-9f1f-781f0aee2469"),
|
Id = Guid.Parse("5e0c6227-d49d-41ff-9f1f-781f0aee2469"),
|
||||||
Name = "Procurement",
|
Name = "Procurement",
|
||||||
@ -668,7 +687,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
IsAttachmentRequried = true,
|
IsAttachmentRequried = true,
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
},
|
},
|
||||||
new ExpensesTypeMaster
|
new ExpenseCategoryMaster
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("2de53163-0dbd-404b-8e60-1b02e6b4886a"),
|
Id = Guid.Parse("2de53163-0dbd-404b-8e60-1b02e6b4886a"),
|
||||||
Name = "Transport",
|
Name = "Transport",
|
||||||
@ -678,7 +697,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
IsAttachmentRequried = false,
|
IsAttachmentRequried = false,
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
},
|
},
|
||||||
new ExpensesTypeMaster
|
new ExpenseCategoryMaster
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"),
|
Id = Guid.Parse("dd120bc4-ab0a-45ba-8450-5cd45ff221ca"),
|
||||||
Name = "Travelling",
|
Name = "Travelling",
|
||||||
@ -688,7 +707,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
IsAttachmentRequried = false,
|
IsAttachmentRequried = false,
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
},
|
},
|
||||||
new ExpensesTypeMaster
|
new ExpenseCategoryMaster
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("52484820-1b54-4865-8f0f-baa2b1d339b9"),
|
Id = Guid.Parse("52484820-1b54-4865-8f0f-baa2b1d339b9"),
|
||||||
Name = "Mobilization",
|
Name = "Mobilization",
|
||||||
@ -698,7 +717,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
IsAttachmentRequried = true,
|
IsAttachmentRequried = true,
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
},
|
},
|
||||||
new ExpensesTypeMaster
|
new ExpenseCategoryMaster
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("fc59eb90-98ea-481c-b421-54bfa9e42d8f"),
|
Id = Guid.Parse("fc59eb90-98ea-481c-b421-54bfa9e42d8f"),
|
||||||
Name = "Employee Welfare",
|
Name = "Employee Welfare",
|
||||||
@ -708,7 +727,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
IsAttachmentRequried = true,
|
IsAttachmentRequried = true,
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
},
|
},
|
||||||
new ExpensesTypeMaster
|
new ExpenseCategoryMaster
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("77013784-9324-4d8b-bd36-d6f928e68942"),
|
Id = Guid.Parse("77013784-9324-4d8b-bd36-d6f928e68942"),
|
||||||
Name = "Maintenance & Utilities",
|
Name = "Maintenance & Utilities",
|
||||||
@ -718,7 +737,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
IsAttachmentRequried = true,
|
IsAttachmentRequried = true,
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
},
|
},
|
||||||
new ExpensesTypeMaster
|
new ExpenseCategoryMaster
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("1e2d697a-76b4-4be8-bc66-87144561a1a0"),
|
Id = Guid.Parse("1e2d697a-76b4-4be8-bc66-87144561a1a0"),
|
||||||
Name = "Vendor/Supplier Payments",
|
Name = "Vendor/Supplier Payments",
|
||||||
@ -728,7 +747,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
IsAttachmentRequried = true,
|
IsAttachmentRequried = true,
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
},
|
},
|
||||||
new ExpensesTypeMaster
|
new ExpenseCategoryMaster
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("4842fa61-64eb-4241-aebd-8282065af9f9"),
|
Id = Guid.Parse("4842fa61-64eb-4241-aebd-8282065af9f9"),
|
||||||
Name = "Compliance & Safety",
|
Name = "Compliance & Safety",
|
||||||
@ -746,30 +765,106 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
Id = Guid.Parse("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"),
|
Id = Guid.Parse("24e6b0df-7929-47d2-88a3-4cf14c1f28f9"),
|
||||||
Name = "Cash",
|
Name = "Cash",
|
||||||
Description = "Physical currency; still used for small or informal transactions.",
|
Description = "Physical currency; still used for small or informal transactions.",
|
||||||
IsActive = true,
|
IsActive = true
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
},
|
},
|
||||||
new PaymentModeMatser
|
new PaymentModeMatser
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("48d9b462-5d87-4dec-8dec-2bc943943172"),
|
Id = Guid.Parse("48d9b462-5d87-4dec-8dec-2bc943943172"),
|
||||||
Name = "Cheque",
|
Name = "Cheque",
|
||||||
Description = "Paper-based payment order; less common now due to processing delays and fraud risks.",
|
Description = "Paper-based payment order; less common now due to processing delays and fraud risks.",
|
||||||
IsActive = true,
|
IsActive = true
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
},
|
},
|
||||||
new PaymentModeMatser
|
new PaymentModeMatser
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("ed667353-8eea-4fd1-8750-719405932480"),
|
Id = Guid.Parse("ed667353-8eea-4fd1-8750-719405932480"),
|
||||||
Name = "NetBanking",
|
Name = "NetBanking",
|
||||||
Description = "Online banking portals used to transfer funds directly between accounts",
|
Description = "Online banking portals used to transfer funds directly between accounts",
|
||||||
IsActive = true,
|
IsActive = true
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
},
|
},
|
||||||
new PaymentModeMatser
|
new PaymentModeMatser
|
||||||
{
|
{
|
||||||
Id = Guid.Parse("2e919e94-694c-41d9-9489-0a2b4208a027"),
|
Id = Guid.Parse("2e919e94-694c-41d9-9489-0a2b4208a027"),
|
||||||
Name = "UPI",
|
Name = "UPI",
|
||||||
Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.",
|
Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.",
|
||||||
|
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
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
modelBuilder.Entity<PaymentAdjustmentHead>().HasData(
|
||||||
|
new PaymentAdjustmentHead
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("dbdc047f-a2d2-4db0-b0e6-b9d9f923a0f1"),
|
||||||
|
Name = "Advance payment",
|
||||||
|
Description = "An advance payment is a sum paid before receiving goods or services, often to secure a transaction or cover initial costs.",
|
||||||
|
IsActive = true,
|
||||||
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
|
},
|
||||||
|
new PaymentAdjustmentHead
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("66c3c241-8b52-4327-a5ad-c1faf102583e"),
|
||||||
|
Name = "Base Amount",
|
||||||
|
Description = "The base amount refers to the principal sum or original value used as a reference in financial calculations, excluding taxes, fees, or additional charges.",
|
||||||
|
IsActive = true,
|
||||||
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
|
},
|
||||||
|
new PaymentAdjustmentHead
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("0d70cb2e-827e-44fc-90a5-c2c55ba51ba9"),
|
||||||
|
Name = "Tax Deducted at Source (TDS)",
|
||||||
|
Description = "TDS, or Tax Deducted at Source, is a system under the Indian Income Tax Act where tax is deducted at the point of income generation—such as salary, interest, or rent—and remitted to the government to prevent tax evasion and ensure timely collection.",
|
||||||
|
IsActive = true,
|
||||||
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
|
},
|
||||||
|
new PaymentAdjustmentHead
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("95f35acd-d979-4177-91ea-fd03a00e49ff"),
|
||||||
|
Name = "Retention",
|
||||||
|
Description = "Retention refers to a company's ability to keep customers, employees, or profits over time, commonly measured as a percentage and critical for long-term business sustainability and growth.",
|
||||||
|
IsActive = true,
|
||||||
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
|
},
|
||||||
|
new PaymentAdjustmentHead
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("3f09b19a-8d45-4cf2-be27-f4f09b38b9f7"),
|
||||||
|
Name = "Tax",
|
||||||
|
Description = "Tax is a mandatory financial charge imposed by a government on individuals or entities to fund public services and government operations, without direct benefit to the taxpayer.",
|
||||||
|
IsActive = true,
|
||||||
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
|
},
|
||||||
|
new PaymentAdjustmentHead
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("ec5e6a5f-ce62-44e5-8911-8426bbb4dde8"),
|
||||||
|
Name = "Penalty",
|
||||||
|
Description = "A penalty in the context of taxation is a financial sanction imposed by the government on individuals or entities for non-compliance with tax laws, such as late filing, underreporting income, or failure to pay taxes, and is typically calculated as a percentage of the tax due or a fixed amount.",
|
||||||
|
IsActive = true,
|
||||||
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
|
},
|
||||||
|
new PaymentAdjustmentHead
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("50584332-1cb7-4359-9721-c8ea35040881"),
|
||||||
|
Name = "Utility fees",
|
||||||
|
Description = "Utility fees are recurring charges for essential services such as electricity, water, gas, sewage, waste disposal, internet, and telecommunications, typically based on usage and necessary for operating a home or business.",
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
}
|
}
|
||||||
@ -1039,6 +1134,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
// Project Module
|
// 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("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("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("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("9d4b5489-2079-40b9-bd77-6e1bf90bc19f"), Description = "Manage Tasks", Name = "Task Management", ModuleId = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), IsActive = true },
|
||||||
|
|
||||||
// Employee Module
|
// Employee Module
|
||||||
@ -1110,6 +1206,13 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
new FeaturePermission { Id = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Process", Description = "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled." },
|
new FeaturePermission { Id = new Guid("ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Process", Description = "Allows a user to handle post-approval actions such as recording payments, updating financial records, or marking expenses as reimbursed or settled." },
|
||||||
new FeaturePermission { Id = new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Manage", Description = "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules." },
|
new FeaturePermission { Id = new Guid("bdee29a2-b73b-402d-8dd1-c4b1f81ccbc3"), FeatureId = new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), IsEnabled = true, Name = "Manage", Description = "Allows a user to configure and control system settings, such as managing expense types, payment modes, permissions, and overall workflow rules." },
|
||||||
|
|
||||||
|
// Collection Management Feature
|
||||||
|
new FeaturePermission { Id = new Guid("dbf17591-09fe-4c93-9e1a-12db8f5cc5de"), FeatureId = new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), IsEnabled = true, Name = "Collection Admin", Description = "Collection Admin is a permission that grants a user full administrative control over collections, including creating, editing, managing access, and deleting collections within a system." },
|
||||||
|
new FeaturePermission { Id = new Guid("c8d7eea5-4033-4aad-9ebe-76de49896830"), FeatureId = new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), IsEnabled = true, Name = "View Collection", Description = "View Collection is a permission that allows users to see and browse assets or items within a collection without making any modifications or edits to its contents." },
|
||||||
|
new FeaturePermission { Id = new Guid("b93141fd-dbd3-4051-8f57-bf25d18e3555"), FeatureId = new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), IsEnabled = true, Name = "Create Collection", Description = "Authorizes users to create new collections for organizing related resources and managing access" },
|
||||||
|
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." },
|
||||||
|
|
||||||
// Organization Management Feature
|
// 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("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" },
|
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" },
|
||||||
|
|||||||
6209
Marco.Pms.DataAccess/Migrations/20251003093145_Added_ExpenceUID_In_Expense_Table.Designer.cs
generated
Normal file
6209
Marco.Pms.DataAccess/Migrations/20251003093145_Added_ExpenceUID_In_Expense_Table.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Added_ExpenceUID_In_Expense_Table : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "ExpenseUId",
|
||||||
|
table: "Expenses",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ExpenseUId",
|
||||||
|
table: "Expenses");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6226
Marco.Pms.DataAccess/Migrations/20251008121556_Added_Requested_In_Attendance_Table.Designer.cs
generated
Normal file
6226
Marco.Pms.DataAccess/Migrations/20251008121556_Added_Requested_In_Attendance_Table.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Added_Requested_In_Attendance_Table : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "ApprovedAt",
|
||||||
|
table: "Attendes",
|
||||||
|
type: "datetime(6)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "RequestedAt",
|
||||||
|
table: "Attendes",
|
||||||
|
type: "datetime(6)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "RequestedById",
|
||||||
|
table: "Attendes",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: true,
|
||||||
|
collation: "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Attendes_RequestedById",
|
||||||
|
table: "Attendes",
|
||||||
|
column: "RequestedById");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Attendes_Employees_RequestedById",
|
||||||
|
table: "Attendes",
|
||||||
|
column: "RequestedById",
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Attendes_Employees_RequestedById",
|
||||||
|
table: "Attendes");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Attendes_RequestedById",
|
||||||
|
table: "Attendes");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ApprovedAt",
|
||||||
|
table: "Attendes");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "RequestedAt",
|
||||||
|
table: "Attendes");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "RequestedById",
|
||||||
|
table: "Attendes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6783
Marco.Pms.DataAccess/Migrations/20251029065544_Added_Payment_Related_Tables.Designer.cs
generated
Normal file
6783
Marco.Pms.DataAccess/Migrations/20251029065544_Added_Payment_Related_Tables.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,469 @@
|
|||||||
|
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_Payment_Related_Tables : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "PaymentDetailId",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: true,
|
||||||
|
collation: "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Invoices",
|
||||||
|
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"),
|
||||||
|
InvoiceNumber = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
EInvoiceNumber = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ProjectId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
InvoiceDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
ClientSubmitedDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
ExceptedPaymentDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
BasicAmount = table.Column<double>(type: "double", nullable: false),
|
||||||
|
TaxAmount = table.Column<double>(type: "double", nullable: false),
|
||||||
|
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
MarkAsCompleted = 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_Invoices", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Invoices_Employees_CreatedById",
|
||||||
|
column: x => x.CreatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Invoices_Employees_UpdatedById",
|
||||||
|
column: x => x.UpdatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Invoices_Projects_ProjectId",
|
||||||
|
column: x => x.ProjectId,
|
||||||
|
principalTable: "Projects",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Invoices_Tenants_TenantId",
|
||||||
|
column: x => x.TenantId,
|
||||||
|
principalTable: "Tenants",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PaymentAdjustmentHeads",
|
||||||
|
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"),
|
||||||
|
Description = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
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_PaymentAdjustmentHeads", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_PaymentAdjustmentHeads_Tenants_TenantId",
|
||||||
|
column: x => x.TenantId,
|
||||||
|
principalTable: "Tenants",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PaymentDetails",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
PaymentId = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
OrderId = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Status = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Method = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
EncryptedDetails = table.Column<byte[]>(type: "longblob", nullable: true),
|
||||||
|
Nonce = table.Column<byte[]>(type: "longblob", nullable: true),
|
||||||
|
Tag = table.Column<byte[]>(type: "longblob", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_PaymentDetails", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "TenantEnquires",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
FirstName = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
LastName = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
OrganizationName = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Email = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ContactNumber = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
BillingAddress = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
OrganizationSize = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
IndustryId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
Reference = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_TenantEnquires", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_TenantEnquires_Industries_IndustryId",
|
||||||
|
column: x => x.IndustryId,
|
||||||
|
principalTable: "Industries",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "InvoiceAttachments",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
InvoiceId = 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_InvoiceAttachments", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_InvoiceAttachments_Documents_DocumentId",
|
||||||
|
column: x => x.DocumentId,
|
||||||
|
principalTable: "Documents",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_InvoiceAttachments_Invoices_InvoiceId",
|
||||||
|
column: x => x.InvoiceId,
|
||||||
|
principalTable: "Invoices",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_InvoiceAttachments_Tenants_TenantId",
|
||||||
|
column: x => x.TenantId,
|
||||||
|
principalTable: "Tenants",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "InvoiceComments",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
Comment = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
CreatedById = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
InvoiceId = 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_InvoiceComments", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_InvoiceComments_Employees_CreatedById",
|
||||||
|
column: x => x.CreatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_InvoiceComments_Invoices_InvoiceId",
|
||||||
|
column: x => x.InvoiceId,
|
||||||
|
principalTable: "Invoices",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_InvoiceComments_Tenants_TenantId",
|
||||||
|
column: x => x.TenantId,
|
||||||
|
principalTable: "Tenants",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ReceivedInvoicePayments",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
InvoiceId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
PaymentReceivedDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
TransactionId = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Amount = table.Column<double>(type: "double", nullable: false),
|
||||||
|
Comment = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
PaymentAdjustmentHeadId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
CreatedById = 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_ReceivedInvoicePayments", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ReceivedInvoicePayments_Employees_CreatedById",
|
||||||
|
column: x => x.CreatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ReceivedInvoicePayments_Invoices_InvoiceId",
|
||||||
|
column: x => x.InvoiceId,
|
||||||
|
principalTable: "Invoices",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ReceivedInvoicePayments_PaymentAdjustmentHeads_PaymentAdjust~",
|
||||||
|
column: x => x.PaymentAdjustmentHeadId,
|
||||||
|
principalTable: "PaymentAdjustmentHeads",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ReceivedInvoicePayments_Tenants_TenantId",
|
||||||
|
column: x => x.TenantId,
|
||||||
|
principalTable: "Tenants",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "Features",
|
||||||
|
columns: new[] { "Id", "Description", "IsActive", "ModuleId", "Name" },
|
||||||
|
values: new object[] { new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), "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.", true, new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"), "Collection Management" });
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "PaymentAdjustmentHeads",
|
||||||
|
columns: new[] { "Id", "Description", "IsActive", "Name", "TenantId" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("0d70cb2e-827e-44fc-90a5-c2c55ba51ba9"), "TDS, or Tax Deducted at Source, is a system under the Indian Income Tax Act where tax is deducted at the point of income generation—such as salary, interest, or rent—and remitted to the government to prevent tax evasion and ensure timely collection.", true, "Tax Deducted at Source (TDS)", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
|
||||||
|
{ new Guid("3f09b19a-8d45-4cf2-be27-f4f09b38b9f7"), "Tax is a mandatory financial charge imposed by a government on individuals or entities to fund public services and government operations, without direct benefit to the taxpayer.", true, "Tax", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
|
||||||
|
{ new Guid("50584332-1cb7-4359-9721-c8ea35040881"), "Utility fees are recurring charges for essential services such as electricity, water, gas, sewage, waste disposal, internet, and telecommunications, typically based on usage and necessary for operating a home or business.", true, "Utility fees", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
|
||||||
|
{ new Guid("66c3c241-8b52-4327-a5ad-c1faf102583e"), "The base amount refers to the principal sum or original value used as a reference in financial calculations, excluding taxes, fees, or additional charges.", true, "Base Amount", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
|
||||||
|
{ new Guid("95f35acd-d979-4177-91ea-fd03a00e49ff"), "Retention refers to a company's ability to keep customers, employees, or profits over time, commonly measured as a percentage and critical for long-term business sustainability and growth.", true, "Retention", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
|
||||||
|
{ new Guid("dbdc047f-a2d2-4db0-b0e6-b9d9f923a0f1"), "An advance payment is a sum paid before receiving goods or services, often to secure a transaction or cover initial costs.", true, "Advance payment", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") },
|
||||||
|
{ new Guid("ec5e6a5f-ce62-44e5-8911-8426bbb4dde8"), "A penalty in the context of taxation is a financial sanction imposed by the government on individuals or entities for non-compliance with tax laws, such as late filing, underreporting income, or failure to pay taxes, and is typically calculated as a percentage of the tax due or a fixed amount.", true, "Penalty", new Guid("b3466e83-7e11-464c-b93a-daf047838b26") }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "FeaturePermissions",
|
||||||
|
columns: new[] { "Id", "Description", "FeatureId", "IsEnabled", "Name" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("061d9ccd-85b4-4cb0-be06-2f9f32cebb72"), " Enables entry and processing of payment transactions.", new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), true, "Add Payment" },
|
||||||
|
{ new Guid("455187b4-fef1-41f9-b3d0-025d0b6302c3"), "Ability to modify collection properties, content, and access rights.", new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), true, "Edit Collection" },
|
||||||
|
{ new Guid("b93141fd-dbd3-4051-8f57-bf25d18e3555"), "Authorizes users to create new collections for organizing related resources and managing access", new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), true, "Create Collection" },
|
||||||
|
{ new Guid("c8d7eea5-4033-4aad-9ebe-76de49896830"), "View Collection is a permission that allows users to see and browse assets or items within a collection without making any modifications or edits to its contents.", new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), true, "View Collection" },
|
||||||
|
{ new Guid("dbf17591-09fe-4c93-9e1a-12db8f5cc5de"), "Collection Admin is a permission that grants a user full administrative control over collections, including creating, editing, managing access, and deleting collections within a system.", new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"), true, "Collection Admin" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TenantSubscriptions_PaymentDetailId",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
column: "PaymentDetailId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_InvoiceAttachments_DocumentId",
|
||||||
|
table: "InvoiceAttachments",
|
||||||
|
column: "DocumentId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_InvoiceAttachments_InvoiceId",
|
||||||
|
table: "InvoiceAttachments",
|
||||||
|
column: "InvoiceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_InvoiceAttachments_TenantId",
|
||||||
|
table: "InvoiceAttachments",
|
||||||
|
column: "TenantId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_InvoiceComments_CreatedById",
|
||||||
|
table: "InvoiceComments",
|
||||||
|
column: "CreatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_InvoiceComments_InvoiceId",
|
||||||
|
table: "InvoiceComments",
|
||||||
|
column: "InvoiceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_InvoiceComments_TenantId",
|
||||||
|
table: "InvoiceComments",
|
||||||
|
column: "TenantId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Invoices_CreatedById",
|
||||||
|
table: "Invoices",
|
||||||
|
column: "CreatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Invoices_ProjectId",
|
||||||
|
table: "Invoices",
|
||||||
|
column: "ProjectId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Invoices_TenantId",
|
||||||
|
table: "Invoices",
|
||||||
|
column: "TenantId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Invoices_UpdatedById",
|
||||||
|
table: "Invoices",
|
||||||
|
column: "UpdatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PaymentAdjustmentHeads_TenantId",
|
||||||
|
table: "PaymentAdjustmentHeads",
|
||||||
|
column: "TenantId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ReceivedInvoicePayments_CreatedById",
|
||||||
|
table: "ReceivedInvoicePayments",
|
||||||
|
column: "CreatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ReceivedInvoicePayments_InvoiceId",
|
||||||
|
table: "ReceivedInvoicePayments",
|
||||||
|
column: "InvoiceId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ReceivedInvoicePayments_PaymentAdjustmentHeadId",
|
||||||
|
table: "ReceivedInvoicePayments",
|
||||||
|
column: "PaymentAdjustmentHeadId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ReceivedInvoicePayments_TenantId",
|
||||||
|
table: "ReceivedInvoicePayments",
|
||||||
|
column: "TenantId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TenantEnquires_IndustryId",
|
||||||
|
table: "TenantEnquires",
|
||||||
|
column: "IndustryId");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_TenantSubscriptions_PaymentDetails_PaymentDetailId",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
column: "PaymentDetailId",
|
||||||
|
principalTable: "PaymentDetails",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_TenantSubscriptions_PaymentDetails_PaymentDetailId",
|
||||||
|
table: "TenantSubscriptions");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "InvoiceAttachments");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "InvoiceComments");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PaymentDetails");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ReceivedInvoicePayments");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "TenantEnquires");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Invoices");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PaymentAdjustmentHeads");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_TenantSubscriptions_PaymentDetailId",
|
||||||
|
table: "TenantSubscriptions");
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "FeaturePermissions",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("061d9ccd-85b4-4cb0-be06-2f9f32cebb72"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "FeaturePermissions",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("455187b4-fef1-41f9-b3d0-025d0b6302c3"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "FeaturePermissions",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("b93141fd-dbd3-4051-8f57-bf25d18e3555"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "FeaturePermissions",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("c8d7eea5-4033-4aad-9ebe-76de49896830"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "FeaturePermissions",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("dbf17591-09fe-4c93-9e1a-12db8f5cc5de"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "Features",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("fc586e7d-ed1a-45e5-bb51-9f34af98ec13"));
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PaymentDetailId",
|
||||||
|
table: "TenantSubscriptions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,438 @@
|
|||||||
|
using System;
|
||||||
|
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_PaymentRequest_RecurringPayment_AdvancePayment_Related_Tables : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PaymentModeMatser_Tenants_TenantId",
|
||||||
|
table: "PaymentModeMatser");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_PaymentModeMatser_TenantId",
|
||||||
|
table: "PaymentModeMatser");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "TenantId",
|
||||||
|
table: "PaymentModeMatser");
|
||||||
|
|
||||||
|
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),
|
||||||
|
EmployeeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
Amount = table.Column<double>(type: "double", 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_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: false),
|
||||||
|
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"),
|
||||||
|
ExpenseStatusId = 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"),
|
||||||
|
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: 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_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",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_RecurringPayments_ExpensesStatusMaster_ExpenseStatusId",
|
||||||
|
column: x => x.ExpenseStatusId,
|
||||||
|
principalTable: "ExpensesStatusMaster",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_RecurringPayments_ExpensesStatusMaster_StatusId",
|
||||||
|
column: x => x.StatusId,
|
||||||
|
principalTable: "ExpensesStatusMaster",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_RecurringPayments_ExpensesTypeMaster_ExpenseCategoryId",
|
||||||
|
column: x => x.ExpenseCategoryId,
|
||||||
|
principalTable: "ExpensesTypeMaster",
|
||||||
|
principalColumn: "Id");
|
||||||
|
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: "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"),
|
||||||
|
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: "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"),
|
||||||
|
CurrencyId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
Amount = table.Column<double>(type: "double", nullable: false),
|
||||||
|
DueDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
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"),
|
||||||
|
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: 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_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_UpdatedById",
|
||||||
|
column: x => x.UpdatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_PaymentRequests_ExpensesStatusMaster_ExpenseStatusId",
|
||||||
|
column: x => x.ExpenseStatusId,
|
||||||
|
principalTable: "ExpensesStatusMaster",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_PaymentRequests_ExpensesTypeMaster_ExpenseCategoryId",
|
||||||
|
column: x => x.ExpenseCategoryId,
|
||||||
|
principalTable: "ExpensesTypeMaster",
|
||||||
|
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.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.CreateIndex(
|
||||||
|
name: "IX_AdvancePaymentTransactions_CreatedById",
|
||||||
|
table: "AdvancePaymentTransactions",
|
||||||
|
column: "CreatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AdvancePaymentTransactions_EmployeeId",
|
||||||
|
table: "AdvancePaymentTransactions",
|
||||||
|
column: "EmployeeId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AdvancePaymentTransactions_TenantId",
|
||||||
|
table: "AdvancePaymentTransactions",
|
||||||
|
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_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_ExpenseStatusId",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
column: "ExpenseStatusId");
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AdvancePaymentTransactions");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PaymentRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "StatusUpdateLogs");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "RecurringPayments");
|
||||||
|
|
||||||
|
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.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: "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.AddForeignKey(
|
||||||
|
name: "FK_PaymentModeMatser_Tenants_TenantId",
|
||||||
|
table: "PaymentModeMatser",
|
||||||
|
column: "TenantId",
|
||||||
|
principalTable: "Tenants",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Added_ProjectId_In_PaymentRequest_RecurringPayment_Tables : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "ProjectId",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: true,
|
||||||
|
collation: "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "ProjectId",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: true,
|
||||||
|
collation: "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_RecurringPayments_ProjectId",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
column: "ProjectId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PaymentRequests_ProjectId",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
column: "ProjectId");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_PaymentRequests_Projects_ProjectId",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
column: "ProjectId",
|
||||||
|
principalTable: "Projects",
|
||||||
|
principalColumn: "Id");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_RecurringPayments_Projects_ProjectId",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
column: "ProjectId",
|
||||||
|
principalTable: "Projects",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PaymentRequests_Projects_ProjectId",
|
||||||
|
table: "PaymentRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_RecurringPayments_Projects_ProjectId",
|
||||||
|
table: "RecurringPayments");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_RecurringPayments_ProjectId",
|
||||||
|
table: "RecurringPayments");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_PaymentRequests_ProjectId",
|
||||||
|
table: "PaymentRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ProjectId",
|
||||||
|
table: "RecurringPayments");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ProjectId",
|
||||||
|
table: "PaymentRequests");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7221
Marco.Pms.DataAccess/Migrations/20251101070254_Added_CurrentBalance_In_AdvancePayment_Tables.Designer.cs
generated
Normal file
7221
Marco.Pms.DataAccess/Migrations/20251101070254_Added_CurrentBalance_In_AdvancePayment_Tables.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Added_CurrentBalance_In_AdvancePayment_Tables : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<double>(
|
||||||
|
name: "CurrentBalance",
|
||||||
|
table: "AdvancePaymentTransactions",
|
||||||
|
type: "double",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "CurrentBalance",
|
||||||
|
table: "AdvancePaymentTransactions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7217
Marco.Pms.DataAccess/Migrations/20251101085801_Made_UpdatedBy_And_UpdateAt_As_Nullable.Designer.cs
generated
Normal file
7217
Marco.Pms.DataAccess/Migrations/20251101085801_Made_UpdatedBy_And_UpdateAt_As_Nullable.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,145 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Made_UpdatedBy_And_UpdateAt_As_Nullable : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PaymentRequests_Employees_UpdatedById",
|
||||||
|
table: "PaymentRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_RecurringPayments_Employees_UpdatedById",
|
||||||
|
table: "RecurringPayments");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<Guid>(
|
||||||
|
name: "UpdatedById",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: true,
|
||||||
|
collation: "ascii_general_ci",
|
||||||
|
oldClrType: typeof(Guid),
|
||||||
|
oldType: "char(36)")
|
||||||
|
.OldAnnotation("Relational:Collation", "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "UpdatedAt",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
type: "datetime(6)",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "datetime(6)");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<Guid>(
|
||||||
|
name: "UpdatedById",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: true,
|
||||||
|
collation: "ascii_general_ci",
|
||||||
|
oldClrType: typeof(Guid),
|
||||||
|
oldType: "char(36)")
|
||||||
|
.OldAnnotation("Relational:Collation", "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "UpdatedAt",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
type: "datetime(6)",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "datetime(6)");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_PaymentRequests_Employees_UpdatedById",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
column: "UpdatedById",
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_RecurringPayments_Employees_UpdatedById",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
column: "UpdatedById",
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PaymentRequests_Employees_UpdatedById",
|
||||||
|
table: "PaymentRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_RecurringPayments_Employees_UpdatedById",
|
||||||
|
table: "RecurringPayments");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<Guid>(
|
||||||
|
name: "UpdatedById",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||||
|
collation: "ascii_general_ci",
|
||||||
|
oldClrType: typeof(Guid),
|
||||||
|
oldType: "char(36)",
|
||||||
|
oldNullable: true)
|
||||||
|
.OldAnnotation("Relational:Collation", "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "UpdatedAt",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
type: "datetime(6)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "datetime(6)",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<Guid>(
|
||||||
|
name: "UpdatedById",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||||
|
collation: "ascii_general_ci",
|
||||||
|
oldClrType: typeof(Guid),
|
||||||
|
oldType: "char(36)",
|
||||||
|
oldNullable: true)
|
||||||
|
.OldAnnotation("Relational:Collation", "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "UpdatedAt",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
type: "datetime(6)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "datetime(6)",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_PaymentRequests_Employees_UpdatedById",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
column: "UpdatedById",
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_RecurringPayments_Employees_UpdatedById",
|
||||||
|
table: "RecurringPayments",
|
||||||
|
column: "UpdatedById",
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7317
Marco.Pms.DataAccess/Migrations/20251101101344_Added_PaymentRequestAttachmnets_Table.Designer.cs
generated
Normal file
7317
Marco.Pms.DataAccess/Migrations/20251101101344_Added_PaymentRequestAttachmnets_Table.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,209 @@
|
|||||||
|
using System;
|
||||||
|
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_PaymentRequestAttachmnets_Table : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PaymentRequests_ExpensesTypeMaster_ExpenseCategoryId",
|
||||||
|
table: "PaymentRequests");
|
||||||
|
|
||||||
|
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.AddColumn<bool>(
|
||||||
|
name: "IsAdvancePayment",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
type: "tinyint(1)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
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: "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.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.AddForeignKey(
|
||||||
|
name: "FK_PaymentRequests_ExpenseCategoryMasters_ExpenseCategoryId",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
column: "ExpenseCategoryId",
|
||||||
|
principalTable: "ExpenseCategoryMasters",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PaymentRequests_ExpenseCategoryMasters_ExpenseCategoryId",
|
||||||
|
table: "PaymentRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ExpenseCategoryMasters");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PaymentRequestAttachments");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsAdvancePayment",
|
||||||
|
table: "PaymentRequests");
|
||||||
|
|
||||||
|
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.AddForeignKey(
|
||||||
|
name: "FK_PaymentRequests_ExpensesTypeMaster_ExpenseCategoryId",
|
||||||
|
table: "PaymentRequests",
|
||||||
|
column: "ExpenseCategoryId",
|
||||||
|
principalTable: "ExpensesTypeMaster",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -234,6 +234,27 @@ namespace Marco.Pms.Helpers.CacheHelper
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public async Task<bool> ClearAllEmployeesFromCacheByTenantId(Guid tenantId)
|
||||||
|
{
|
||||||
|
var tenantIdString = tenantId.ToString();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<EmployeePermissionMongoDB>.Filter.Eq(e => e.TenantId, tenantIdString);
|
||||||
|
|
||||||
|
var result = await _collection.DeleteManyAsync(filter);
|
||||||
|
|
||||||
|
if (result.DeletedCount == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occured while deleting employee profile");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A private method to handle the one-time setup of the collection's indexes.
|
// A private method to handle the one-time setup of the collection's indexes.
|
||||||
private async Task InitializeCollectionAsync()
|
private async Task InitializeCollectionAsync()
|
||||||
|
|||||||
@ -19,6 +19,8 @@ namespace Marco.Pms.Model.AttendanceModule
|
|||||||
public Guid ProjectID { get; set; }
|
public Guid ProjectID { get; set; }
|
||||||
|
|
||||||
public DateTime AttendanceDate { get; set; }
|
public DateTime AttendanceDate { get; set; }
|
||||||
|
public DateTime? RequestedAt { get; set; }
|
||||||
|
public DateTime? ApprovedAt { get; set; }
|
||||||
public DateTime? InTime { get; set; }
|
public DateTime? InTime { get; set; }
|
||||||
public DateTime? OutTime { get; set; }
|
public DateTime? OutTime { get; set; }
|
||||||
public bool IsApproved { get; set; }
|
public bool IsApproved { get; set; }
|
||||||
@ -29,5 +31,10 @@ namespace Marco.Pms.Model.AttendanceModule
|
|||||||
[ForeignKey("ApprovedById")]
|
[ForeignKey("ApprovedById")]
|
||||||
[ValidateNever]
|
[ValidateNever]
|
||||||
public Employee? Approver { get; set; }
|
public Employee? Approver { get; set; }
|
||||||
|
public Guid? RequestedById { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("RequestedById")]
|
||||||
|
[ValidateNever]
|
||||||
|
public Employee? RequestedBy { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
Marco.Pms.Model/Collection/Invoice.cs
Normal file
41
Marco.Pms.Model/Collection/Invoice.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
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.Collection
|
||||||
|
{
|
||||||
|
public class Invoice : TenantRelation
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Title { get; set; } = default!;
|
||||||
|
public string Description { get; set; } = default!;
|
||||||
|
public string InvoiceNumber { get; set; } = default!;
|
||||||
|
public string? EInvoiceNumber { get; set; }
|
||||||
|
public Guid ProjectId { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("ProjectId")]
|
||||||
|
public Project? Project { get; set; }
|
||||||
|
public DateTime InvoiceDate { get; set; }
|
||||||
|
public DateTime ClientSubmitedDate { get; set; }
|
||||||
|
public DateTime ExceptedPaymentDate { get; set; }
|
||||||
|
public double BasicAmount { get; set; }
|
||||||
|
public double TaxAmount { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
public bool MarkAsCompleted { get; set; } = true;
|
||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Marco.Pms.Model/Collection/InvoiceAttachment.cs
Normal file
22
Marco.Pms.Model/Collection/InvoiceAttachment.cs
Normal 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.Collection
|
||||||
|
{
|
||||||
|
public class InvoiceAttachment : TenantRelation
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public Guid InvoiceId { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("InvoiceId")]
|
||||||
|
public Invoice? Invoice { get; set; }
|
||||||
|
public Guid DocumentId { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("DocumentId")]
|
||||||
|
public Document? Document { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Marco.Pms.Model/Collection/InvoiceComment.cs
Normal file
24
Marco.Pms.Model/Collection/InvoiceComment.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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.Collection
|
||||||
|
{
|
||||||
|
public class InvoiceComment : TenantRelation
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Comment { get; set; } = default!;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public Guid CreatedById { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("CreatedById")]
|
||||||
|
public Employee? CreatedBy { get; set; }
|
||||||
|
public Guid InvoiceId { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("InvoiceId")]
|
||||||
|
public Invoice? Invoice { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Marco.Pms.Model/Collection/PaymentAdjustmentHead.cs
Normal file
12
Marco.Pms.Model/Collection/PaymentAdjustmentHead.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Marco.Pms.Model.Utilities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.Collection
|
||||||
|
{
|
||||||
|
public class PaymentAdjustmentHead : TenantRelation
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Name { get; set; } = default!;
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
Marco.Pms.Model/Collection/ReceivedInvoicePayment.cs
Normal file
33
Marco.Pms.Model/Collection/ReceivedInvoicePayment.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
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.Collection
|
||||||
|
{
|
||||||
|
public class ReceivedInvoicePayment : TenantRelation
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public Guid InvoiceId { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("InvoiceId")]
|
||||||
|
public Invoice? Invoice { get; set; }
|
||||||
|
public DateTime PaymentReceivedDate { get; set; }
|
||||||
|
public string TransactionId { get; set; } = default!;
|
||||||
|
public double Amount { get; set; }
|
||||||
|
public string Comment { get; set; } = default!;
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
public Guid PaymentAdjustmentHeadId { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("PaymentAdjustmentHeadId")]
|
||||||
|
public PaymentAdjustmentHead? PaymentAdjustmentHead { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public Guid CreatedById { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("CreatedById")]
|
||||||
|
public Employee? CreatedBy { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public class CreateWorkStatusMasterDto
|
public class CreateWorkStatusMasterDto
|
||||||
{
|
{
|
||||||
public string? Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public required string Description { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
public class UpdateWorkStatusMasterDto
|
public class UpdateWorkStatusMasterDto
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public string? Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public required string Description { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,5 @@
|
|||||||
public required Guid EmployeeId { get; set; }
|
public required Guid EmployeeId { get; set; }
|
||||||
public required string MPIN { get; set; }
|
public required string MPIN { get; set; }
|
||||||
public required string MPINToken { get; set; }
|
public required string MPINToken { get; set; }
|
||||||
public required string FcmToken { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
Marco.Pms.Model/Dtos/Collection/InvoiceCommentDto.cs
Normal file
8
Marco.Pms.Model/Dtos/Collection/InvoiceCommentDto.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Collection
|
||||||
|
{
|
||||||
|
public class InvoiceCommentDto
|
||||||
|
{
|
||||||
|
public required string Comment { get; set; }
|
||||||
|
public required Guid InvoiceId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Marco.Pms.Model/Dtos/Collection/InvoiceDto.cs
Normal file
20
Marco.Pms.Model/Dtos/Collection/InvoiceDto.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using Marco.Pms.Model.Utilities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.Dtos.Collection
|
||||||
|
{
|
||||||
|
public class InvoiceDto
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
public required string Title { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public required string InvoiceNumber { get; set; }
|
||||||
|
public string? EInvoiceNumber { get; set; }
|
||||||
|
public required Guid ProjectId { get; set; }
|
||||||
|
public required DateTime InvoiceDate { get; set; }
|
||||||
|
public required DateTime ClientSubmitedDate { get; set; }
|
||||||
|
public required DateTime ExceptedPaymentDate { get; set; }
|
||||||
|
public double BasicAmount { get; set; }
|
||||||
|
public double TaxAmount { get; set; }
|
||||||
|
public List<FileUploadModel>? Attachments { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Collection
|
||||||
|
{
|
||||||
|
public class PaymentAdjustmentHeadDto
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
public required string Name { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Marco.Pms.Model/Dtos/Collection/ReceivedInvoicePaymentDto.cs
Normal file
13
Marco.Pms.Model/Dtos/Collection/ReceivedInvoicePaymentDto.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Collection
|
||||||
|
{
|
||||||
|
public class ReceivedInvoicePaymentDto
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
public required Guid InvoiceId { get; set; }
|
||||||
|
public required DateTime PaymentReceivedDate { get; set; }
|
||||||
|
public required string TransactionId { get; set; }
|
||||||
|
public required Guid PaymentAdjustmentHeadId { get; set; }
|
||||||
|
public required double Amount { get; set; }
|
||||||
|
public required string Comment { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,7 +19,7 @@
|
|||||||
public string? EmergencyPhoneNumber { get; set; }
|
public string? EmergencyPhoneNumber { get; set; }
|
||||||
public string? EmergencyContactPerson { get; set; }
|
public string? EmergencyContactPerson { get; set; }
|
||||||
public Guid JobRoleId { get; set; }
|
public Guid JobRoleId { get; set; }
|
||||||
public required Guid OrganizationId { get; set; }
|
public Guid? OrganizationId { get; set; }
|
||||||
public required bool HasApplicationAccess { get; set; }
|
public required bool HasApplicationAccess { get; set; }
|
||||||
}
|
}
|
||||||
public class MobileUserManageDto
|
public class MobileUserManageDto
|
||||||
@ -33,7 +33,7 @@
|
|||||||
public required string Gender { get; set; }
|
public required string Gender { get; set; }
|
||||||
public Guid JobRoleId { get; set; }
|
public Guid JobRoleId { get; set; }
|
||||||
public string? ProfileImage { get; set; }
|
public string? ProfileImage { get; set; }
|
||||||
public required Guid OrganizationId { get; set; }
|
public Guid? OrganizationId { get; set; }
|
||||||
public required bool HasApplicationAccess { get; set; }
|
public required bool HasApplicationAccess { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
19
Marco.Pms.Model/Dtos/Expenses/PaymentRequestDto.cs
Normal file
19
Marco.Pms.Model/Dtos/Expenses/PaymentRequestDto.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public class CreateContactCategoryDto
|
public class CreateContactCategoryDto
|
||||||
{
|
{
|
||||||
public string? Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public required string Description { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public class CreateContactTagDto
|
public class CreateContactTagDto
|
||||||
{
|
{
|
||||||
public string? Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
public class UpdateContactCategoryDto
|
public class UpdateContactCategoryDto
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public string? Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public required string Description { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
Marco.Pms.Model/Dtos/PaymentGetway/CreateOrderDto.cs
Normal file
7
Marco.Pms.Model/Dtos/PaymentGetway/CreateOrderDto.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.PaymentGetway
|
||||||
|
{
|
||||||
|
public class CreateOrderDto
|
||||||
|
{
|
||||||
|
public double Amount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.PaymentGetway
|
||||||
|
{
|
||||||
|
public class PaymentVerificationRequest
|
||||||
|
{
|
||||||
|
public required Guid TenantEnquireId { get; set; }
|
||||||
|
public required Guid PlanId { get; set; }
|
||||||
|
public required string OrderId { get; set; }
|
||||||
|
public required string PaymentId { get; set; }
|
||||||
|
public required string Signature { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -27,7 +27,7 @@ namespace Marco.Pms.Model.Dtos.Project
|
|||||||
[DisplayName("Project Status")]
|
[DisplayName("Project Status")]
|
||||||
[Required(ErrorMessage = "Project Status is required!")]
|
[Required(ErrorMessage = "Project Status is required!")]
|
||||||
public required Guid ProjectStatusId { get; set; }
|
public required Guid ProjectStatusId { get; set; }
|
||||||
public required Guid PromoterId { get; set; }
|
public Guid? PromoterId { get; set; }
|
||||||
public required Guid PMCId { get; set; }
|
public Guid? PMCId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ namespace Marco.Pms.Model.Dtos.Project
|
|||||||
[DisplayName("Project Status")]
|
[DisplayName("Project Status")]
|
||||||
[Required(ErrorMessage = "Project Status is required!")]
|
[Required(ErrorMessage = "Project Status is required!")]
|
||||||
public required Guid ProjectStatusId { get; set; }
|
public required Guid ProjectStatusId { get; set; }
|
||||||
public required Guid PromoterId { get; set; }
|
public Guid? PromoterId { get; set; }
|
||||||
public required Guid PMCId { get; set; }
|
public Guid? PMCId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
Marco.Pms.Model/Dtos/Tenant/RenewSubscriptionDto.cs
Normal file
8
Marco.Pms.Model/Dtos/Tenant/RenewSubscriptionDto.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class RenewSubscriptionDto
|
||||||
|
{
|
||||||
|
public Guid PaymentDetailId { get; set; }
|
||||||
|
public Guid PlanId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Marco.Pms.Model/Dtos/Tenant/SelfSubscriptionDto.cs
Normal file
9
Marco.Pms.Model/Dtos/Tenant/SelfSubscriptionDto.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class SelfSubscriptionDto
|
||||||
|
{
|
||||||
|
public Guid TenantEnquireId { get; set; }
|
||||||
|
public Guid PaymentDetailId { get; set; }
|
||||||
|
public Guid PlanId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Marco.Pms.Model/Dtos/Tenant/TenantEnquireDto.cs
Normal file
15
Marco.Pms.Model/Dtos/Tenant/TenantEnquireDto.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class TenantEnquireDto
|
||||||
|
{
|
||||||
|
public required string FirstName { get; set; }
|
||||||
|
public required string LastName { get; set; }
|
||||||
|
public required string OrganizationName { get; set; }
|
||||||
|
public required string Email { get; set; }
|
||||||
|
public required string ContactNumber { get; set; }
|
||||||
|
public required string BillingAddress { get; set; }
|
||||||
|
public required string OrganizationSize { get; set; }
|
||||||
|
public required Guid IndustryId { get; set; }
|
||||||
|
public required string Reference { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -47,6 +47,12 @@
|
|||||||
public static readonly Guid DownloadDocument = Guid.Parse("404373d0-860f-490e-a575-1c086ffbce1d");
|
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 VerifyDocument = Guid.Parse("13a1f30f-38d1-41bf-8e7a-b75189aab8e0");
|
||||||
|
|
||||||
|
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");
|
||||||
|
public static readonly Guid EditCollection = Guid.Parse("455187b4-fef1-41f9-b3d0-025d0b6302c3");
|
||||||
|
public static readonly Guid AddPayment = Guid.Parse("061d9ccd-85b4-4cb0-be06-2f9f32cebb72");
|
||||||
|
|
||||||
public static readonly Guid AddOrganization = Guid.Parse("068cb3c1-49c5-4746-9f29-1fce16e820ac");
|
public static readonly Guid AddOrganization = Guid.Parse("068cb3c1-49c5-4746-9f29-1fce16e820ac");
|
||||||
public static readonly Guid EditOrganization = Guid.Parse("c1ae1363-ab8a-4bd9-a9d1-8c2c6083873a");
|
public static readonly Guid EditOrganization = Guid.Parse("c1ae1363-ab8a-4bd9-a9d1-8c2c6083873a");
|
||||||
public static readonly Guid ViewOrganization = Guid.Parse("7a6cf830-0008-4e03-b31d-0d050cb634f4");
|
public static readonly Guid ViewOrganization = Guid.Parse("7a6cf830-0008-4e03-b31d-0d050cb634f4");
|
||||||
|
|||||||
28
Marco.Pms.Model/Expenses/AdvancePaymentTransaction.cs
Normal file
28
Marco.Pms.Model/Expenses/AdvancePaymentTransaction.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
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.Expenses
|
||||||
|
{
|
||||||
|
public class AdvancePaymentTransaction : TenantRelation
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string FinanceUIdPrefix { get; set; } = default!;
|
||||||
|
public int FinanceUIdPostfix { 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 CreatedAt { get; set; }
|
||||||
|
public Guid CreatedById { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("CreatedById")]
|
||||||
|
public Employee? CreatedBy { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Marco.Pms.Model/Expenses/ExpenseCategoryMaster.cs
Normal file
14
Marco.Pms.Model/Expenses/ExpenseCategoryMaster.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using Marco.Pms.Model.Utilities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.Expenses
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -54,6 +54,7 @@ namespace Marco.Pms.Model.Expenses
|
|||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
public string? TransactionId { get; set; }
|
public string? TransactionId { get; set; }
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
|
public string ExpenseUId { get; set; } = string.Empty;
|
||||||
public string? Location { get; set; }
|
public string? Location { get; set; }
|
||||||
public string? GSTNumber { get; set; }
|
public string? GSTNumber { get; set; }
|
||||||
public string SupplerName { get; set; } = string.Empty;
|
public string SupplerName { get; set; } = string.Empty;
|
||||||
|
|||||||
60
Marco.Pms.Model/Expenses/PaymentRequest.cs
Normal file
60
Marco.Pms.Model/Expenses/PaymentRequest.cs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
using Marco.Pms.Model.Employees;
|
||||||
|
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 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 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Marco.Pms.Model/Expenses/PaymentRequestAttachment.cs
Normal file
22
Marco.Pms.Model/Expenses/PaymentRequestAttachment.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
66
Marco.Pms.Model/Expenses/RecurringPayment.cs
Normal file
66
Marco.Pms.Model/Expenses/RecurringPayment.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using Marco.Pms.Model.Employees;
|
||||||
|
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 ExpensesTypeMaster? ExpenseCategory { get; set; }
|
||||||
|
public Guid ExpenseStatusId { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("ExpenseStatusId")]
|
||||||
|
public ExpensesStatusMaster? ExpenseStatus { get; set; }
|
||||||
|
public Guid StatusId { get; set; }
|
||||||
|
|
||||||
|
[ValidateNever]
|
||||||
|
[ForeignKey("StatusId")]
|
||||||
|
public ExpensesStatusMaster? 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@
|
|||||||
public List<Guid>? StatusIds { get; set; }
|
public List<Guid>? StatusIds { get; set; }
|
||||||
public List<Guid>? CreatedByIds { get; set; }
|
public List<Guid>? CreatedByIds { get; set; }
|
||||||
public List<Guid>? PaidById { get; set; }
|
public List<Guid>? PaidById { get; set; }
|
||||||
|
public List<Guid>? ExpenseTypeIds { get; set; }
|
||||||
public bool IsTransactionDate { get; set; } = false;
|
public bool IsTransactionDate { get; set; } = false;
|
||||||
public DateTime? StartDate { get; set; }
|
public DateTime? StartDate { get; set; }
|
||||||
public DateTime? EndDate { get; set; }
|
public DateTime? EndDate { get; set; }
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
public List<Guid>? BuildingIds { get; set; }
|
public List<Guid>? BuildingIds { get; set; }
|
||||||
public List<Guid>? FloorIds { get; set; }
|
public List<Guid>? FloorIds { get; set; }
|
||||||
public List<Guid>? ActivityIds { get; set; }
|
public List<Guid>? ActivityIds { get; set; }
|
||||||
|
public List<Guid>? ServiceIds { get; set; }
|
||||||
public DateTime? dateFrom { get; set; }
|
public DateTime? dateFrom { get; set; }
|
||||||
public DateTime? dateTo { get; set; }
|
public DateTime? dateTo { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 Guid Id { get; set; }
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
|
|||||||
21
Marco.Pms.Model/Master/StatusUpdateLog.cs
Normal file
21
Marco.Pms.Model/Master/StatusUpdateLog.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,6 +20,7 @@ namespace Marco.Pms.Model.MongoDBModels.Expenses
|
|||||||
public DateTime ExpireAt { get; set; } = DateTime.UtcNow.Date.AddDays(1);
|
public DateTime ExpireAt { get; set; } = DateTime.UtcNow.Date.AddDays(1);
|
||||||
public string SupplerName { get; set; } = string.Empty;
|
public string SupplerName { get; set; } = string.Empty;
|
||||||
public double Amount { get; set; }
|
public double Amount { get; set; }
|
||||||
|
public string? ExpenseUId { get; set; }
|
||||||
public ExpensesStatusMasterMongoDB Status { get; set; } = new ExpensesStatusMasterMongoDB();
|
public ExpensesStatusMasterMongoDB Status { get; set; } = new ExpensesStatusMasterMongoDB();
|
||||||
public List<ExpensesStatusMasterMongoDB> NextStatus { get; set; } = new List<ExpensesStatusMasterMongoDB>();
|
public List<ExpensesStatusMasterMongoDB> NextStatus { get; set; } = new List<ExpensesStatusMasterMongoDB>();
|
||||||
public bool PreApproved { get; set; } = false;
|
public bool PreApproved { get; set; } = false;
|
||||||
|
|||||||
@ -5,6 +5,5 @@
|
|||||||
public string Id { get; set; } = string.Empty;
|
public string Id { get; set; } = string.Empty;
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
public string TenantId { get; set; } = string.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
Marco.Pms.Model/PaymentGetway/PaymentDetail.cs
Normal file
16
Marco.Pms.Model/PaymentGetway/PaymentDetail.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
namespace Marco.Pms.Model.PaymentGetway
|
||||||
|
{
|
||||||
|
public class PaymentDetail
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string PaymentId { get; set; } = string.Empty;
|
||||||
|
public string OrderId { get; set; } = string.Empty;
|
||||||
|
public string Status { get; set; } = string.Empty; // created, authorized, captured, refunded, failed
|
||||||
|
public string Method { get; set; } = string.Empty;
|
||||||
|
public byte[]? EncryptedDetails { get; set; }
|
||||||
|
public byte[]? Nonce { get; set; }
|
||||||
|
public byte[]? Tag { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,6 @@
|
|||||||
|
|
||||||
public enum PLAN_FREQUENCY
|
public enum PLAN_FREQUENCY
|
||||||
{
|
{
|
||||||
MONTHLY = 0, QUARTERLY = 1, HALF_YEARLY = 2, YEARLY = 3
|
MONTHLY = 0, QUARTERLY = 1, HALF_YEARLY = 2, YEARLY = 3, DAILY = 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
Marco.Pms.Model/TenantModels/TenantEnquire.cs
Normal file
24
Marco.Pms.Model/TenantModels/TenantEnquire.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using Marco.Pms.Model.Master;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels
|
||||||
|
{
|
||||||
|
public class TenantEnquire
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string FirstName { get; set; } = default!;
|
||||||
|
public string LastName { get; set; } = default!;
|
||||||
|
public string OrganizationName { get; set; } = default!;
|
||||||
|
public string Email { get; set; } = default!;
|
||||||
|
public string ContactNumber { get; set; } = default!;
|
||||||
|
public string BillingAddress { get; set; } = default!;
|
||||||
|
public string OrganizationSize { get; set; } = default!;
|
||||||
|
public Guid IndustryId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("IndustryId")]
|
||||||
|
[ValidateNever]
|
||||||
|
public Industry? Industry { get; set; }
|
||||||
|
public string Reference { get; set; } = default!;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using Marco.Pms.Model.Employees;
|
using Marco.Pms.Model.Employees;
|
||||||
using Marco.Pms.Model.Master;
|
using Marco.Pms.Model.Master;
|
||||||
|
using Marco.Pms.Model.PaymentGetway;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
@ -28,6 +29,11 @@ namespace Marco.Pms.Model.TenantModels
|
|||||||
[ForeignKey("CurrencyId")]
|
[ForeignKey("CurrencyId")]
|
||||||
[ValidateNever]
|
[ValidateNever]
|
||||||
public CurrencyMaster? Currency { get; set; }
|
public CurrencyMaster? Currency { get; set; }
|
||||||
|
public Guid? PaymentDetailId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("PaymentDetailId")]
|
||||||
|
[ValidateNever]
|
||||||
|
public PaymentDetail? PaymentDetail { get; set; }
|
||||||
public DateTime NextBillingDate { get; set; }
|
public DateTime NextBillingDate { get; set; }
|
||||||
public DateTime? CancellationDate { get; set; }
|
public DateTime? CancellationDate { get; set; }
|
||||||
public bool AutoRenew { get; set; } = true;
|
public bool AutoRenew { get; set; } = true;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Marco.Pms.Model.Dtos.Attendance;
|
using Marco.Pms.Model.Dtos.Attendance;
|
||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
|
||||||
namespace Marco.Pms.Model.ViewModels.AttendanceVM
|
namespace Marco.Pms.Model.ViewModels.AttendanceVM
|
||||||
{
|
{
|
||||||
@ -6,15 +7,20 @@ namespace Marco.Pms.Model.ViewModels.AttendanceVM
|
|||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public Guid EmployeeId { get; set; }
|
public Guid EmployeeId { get; set; }
|
||||||
|
public Guid ProjectId { get; set; }
|
||||||
public string? FirstName { get; set; }
|
public string? FirstName { get; set; }
|
||||||
public string? LastName { get; set; }
|
public string? LastName { get; set; }
|
||||||
public string? EmployeeAvatar { get; set; }
|
public string? EmployeeAvatar { get; set; }
|
||||||
public string? OrganizationName { get; set; }
|
public string? OrganizationName { get; set; }
|
||||||
|
public string? ProjectName { get; set; }
|
||||||
public DateTime? CheckInTime { get; set; }
|
public DateTime? CheckInTime { get; set; }
|
||||||
public DateTime? CheckOutTime { get; set; }
|
public DateTime? CheckOutTime { get; set; }
|
||||||
|
public DateTime? RequestedAt { get; set; }
|
||||||
|
public DateTime? ApprovedAt { get; set; }
|
||||||
public string? JobRoleName { get; set; }
|
public string? JobRoleName { get; set; }
|
||||||
public ATTENDANCE_MARK_TYPE Activity { get; set; }
|
public ATTENDANCE_MARK_TYPE Activity { get; set; }
|
||||||
|
public BasicEmployeeVM? Approver { get; set; }
|
||||||
|
public BasicEmployeeVM? RequestedBy { get; set; }
|
||||||
public Guid? DocumentId { get; set; }
|
public Guid? DocumentId { get; set; }
|
||||||
public string? ThumbPreSignedUrl { get; set; }
|
public string? ThumbPreSignedUrl { get; set; }
|
||||||
public string? PreSignedUrl { get; set; }
|
public string? PreSignedUrl { get; set; }
|
||||||
|
|||||||
16
Marco.Pms.Model/ViewModels/Collection/InvoiceAttachmentVM.cs
Normal file
16
Marco.Pms.Model/ViewModels/Collection/InvoiceAttachmentVM.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.ViewModels.Collection
|
||||||
|
{
|
||||||
|
public class InvoiceAttachmentVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public Guid InvoiceId { get; set; }
|
||||||
|
public Guid DocumentId { get; set; }
|
||||||
|
public string? FileName { get; set; }
|
||||||
|
public string? ContentType { get; set; }
|
||||||
|
public string? PreSignedUrl { get; set; }
|
||||||
|
public BasicEmployeeVM? UploadedBy { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Marco.Pms.Model/ViewModels/Collection/InvoiceCommentVM.cs
Normal file
13
Marco.Pms.Model/ViewModels/Collection/InvoiceCommentVM.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.ViewModels.Collection
|
||||||
|
{
|
||||||
|
public class InvoiceCommentVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Comment { get; set; } = default!;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||||
|
public Guid InvoiceId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
31
Marco.Pms.Model/ViewModels/Collection/InvoiceDetailsVM.cs
Normal file
31
Marco.Pms.Model/ViewModels/Collection/InvoiceDetailsVM.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
using Marco.Pms.Model.ViewModels.Projects;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.ViewModels.Collection
|
||||||
|
{
|
||||||
|
public class InvoiceDetailsVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Title { get; set; } = default!;
|
||||||
|
public string Description { get; set; } = default!;
|
||||||
|
public string InvoiceNumber { get; set; } = default!;
|
||||||
|
public string? EInvoiceNumber { get; set; }
|
||||||
|
public BasicProjectVM? Project { get; set; }
|
||||||
|
public DateTime InvoiceDate { get; set; }
|
||||||
|
public DateTime ClientSubmitedDate { get; set; }
|
||||||
|
public DateTime ExceptedPaymentDate { get; set; }
|
||||||
|
public double BasicAmount { get; set; }
|
||||||
|
public double TaxAmount { get; set; }
|
||||||
|
public double BalanceAmount { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
public bool MarkAsCompleted { get; set; } = true;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
public BasicEmployeeVM? UpdatedBy { get; set; }
|
||||||
|
public List<InvoiceAttachmentVM>? Attachments { get; set; }
|
||||||
|
public List<ReceivedInvoicePaymentVM>? ReceivedInvoicePayments { get; set; }
|
||||||
|
public List<InvoiceCommentVM>? Comments { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Marco.Pms.Model/ViewModels/Collection/InvoiceListVM.cs
Normal file
27
Marco.Pms.Model/ViewModels/Collection/InvoiceListVM.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
using Marco.Pms.Model.ViewModels.Projects;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.ViewModels.Collection
|
||||||
|
{
|
||||||
|
public class InvoiceListVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Title { get; set; } = default!;
|
||||||
|
public string Description { get; set; } = default!;
|
||||||
|
public string InvoiceNumber { get; set; } = default!;
|
||||||
|
public string? EInvoiceNumber { get; set; }
|
||||||
|
public BasicProjectVM? Project { get; set; }
|
||||||
|
public DateTime InvoiceDate { get; set; }
|
||||||
|
public DateTime ClientSubmitedDate { get; set; }
|
||||||
|
public DateTime ExceptedPaymentDate { get; set; }
|
||||||
|
public double BasicAmount { get; set; }
|
||||||
|
public double TaxAmount { get; set; }
|
||||||
|
public double BalanceAmount { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public bool MarkAsCompleted { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
public BasicEmployeeVM? UpdatedBy { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.Collection
|
||||||
|
{
|
||||||
|
public class PaymentAdjustmentHeadVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.ViewModels.Collection
|
||||||
|
{
|
||||||
|
public class ReceivedInvoicePaymentVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public Guid InvoiceId { get; set; }
|
||||||
|
public DateTime PaymentReceivedDate { get; set; }
|
||||||
|
public PaymentAdjustmentHeadVM? PaymentAdjustmentHead { get; set; }
|
||||||
|
public string TransactionId { get; set; } = default!;
|
||||||
|
public double Amount { get; set; }
|
||||||
|
public string? Comment { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -26,6 +26,7 @@ namespace Marco.Pms.Model.ViewModels.Expenses
|
|||||||
public string? TransactionId { get; set; }
|
public string? TransactionId { get; set; }
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
public string? Location { get; set; }
|
public string? Location { get; set; }
|
||||||
|
public string? ExpenseUId { get; set; }
|
||||||
public List<BasicDocumentVM> Documents { get; set; } = new List<BasicDocumentVM>();
|
public List<BasicDocumentVM> Documents { get; set; } = new List<BasicDocumentVM>();
|
||||||
public List<ExpenseLogVM> ExpenseLogs { get; set; } = new List<ExpenseLogVM>();
|
public List<ExpenseLogVM> ExpenseLogs { get; set; } = new List<ExpenseLogVM>();
|
||||||
public string? GSTNumber { get; set; }
|
public string? GSTNumber { get; set; }
|
||||||
|
|||||||
@ -18,6 +18,7 @@ namespace Marco.Pms.Model.ViewModels.Expanses
|
|||||||
public DateTime TransactionDate { get; set; }
|
public DateTime TransactionDate { get; set; }
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
public string SupplerName { get; set; } = string.Empty;
|
public string SupplerName { get; set; } = string.Empty;
|
||||||
|
public string? ExpenseUId { get; set; }
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
public string TransactionId { get; set; } = string.Empty;
|
public string TransactionId { get; set; } = string.Empty;
|
||||||
public double Amount { get; set; }
|
public double Amount { get; set; }
|
||||||
|
|||||||
31
Marco.Pms.Model/ViewModels/Expenses/PaymentRequestVM.cs
Normal file
31
Marco.Pms.Model/ViewModels/Expenses/PaymentRequestVM.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using Marco.Pms.Model.Expenses;
|
||||||
|
using Marco.Pms.Model.Master;
|
||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
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 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 RecurringPayment? RecurringPayment { get; set; }
|
||||||
|
public ExpensesTypeMasterVM? ExpenseCategory { get; set; }
|
||||||
|
public ExpensesStatusMasterVM? ExpenseStatus { get; set; }
|
||||||
|
public bool IsAdvancePayment { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
public Guid? UpdatedById { get; set; }
|
||||||
|
public BasicEmployeeVM? UpdatedBy { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Marco.Pms.Model/ViewModels/PaymentGetway/BankDetails.cs
Normal file
8
Marco.Pms.Model/ViewModels/PaymentGetway/BankDetails.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.PaymentGetway
|
||||||
|
{
|
||||||
|
public class BankDetails
|
||||||
|
{
|
||||||
|
public string? Bank { get; set; }
|
||||||
|
public string? BankCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Marco.Pms.Model/ViewModels/PaymentGetway/CardDetails.cs
Normal file
14
Marco.Pms.Model/ViewModels/PaymentGetway/CardDetails.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.PaymentGetway
|
||||||
|
{
|
||||||
|
public class CardDetails
|
||||||
|
{
|
||||||
|
public string? CardId { get; set; }
|
||||||
|
public string? Last4Digits { get; set; }
|
||||||
|
public string? Network { get; set; } // Visa, MasterCard, Amex, RuPay
|
||||||
|
public string? CardType { get; set; } // credit, debit, prepaid
|
||||||
|
public string? Issuer { get; set; } // Bank name
|
||||||
|
public bool International { get; set; }
|
||||||
|
public bool Emi { get; set; }
|
||||||
|
public string? SubType { get; set; } // consumer, business
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.PaymentGetway
|
||||||
|
{
|
||||||
|
public class CreateOrderVM
|
||||||
|
{
|
||||||
|
public string? OrderId { get; set; }
|
||||||
|
public string? Key { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.PaymentGetway
|
||||||
|
{
|
||||||
|
public class PaymentDetailsVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public RazorpayPaymentDetails? RazorpayPaymentDetails { get; set; }
|
||||||
|
public RazorpayOrderDetails? RazorpayOrderDetails { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.PaymentGetway
|
||||||
|
{
|
||||||
|
public class RazorpayOrderDetails
|
||||||
|
{
|
||||||
|
public string? OrderId { get; set; }
|
||||||
|
public decimal Amount { get; set; }
|
||||||
|
public string? Currency { get; set; }
|
||||||
|
public string? Status { get; set; }
|
||||||
|
public string? Receipt { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public decimal AmountPaid { get; set; }
|
||||||
|
public decimal AmountDue { get; set; }
|
||||||
|
public int Attempts { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.PaymentGetway
|
||||||
|
{
|
||||||
|
public class RazorpayPaymentDetails
|
||||||
|
{
|
||||||
|
public string? PaymentId { get; set; }
|
||||||
|
public string? OrderId { get; set; }
|
||||||
|
public decimal Amount { get; set; }
|
||||||
|
public string? Currency { get; set; }
|
||||||
|
public string? Status { get; set; } // created, authorized, captured, refunded, failed
|
||||||
|
public string? Method { get; set; } // card, netbanking, wallet, upi
|
||||||
|
public string? Email { get; set; }
|
||||||
|
public string? Contact { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public string? CustomerName { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
// Payment method specific details
|
||||||
|
public CardDetails? CardDetails { get; set; }
|
||||||
|
public BankDetails? BankDetails { get; set; }
|
||||||
|
public UpiDetails? UpiDetails { get; set; }
|
||||||
|
public WalletDetails? WalletDetails { get; set; }
|
||||||
|
|
||||||
|
// Fee and tax
|
||||||
|
public decimal Fee { get; set; }
|
||||||
|
public decimal Tax { get; set; }
|
||||||
|
|
||||||
|
// Error details (if payment failed)
|
||||||
|
public string? ErrorCode { get; set; }
|
||||||
|
public string? ErrorDescription { get; set; }
|
||||||
|
|
||||||
|
// Additional flags
|
||||||
|
public bool InternationalPayment { get; set; }
|
||||||
|
public bool Captured { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Marco.Pms.Model/ViewModels/PaymentGetway/UpiDetails.cs
Normal file
8
Marco.Pms.Model/ViewModels/PaymentGetway/UpiDetails.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.PaymentGetway
|
||||||
|
{
|
||||||
|
public class UpiDetails
|
||||||
|
{
|
||||||
|
public string? Vpa { get; set; } // UPI ID
|
||||||
|
public string? Provider { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.PaymentGetway
|
||||||
|
{
|
||||||
|
public class WalletDetails
|
||||||
|
{
|
||||||
|
public string? WalletName { get; set; } // paytm, phonepe, amazonpay, freecharge, jiomoney, olamoney
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
using Marco.Pms.Model.Master;
|
using Marco.Pms.Model.Master;
|
||||||
using Marco.Pms.Model.TenantModels;
|
using Marco.Pms.Model.TenantModels;
|
||||||
using Marco.Pms.Model.ViewModels.Activities;
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
using Marco.Pms.Model.ViewModels.PaymentGetway;
|
||||||
|
|
||||||
namespace Marco.Pms.Model.ViewModels.Tenant
|
namespace Marco.Pms.Model.ViewModels.Tenant
|
||||||
{
|
{
|
||||||
@ -16,6 +17,7 @@ namespace Marco.Pms.Model.ViewModels.Tenant
|
|||||||
public DateTime EndDate { get; set; }
|
public DateTime EndDate { get; set; }
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
public DateTime? UpdatedAt { get; set; }
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
public PaymentDetailsVM? PaymentDetail { get; set; }
|
||||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||||
public BasicEmployeeVM? updatedBy { get; set; }
|
public BasicEmployeeVM? updatedBy { get; set; }
|
||||||
public CurrencyMaster? Currency { get; set; }
|
public CurrencyMaster? Currency { get; set; }
|
||||||
|
|||||||
@ -470,6 +470,19 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
|
|
||||||
foreach (var item in menu.Items)
|
foreach (var item in menu.Items)
|
||||||
{
|
{
|
||||||
|
if (item.Text == "Projects")
|
||||||
|
{
|
||||||
|
allowedItems.Add(new MenuItem
|
||||||
|
{
|
||||||
|
Text = "Projects",
|
||||||
|
Icon = "bx bx-building-house",
|
||||||
|
Available = true,
|
||||||
|
Link = "/projects",
|
||||||
|
PermissionIds = new List<string>(),
|
||||||
|
Submenu = new List<SubMenuItem>()
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// --- Item permission check ---
|
// --- Item permission check ---
|
||||||
if (!item.PermissionIds.Any())
|
if (!item.PermissionIds.Any())
|
||||||
{
|
{
|
||||||
@ -577,7 +590,6 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
{
|
{
|
||||||
new MasterMenuVM { Id = 3, Name = "Work Category" },
|
new MasterMenuVM { Id = 3, Name = "Work Category" },
|
||||||
new MasterMenuVM { Id = 8, Name = "Services" }
|
new MasterMenuVM { Id = 8, Name = "Services" }
|
||||||
//new MasterMenuVM { Id = 10, Name = "Payment Mode" }
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -591,7 +603,8 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
ExpenseManagement, new List<MasterMenuVM>
|
ExpenseManagement, new List<MasterMenuVM>
|
||||||
{
|
{
|
||||||
new MasterMenuVM { Id = 6, Name = "Expense Type" },
|
new MasterMenuVM { Id = 6, Name = "Expense Type" },
|
||||||
new MasterMenuVM { Id = 7, Name = "Payment Mode" }
|
new MasterMenuVM { Id = 7, Name = "Payment Mode" },
|
||||||
|
new MasterMenuVM { Id = 10, Name = "Payment Adjustment Head" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -608,6 +621,20 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var featureIds = await generalHelper.GetFeatureIdsByTenentIdAsync(tenantId);
|
var featureIds = await generalHelper.GetFeatureIdsByTenentIdAsync(tenantId);
|
||||||
_logger.LogInfo("Enabled features for TenantId: {TenantId} -> {FeatureIds}", tenantId, string.Join(",", featureIds));
|
_logger.LogInfo("Enabled features for TenantId: {TenantId} -> {FeatureIds}", tenantId, string.Join(",", featureIds));
|
||||||
|
|
||||||
|
//if (!(featureIds?.Any() ?? false))
|
||||||
|
//{
|
||||||
|
// featureIds = new List<Guid>
|
||||||
|
// {
|
||||||
|
// new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), // Expense Management feature
|
||||||
|
// new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), // Employee Management feature
|
||||||
|
// new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), // Attendance Management feature
|
||||||
|
// new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), // Document Management feature
|
||||||
|
// new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), // Masters Management feature
|
||||||
|
// new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), // Directory Management feature
|
||||||
|
// new Guid("6d4c82d6-dbce-48ab-b8b8-f785f4d8c914") // Organization Management feature
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
|
||||||
// Aggregate menus based on enabled features
|
// Aggregate menus based on enabled features
|
||||||
var response = featureIds
|
var response = featureIds
|
||||||
.Where(id => featureMenus.ContainsKey(id))
|
.Where(id => featureMenus.ContainsKey(id))
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
using Marco.Pms.DataAccess.Data;
|
using AutoMapper;
|
||||||
|
using Marco.Pms.DataAccess.Data;
|
||||||
using Marco.Pms.Model.AttendanceModule;
|
using Marco.Pms.Model.AttendanceModule;
|
||||||
using Marco.Pms.Model.Dtos.Attendance;
|
using Marco.Pms.Model.Dtos.Attendance;
|
||||||
using Marco.Pms.Model.Employees;
|
using Marco.Pms.Model.Employees;
|
||||||
using Marco.Pms.Model.Entitlements;
|
using Marco.Pms.Model.Entitlements;
|
||||||
using Marco.Pms.Model.Mapper;
|
using Marco.Pms.Model.Mapper;
|
||||||
using Marco.Pms.Model.Projects;
|
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
using Marco.Pms.Model.ViewModels.AttendanceVM;
|
using Marco.Pms.Model.ViewModels.AttendanceVM;
|
||||||
using Marco.Pms.Services.Hubs;
|
using Marco.Pms.Services.Hubs;
|
||||||
using Marco.Pms.Services.Service;
|
using Marco.Pms.Services.Service;
|
||||||
@ -28,48 +29,41 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
public class AttendanceController : ControllerBase
|
public class AttendanceController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _context;
|
private readonly ApplicationDbContext _context;
|
||||||
private readonly EmployeeHelper _employeeHelper;
|
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||||
private readonly IProjectServices _projectServices;
|
|
||||||
private readonly UserHelper _userHelper;
|
private readonly UserHelper _userHelper;
|
||||||
private readonly S3UploadService _s3Service;
|
|
||||||
private readonly PermissionServices _permission;
|
private readonly PermissionServices _permission;
|
||||||
private readonly ILoggingService _logger;
|
private readonly ILoggingService _logger;
|
||||||
private readonly IHubContext<MarcoHub> _signalR;
|
private readonly Guid tenantId;
|
||||||
private readonly IFirebaseService _firebase;
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
public AttendanceController(
|
public AttendanceController(
|
||||||
ApplicationDbContext context, EmployeeHelper employeeHelper, IProjectServices projectServices, UserHelper userHelper,
|
ApplicationDbContext context,
|
||||||
S3UploadService s3Service, ILoggingService logger, PermissionServices permission, IHubContext<MarcoHub> signalR, IFirebaseService firebase)
|
UserHelper userHelper,
|
||||||
|
IServiceScopeFactory serviceScopeFactory,
|
||||||
|
ILoggingService logger,
|
||||||
|
PermissionServices permission,
|
||||||
|
IMapper mapper)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_employeeHelper = employeeHelper;
|
_serviceScopeFactory = serviceScopeFactory;
|
||||||
_projectServices = projectServices;
|
|
||||||
_userHelper = userHelper;
|
_userHelper = userHelper;
|
||||||
_s3Service = s3Service;
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_permission = permission;
|
_permission = permission;
|
||||||
_signalR = signalR;
|
_mapper = mapper;
|
||||||
_firebase = firebase;
|
tenantId = userHelper.GetTenantId();
|
||||||
}
|
|
||||||
|
|
||||||
private Guid GetTenantId()
|
|
||||||
{
|
|
||||||
return _userHelper.GetTenantId();
|
|
||||||
//var tenant = User.FindFirst("TenantId")?.Value;
|
|
||||||
//return (tenant != null ? Convert.ToInt32(tenant) : 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("log/attendance/{attendanceid}")]
|
[HttpGet("log/attendance/{attendanceid}")]
|
||||||
|
|
||||||
public async Task<IActionResult> GetAttendanceLogById(Guid attendanceid)
|
public async Task<IActionResult> GetAttendanceLogById(Guid attendanceid)
|
||||||
{
|
{
|
||||||
Guid TenantId = GetTenantId();
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var _s3Service = scope.ServiceProvider.GetRequiredService<S3UploadService>();
|
||||||
|
|
||||||
List<AttendanceLog> lstAttendance = await _context.AttendanceLogs
|
List<AttendanceLog> lstAttendance = await _context.AttendanceLogs
|
||||||
.Include(a => a.Document)
|
.Include(a => a.Document)
|
||||||
.Include(a => a.Employee)
|
.Include(a => a.Employee)
|
||||||
.Include(a => a.UpdatedByEmployee)
|
.Include(a => a.UpdatedByEmployee)
|
||||||
.Where(c => c.AttendanceId == attendanceid && c.TenantId == TenantId)
|
.Where(c => c.AttendanceId == attendanceid && c.TenantId == tenantId)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
List<AttendanceLogVM> attendanceLogVMs = new List<AttendanceLogVM>();
|
List<AttendanceLogVM> attendanceLogVMs = new List<AttendanceLogVM>();
|
||||||
@ -85,30 +79,42 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("log/employee/{employeeId}")]
|
[HttpGet("log/employee/{employeeId}")]
|
||||||
public async Task<IActionResult> GetAttendanceLogByEmployeeId(Guid employeeId, [FromQuery] string? dateFrom = null, [FromQuery] string? dateTo = null)
|
public async Task<IActionResult> GetAttendanceLogByEmployeeId(Guid employeeId, [FromQuery] DateTime? dateFrom = null, [FromQuery] DateTime? dateTo = null)
|
||||||
{
|
{
|
||||||
Guid TenantId = GetTenantId();
|
|
||||||
DateTime fromDate = new DateTime();
|
|
||||||
DateTime toDate = new DateTime();
|
|
||||||
|
|
||||||
if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("User sent Invalid from Date while featching attendance logs");
|
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
|
||||||
}
|
|
||||||
if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("User sent Invalid to Date while featching attendance logs");
|
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (employeeId == Guid.Empty)
|
if (employeeId == Guid.Empty)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("The employee Id sent by user is empty");
|
_logger.LogWarning("The employee Id sent by user is empty");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Employee ID is required and must not be Empty.", "Employee ID is required and must not be empty.", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Employee ID is required and must not be Empty.", "Employee ID is required and must not be empty.", 400));
|
||||||
}
|
}
|
||||||
List<Attendance> attendances = await _context.Attendes.Where(c => c.EmployeeId == employeeId && c.TenantId == TenantId && c.AttendanceDate.Date >= fromDate && c.AttendanceDate.Date <= toDate).ToListAsync();
|
|
||||||
Employee? employee = await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.Id == employeeId && e.TenantId == TenantId && e.IsActive);
|
Employee? employee = await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.Id == employeeId && e.TenantId == tenantId);
|
||||||
|
if (employee == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Employee {EmployeeId} not found", employeeId);
|
||||||
|
return NotFound(ApiResponse<object>.ErrorResponse("Employee not found", "Employee not found in database", 404));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dateFrom.HasValue)
|
||||||
|
{
|
||||||
|
dateFrom = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
if (!dateTo.HasValue)
|
||||||
|
{
|
||||||
|
var days = 0 - 7;
|
||||||
|
dateTo = dateFrom.Value.AddDays(days);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Attendance> attendances = await _context.Attendes
|
||||||
|
.Include(a => a.RequestedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(a => a.RequestedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Where(c => c.EmployeeId == employeeId && c.TenantId == tenantId && c.AttendanceDate.Date >= dateFrom && c.AttendanceDate.Date <= dateTo).ToListAsync();
|
||||||
|
|
||||||
|
var projectIds = attendances.Select(a => a.ProjectID).Distinct().ToList();
|
||||||
|
|
||||||
|
var projects = await _context.Projects.Where(p => projectIds.Contains(p.Id) && p.TenantId == tenantId).ToListAsync();
|
||||||
|
|
||||||
List<EmployeeAttendanceVM> results = new List<EmployeeAttendanceVM>();
|
List<EmployeeAttendanceVM> results = new List<EmployeeAttendanceVM>();
|
||||||
|
|
||||||
if (employee != null)
|
if (employee != null)
|
||||||
@ -121,11 +127,17 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
EmployeeId = employee.Id,
|
EmployeeId = employee.Id,
|
||||||
FirstName = employee.FirstName,
|
FirstName = employee.FirstName,
|
||||||
LastName = employee.LastName,
|
LastName = employee.LastName,
|
||||||
|
ProjectId = attendance.ProjectID,
|
||||||
|
ProjectName = projects.Where(p => p.Id == attendance.ProjectID).Select(p => p.Name).FirstOrDefault(),
|
||||||
CheckInTime = attendance.InTime,
|
CheckInTime = attendance.InTime,
|
||||||
CheckOutTime = attendance.OutTime,
|
CheckOutTime = attendance.OutTime,
|
||||||
JobRoleName = employee.JobRole != null ? employee.JobRole.Name : "",
|
JobRoleName = employee.JobRole != null ? employee.JobRole.Name : "",
|
||||||
Activity = attendance.Activity,
|
Activity = attendance.Activity,
|
||||||
EmployeeAvatar = null
|
EmployeeAvatar = null,
|
||||||
|
RequestedAt = attendance.RequestedAt,
|
||||||
|
RequestedBy = _mapper.Map<BasicEmployeeVM>(attendance.RequestedBy),
|
||||||
|
ApprovedAt = attendance.ApprovedAt,
|
||||||
|
Approver = _mapper.Map<BasicEmployeeVM>(attendance.Approver)
|
||||||
};
|
};
|
||||||
results.Add(result);
|
results.Add(result);
|
||||||
}
|
}
|
||||||
@ -145,28 +157,12 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
||||||
[HttpGet("project/log")]
|
[HttpGet("project/log")]
|
||||||
|
public async Task<IActionResult> EmployeeAttendanceByDateRange([FromQuery] Guid? projectId, [FromQuery] Guid? organizationId, [FromQuery] string? dateFrom = null, [FromQuery] string? dateTo = null)
|
||||||
public async Task<IActionResult> EmployeeAttendanceByDateRange([FromQuery] Guid projectId, [FromQuery] Guid? organizationId, [FromQuery] string? dateFrom = null, [FromQuery] string? dateTo = null)
|
|
||||||
{
|
{
|
||||||
Guid tenantId = GetTenantId();
|
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
var project = await _context.Projects.AsNoTracking().FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId);
|
|
||||||
if (project == null)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Project {ProjectId} not found in database", projectId);
|
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Project not found."));
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasTeamAttendancePermission = await _permission.HasPermission(PermissionsMaster.TeamAttendance, LoggedInEmployee.Id);
|
var hasTeamAttendancePermission = await _permission.HasPermission(PermissionsMaster.TeamAttendance, LoggedInEmployee.Id);
|
||||||
var hasSelfAttendancePermission = await _permission.HasPermission(PermissionsMaster.SelfAttendance, LoggedInEmployee.Id);
|
var hasSelfAttendancePermission = await _permission.HasPermission(PermissionsMaster.SelfAttendance, LoggedInEmployee.Id);
|
||||||
var hasProjectPermission = await _permission.HasProjectPermission(LoggedInEmployee, projectId);
|
|
||||||
|
|
||||||
if (!hasProjectPermission)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Employee {EmployeeId} tries to access attendance of project {ProjectId}, but don't have access", LoggedInEmployee.Id, projectId);
|
|
||||||
return Unauthorized(ApiResponse<object>.ErrorResponse("Unauthorized access", "Unauthorized access", 404));
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime fromDate = new DateTime();
|
DateTime fromDate = new DateTime();
|
||||||
DateTime toDate = new DateTime();
|
DateTime toDate = new DateTime();
|
||||||
@ -182,26 +178,46 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (projectId == Guid.Empty)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("The project Id sent by user is less than or equal to zero");
|
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = new List<EmployeeAttendanceVM>();
|
var result = new List<EmployeeAttendanceVM>();
|
||||||
//Attendance? attendance = null;
|
//Attendance? attendance = null;
|
||||||
ProjectAllocation? teamMember = null;
|
|
||||||
|
|
||||||
if (dateFrom == null) fromDate = DateTime.UtcNow.Date;
|
if (dateFrom == null) fromDate = DateTime.UtcNow.Date;
|
||||||
if (dateTo == null && dateFrom != null) toDate = fromDate.AddDays(-1);
|
if (dateTo == null && dateFrom != null) toDate = fromDate.AddDays(-1);
|
||||||
|
|
||||||
|
var lstAttendanceQuery = _context.Attendes
|
||||||
|
.Include(a => a.Employee)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(a => a.Employee)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(a => a.Employee)
|
||||||
|
.ThenInclude(e => e!.Organization)
|
||||||
|
.Include(a => a.Employee)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Where(a =>
|
||||||
|
a.AttendanceDate.Date >= fromDate.Date &&
|
||||||
|
a.AttendanceDate.Date <= toDate.Date &&
|
||||||
|
a.TenantId == tenantId &&
|
||||||
|
a.Employee != null &&
|
||||||
|
a.Employee.Organization != null &&
|
||||||
|
a.Employee.JobRole != null);
|
||||||
|
|
||||||
|
if (organizationId.HasValue)
|
||||||
|
{
|
||||||
|
lstAttendanceQuery = lstAttendanceQuery.Where(a => a.Employee != null && a.Employee.OrganizationId == organizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectId.HasValue)
|
||||||
|
{
|
||||||
|
lstAttendanceQuery = lstAttendanceQuery.Where(a => a.ProjectID == projectId);
|
||||||
|
}
|
||||||
|
|
||||||
if (hasTeamAttendancePermission)
|
if (hasTeamAttendancePermission)
|
||||||
{
|
{
|
||||||
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date >= fromDate.Date && c.AttendanceDate.Date <= toDate.Date && c.TenantId == tenantId).ToListAsync();
|
List<Attendance> lstAttendance = await lstAttendanceQuery.ToListAsync();
|
||||||
|
|
||||||
|
var projectIds = lstAttendance.Select(a => a.ProjectID).ToList();
|
||||||
|
var projects = await _context.Projects.Where(p => projectIds.Contains(p.Id) && p.TenantId == tenantId).ToListAsync();
|
||||||
|
|
||||||
List<ProjectAllocation> projectteam = await _projectServices.GetTeamByProject(tenantId, projectId, organizationId, true);
|
|
||||||
var jobRole = await _context.JobRoles.ToListAsync();
|
|
||||||
foreach (Attendance? attendance in lstAttendance)
|
foreach (Attendance? attendance in lstAttendance)
|
||||||
{
|
{
|
||||||
var result1 = new EmployeeAttendanceVM()
|
var result1 = new EmployeeAttendanceVM()
|
||||||
@ -209,77 +225,59 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
Id = attendance.Id,
|
Id = attendance.Id,
|
||||||
CheckInTime = attendance.InTime,
|
CheckInTime = attendance.InTime,
|
||||||
CheckOutTime = attendance.OutTime,
|
CheckOutTime = attendance.OutTime,
|
||||||
Activity = attendance.Activity
|
Activity = attendance.Activity,
|
||||||
|
EmployeeId = attendance.EmployeeId,
|
||||||
|
FirstName = attendance.Employee?.FirstName,
|
||||||
|
LastName = attendance.Employee?.LastName,
|
||||||
|
JobRoleName = attendance.Employee?.JobRole?.Name,
|
||||||
|
ProjectId = attendance.ProjectID,
|
||||||
|
ProjectName = projects.Where(p => p.Id == attendance.ProjectID).Select(p => p.Name).FirstOrDefault(),
|
||||||
|
OrganizationName = attendance.Employee?.Organization?.Name,
|
||||||
|
RequestedAt = attendance.RequestedAt,
|
||||||
|
RequestedBy = _mapper.Map<BasicEmployeeVM>(attendance.RequestedBy),
|
||||||
|
ApprovedAt = attendance.ApprovedAt,
|
||||||
|
Approver = _mapper.Map<BasicEmployeeVM>(attendance.Approver)
|
||||||
};
|
};
|
||||||
teamMember = projectteam.Find(x => x.EmployeeId == attendance.EmployeeId);
|
result.Add(result1);
|
||||||
if (teamMember != null)
|
|
||||||
{
|
|
||||||
result1.EmployeeAvatar = null;
|
|
||||||
result1.EmployeeId = teamMember.EmployeeId;
|
|
||||||
if (teamMember.Employee != null)
|
|
||||||
{
|
|
||||||
result1.FirstName = teamMember.Employee.FirstName;
|
|
||||||
result1.LastName = teamMember.Employee.LastName;
|
|
||||||
result1.JobRoleName = teamMember.Employee.JobRole != null ? teamMember.Employee.JobRole.Name : null;
|
|
||||||
result1.OrganizationName = teamMember.Employee.Organization?.Name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result1.FirstName = null;
|
|
||||||
result1.LastName = null;
|
|
||||||
result1.JobRoleName = null;
|
|
||||||
result1.OrganizationName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Add(result1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (hasSelfAttendancePermission)
|
else if (hasSelfAttendancePermission)
|
||||||
{
|
{
|
||||||
List<Attendance> lstAttendances = await _context.Attendes
|
|
||||||
.Where(c => c.ProjectID == projectId && c.EmployeeId == LoggedInEmployee.Id && c.AttendanceDate.Date >= fromDate.Date && c.AttendanceDate.Date <= toDate.Date && c.TenantId == tenantId)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var projectAllocationQuery = _context.ProjectAllocations
|
var lstAttendances = await lstAttendanceQuery.Where(a => a.EmployeeId == LoggedInEmployee.Id).ToListAsync();
|
||||||
.Include(pa => pa.Employee)
|
|
||||||
.ThenInclude(e => e!.Organization)
|
|
||||||
.Where(pa => pa.ProjectId == projectId && pa.EmployeeId == LoggedInEmployee.Id && pa.TenantId == tenantId && pa.IsActive);
|
|
||||||
|
|
||||||
if (organizationId.HasValue)
|
var projectIds = lstAttendances.Select(a => a.ProjectID).ToList();
|
||||||
{
|
var projects = await _context.Projects.Where(p => projectIds.Contains(p.Id) && p.TenantId == tenantId).ToListAsync();
|
||||||
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId);
|
|
||||||
}
|
|
||||||
|
|
||||||
var projectAllocation = await projectAllocationQuery.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
foreach (var attendance in lstAttendances)
|
foreach (var attendance in lstAttendances)
|
||||||
{
|
{
|
||||||
if (projectAllocation != null)
|
EmployeeAttendanceVM result1 = new EmployeeAttendanceVM
|
||||||
{
|
{
|
||||||
EmployeeAttendanceVM result1 = new EmployeeAttendanceVM
|
Id = attendance.Id,
|
||||||
{
|
EmployeeAvatar = null,
|
||||||
Id = attendance.Id,
|
EmployeeId = attendance.EmployeeId,
|
||||||
EmployeeAvatar = null,
|
FirstName = attendance.Employee?.FirstName,
|
||||||
EmployeeId = projectAllocation.EmployeeId,
|
LastName = attendance.Employee?.LastName,
|
||||||
FirstName = projectAllocation.Employee?.FirstName,
|
JobRoleName = attendance.Employee?.JobRole?.Name,
|
||||||
LastName = projectAllocation.Employee?.LastName,
|
ProjectId = attendance.ProjectID,
|
||||||
JobRoleName = projectAllocation.Employee?.JobRole?.Name,
|
ProjectName = projects.Where(p => p.Id == attendance.ProjectID).Select(p => p.Name).FirstOrDefault(),
|
||||||
OrganizationName = projectAllocation.Employee?.Organization?.Name,
|
OrganizationName = attendance.Employee?.Organization?.Name,
|
||||||
CheckInTime = attendance.InTime,
|
CheckInTime = attendance.InTime,
|
||||||
CheckOutTime = attendance.OutTime,
|
CheckOutTime = attendance.OutTime,
|
||||||
Activity = attendance.Activity
|
Activity = attendance.Activity,
|
||||||
};
|
RequestedAt = attendance.RequestedAt,
|
||||||
result.Add(result1);
|
RequestedBy = _mapper.Map<BasicEmployeeVM>(attendance.RequestedBy),
|
||||||
}
|
ApprovedAt = attendance.ApprovedAt,
|
||||||
|
Approver = _mapper.Map<BasicEmployeeVM>(attendance.Approver)
|
||||||
|
};
|
||||||
|
result.Add(result1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_logger.LogInfo("{count} Attendance records fetched successfully", result.Count);
|
_logger.LogInfo("{count} Attendance records fetched successfully", result.Count);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("project/team")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves employee attendance records for a specified project and date.
|
/// Retrieves employee attendance records for a specified project and date.
|
||||||
/// The result is filtered based on the logged-in employee's permissions (Team or Self).
|
/// The result is filtered based on the logged-in employee's permissions (Team or Self).
|
||||||
@ -289,13 +287,14 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
/// <param name="includeInactive">Optional. Includes inactive employees in the team list if true.</param>
|
/// <param name="includeInactive">Optional. Includes inactive employees in the team list if true.</param>
|
||||||
/// <param name="date">Optional. The date for which to fetch attendance, in "yyyy-MM-dd" format. Defaults to the current UTC date.</param>
|
/// <param name="date">Optional. The date for which to fetch attendance, in "yyyy-MM-dd" format. Defaults to the current UTC date.</param>
|
||||||
/// <returns>An IActionResult containing a list of employee attendance records or an error response.</returns>
|
/// <returns>An IActionResult containing a list of employee attendance records or an error response.</returns>
|
||||||
public async Task<IActionResult> EmployeeAttendanceByProjectAsync([FromQuery] Guid projectId, [FromQuery] Guid? organizationId, [FromQuery] bool includeInactive, [FromQuery] string? date = null)
|
|
||||||
|
[HttpGet("project/team")]
|
||||||
|
public async Task<IActionResult> EmployeeAttendanceByProjectAsync([FromQuery] Guid? projectId, [FromQuery] Guid? organizationId, [FromQuery] bool includeInactive, [FromQuery] string? date = null)
|
||||||
{
|
{
|
||||||
var tenantId = GetTenantId();
|
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
// --- 1. Initial Validation and Permission Checks ---
|
// --- 1. Initial Validation and Permission Checks ---
|
||||||
_logger.LogInfo("Fetching attendance for ProjectId: {ProjectId}, TenantId: {TenantId}", projectId, tenantId);
|
_logger.LogInfo("Fetching attendance for ProjectId: {ProjectId}, TenantId: {TenantId}", projectId ?? Guid.Empty, tenantId);
|
||||||
|
|
||||||
// Validate date format
|
// Validate date format
|
||||||
if (!DateTime.TryParse(date, out var forDate))
|
if (!DateTime.TryParse(date, out var forDate))
|
||||||
@ -303,20 +302,6 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
forDate = DateTime.UtcNow.Date; // Default to today's date
|
forDate = DateTime.UtcNow.Date; // Default to today's date
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the project exists and if the employee has access
|
|
||||||
var project = await _context.Projects.AsNoTracking().FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId);
|
|
||||||
if (project == null)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Project {ProjectId} not found in database", projectId);
|
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Project not found."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!await _permission.HasProjectPermission(loggedInEmployee, projectId))
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Unauthorized access attempt by EmployeeId: {EmployeeId} for ProjectId: {ProjectId}", loggedInEmployee.Id, projectId);
|
|
||||||
return Unauthorized(ApiResponse<object>.ErrorResponse("You do not have permission to access this project."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 2. Delegate to Specific Logic Based on Permissions ---
|
// --- 2. Delegate to Specific Logic Based on Permissions ---
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -325,13 +310,17 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
if (hasTeamAttendancePermission)
|
if (hasTeamAttendancePermission)
|
||||||
{
|
{
|
||||||
|
if (!organizationId.HasValue)
|
||||||
|
{
|
||||||
|
organizationId = loggedInEmployee.OrganizationId;
|
||||||
|
}
|
||||||
_logger.LogInfo("EmployeeId: {EmployeeId} has Team Attendance permission. Fetching team attendance.", loggedInEmployee.Id);
|
_logger.LogInfo("EmployeeId: {EmployeeId} has Team Attendance permission. Fetching team attendance.", loggedInEmployee.Id);
|
||||||
result = await GetTeamAttendanceAsync(tenantId, projectId, organizationId, forDate, includeInactive);
|
result = await GetTeamAttendanceAsync(tenantId, projectId, organizationId.Value, forDate, includeInactive);
|
||||||
}
|
}
|
||||||
else if (await _permission.HasPermission(PermissionsMaster.SelfAttendance, loggedInEmployee.Id))
|
else if (await _permission.HasPermission(PermissionsMaster.SelfAttendance, loggedInEmployee.Id))
|
||||||
{
|
{
|
||||||
_logger.LogInfo("EmployeeId: {EmployeeId} has Self Attendance permission. Fetching self attendance.", loggedInEmployee.Id);
|
_logger.LogInfo("EmployeeId: {EmployeeId} has Self Attendance permission. Fetching self attendance.", loggedInEmployee.Id);
|
||||||
result = await GetSelfAttendanceAsync(tenantId, projectId, loggedInEmployee.Id, organizationId, forDate);
|
result = await GetSelfAttendanceAsync(tenantId, projectId, loggedInEmployee.Id, forDate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -339,57 +328,67 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("You do not have permission to view attendance.", new { }, 403));
|
return StatusCode(403, ApiResponse<object>.ErrorResponse("You do not have permission to view attendance.", new { }, 403));
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInfo("Successfully fetched {Count} attendance records for ProjectId: {ProjectId}", result.Count, projectId);
|
_logger.LogInfo("Successfully fetched {Count} attendance records for ProjectId: {ProjectId}", result.Count, projectId ?? Guid.Empty);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(result, $"{result.Count} attendance records fetched successfully."));
|
return Ok(ApiResponse<object>.SuccessResponse(result, $"{result.Count} attendance records fetched successfully."));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "An error occurred while fetching attendance for ProjectId: {ProjectId}", projectId);
|
_logger.LogError(ex, "An error occurred while fetching attendance for ProjectId: {ProjectId}", projectId ?? Guid.Empty);
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("An internal server error occurred."));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("An internal server error occurred."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("regularize")]
|
[HttpGet("regularize")]
|
||||||
public async Task<IActionResult> GetRequestRegularizeAttendance([FromQuery] Guid projectId, [FromQuery] Guid? organizationId, [FromQuery] bool IncludeInActive)
|
public async Task<IActionResult> GetRequestRegularizeAttendance([FromQuery] Guid? projectId, [FromQuery] Guid? organizationId, [FromQuery] bool IncludeInActive)
|
||||||
{
|
{
|
||||||
Guid TenantId = GetTenantId();
|
|
||||||
Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var result = new List<EmployeeAttendanceVM>();
|
var result = new List<EmployeeAttendanceVM>();
|
||||||
var hasProjectPermission = await _permission.HasProjectPermission(LoggedInEmployee, projectId);
|
|
||||||
|
|
||||||
if (!hasProjectPermission)
|
var lstAttendanceQuery = _context.Attendes
|
||||||
|
.Include(a => a.RequestedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(a => a.Employee)
|
||||||
|
.ThenInclude(e => e!.Organization)
|
||||||
|
.Include(a => a.Employee)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
|
||||||
|
.Where(c => c.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE && c.Employee != null && c.Employee.JobRole != null && c.TenantId == tenantId);
|
||||||
|
|
||||||
|
if (organizationId.HasValue)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Employee {EmployeeId} tries to access attendance of project {ProjectId}, but don't have access", LoggedInEmployee.Id, projectId);
|
lstAttendanceQuery = lstAttendanceQuery.Where(a => a.Employee != null && a.Employee.OrganizationId == organizationId);
|
||||||
return Unauthorized(ApiResponse<object>.ErrorResponse("Unauthorized access", "Unauthorized access", 404));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE && c.TenantId == TenantId).ToListAsync();
|
if (projectId.HasValue)
|
||||||
|
{
|
||||||
|
lstAttendanceQuery = lstAttendanceQuery.Where(a => a.ProjectID == projectId);
|
||||||
|
}
|
||||||
|
|
||||||
List<ProjectAllocation> projectteam = await _projectServices.GetTeamByProject(TenantId, projectId, organizationId, true);
|
List<Attendance> lstAttendance = await lstAttendanceQuery.ToListAsync();
|
||||||
var idList = projectteam.Select(p => p.EmployeeId).ToList();
|
|
||||||
var jobRole = await _context.JobRoles.ToListAsync();
|
var projectIds = lstAttendance.Select(a => a.ProjectID).ToList();
|
||||||
|
var projects = await _context.Projects.Where(p => projectIds.Contains(p.Id) && p.TenantId == tenantId).ToListAsync();
|
||||||
|
|
||||||
foreach (Attendance attende in lstAttendance)
|
foreach (Attendance attende in lstAttendance)
|
||||||
{
|
{
|
||||||
var teamMember = projectteam.Find(m => m.EmployeeId == attende.EmployeeId);
|
var result1 = new EmployeeAttendanceVM()
|
||||||
if (teamMember != null && teamMember.Employee != null && teamMember.Employee.JobRole != null)
|
|
||||||
{
|
{
|
||||||
var result1 = new EmployeeAttendanceVM()
|
Id = attende.Id,
|
||||||
{
|
CheckInTime = attende.InTime,
|
||||||
Id = attende.Id,
|
CheckOutTime = attende.OutTime,
|
||||||
CheckInTime = attende.InTime,
|
Activity = attende.Activity,
|
||||||
CheckOutTime = attende.OutTime,
|
EmployeeAvatar = null,
|
||||||
Activity = attende.Activity,
|
EmployeeId = attende.EmployeeId,
|
||||||
EmployeeAvatar = null,
|
ProjectId = attende.ProjectID,
|
||||||
EmployeeId = attende.EmployeeId,
|
FirstName = attende.Employee?.FirstName,
|
||||||
FirstName = teamMember.Employee.FirstName,
|
ProjectName = projects.Where(p => p.Id == attende.ProjectID).Select(p => p.Name).FirstOrDefault(),
|
||||||
LastName = teamMember.Employee.LastName,
|
LastName = attende.Employee?.LastName,
|
||||||
JobRoleName = teamMember.Employee.JobRole.Name,
|
JobRoleName = attende.Employee?.JobRole?.Name,
|
||||||
OrganizationName = teamMember.Employee.Organization?.Name
|
OrganizationName = attende.Employee?.Organization?.Name,
|
||||||
};
|
RequestedAt = attende.RequestedAt,
|
||||||
result.Add(result1);
|
RequestedBy = _mapper.Map<BasicEmployeeVM>(attende.RequestedBy)
|
||||||
}
|
};
|
||||||
|
result.Add(result1);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -402,8 +401,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost("record")]
|
||||||
[Route("record")]
|
|
||||||
public async Task<IActionResult> RecordAttendance([FromBody] RecordAttendanceDot recordAttendanceDot)
|
public async Task<IActionResult> RecordAttendance([FromBody] RecordAttendanceDot recordAttendanceDot)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
@ -416,13 +414,16 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
Guid TenantId = GetTenantId();
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var _signalR = scope.ServiceProvider.GetRequiredService<IHubContext<MarcoHub>>();
|
||||||
|
var _employeeHelper = scope.ServiceProvider.GetRequiredService<EmployeeHelper>();
|
||||||
|
|
||||||
var currentEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var currentEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
using var transaction = await _context.Database.BeginTransactionAsync();
|
using var transaction = await _context.Database.BeginTransactionAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == TenantId); ;
|
Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == tenantId); ;
|
||||||
|
|
||||||
if (recordAttendanceDot.MarkTime == null)
|
if (recordAttendanceDot.MarkTime == null)
|
||||||
{
|
{
|
||||||
@ -460,10 +461,12 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
{
|
{
|
||||||
DateTime date = attendance.AttendanceDate;
|
DateTime date = attendance.AttendanceDate;
|
||||||
finalDateTime = GetDateFromTimeStamp(date.Date, recordAttendanceDot.MarkTime);
|
finalDateTime = GetDateFromTimeStamp(date.Date, recordAttendanceDot.MarkTime);
|
||||||
if (attendance.InTime < finalDateTime)
|
if (attendance.InTime <= finalDateTime)
|
||||||
{
|
{
|
||||||
attendance.OutTime = finalDateTime;
|
attendance.OutTime = finalDateTime;
|
||||||
attendance.Activity = ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE;
|
attendance.Activity = ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE;
|
||||||
|
attendance.RequestedAt = DateTime.UtcNow;
|
||||||
|
attendance.RequestedById = currentEmployee.Id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -477,12 +480,15 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
attendance.IsApproved = true;
|
attendance.IsApproved = true;
|
||||||
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE;
|
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE;
|
||||||
attendance.ApprovedById = currentEmployee.Id;
|
attendance.ApprovedById = currentEmployee.Id;
|
||||||
|
attendance.ApprovedAt = DateTime.UtcNow;
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
else if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT)
|
else if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT)
|
||||||
{
|
{
|
||||||
attendance.IsApproved = false;
|
attendance.IsApproved = false;
|
||||||
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT;
|
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT;
|
||||||
|
attendance.ApprovedById = currentEmployee.Id;
|
||||||
|
attendance.ApprovedAt = DateTime.UtcNow;
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
attendance.Date = DateTime.UtcNow;
|
attendance.Date = DateTime.UtcNow;
|
||||||
@ -493,7 +499,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
attendance = new Attendance();
|
attendance = new Attendance();
|
||||||
attendance.TenantId = TenantId;
|
attendance.TenantId = tenantId;
|
||||||
attendance.AttendanceDate = recordAttendanceDot.Date;
|
attendance.AttendanceDate = recordAttendanceDot.Date;
|
||||||
// attendance.Activity = recordAttendanceDot.Action;
|
// attendance.Activity = recordAttendanceDot.Action;
|
||||||
attendance.Comment = recordAttendanceDot.Comment;
|
attendance.Comment = recordAttendanceDot.Comment;
|
||||||
@ -525,7 +531,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
Latitude = recordAttendanceDot.Latitude,
|
Latitude = recordAttendanceDot.Latitude,
|
||||||
Longitude = recordAttendanceDot.Longitude,
|
Longitude = recordAttendanceDot.Longitude,
|
||||||
|
|
||||||
TenantId = TenantId,
|
TenantId = tenantId,
|
||||||
UpdatedBy = currentEmployee.Id,
|
UpdatedBy = currentEmployee.Id,
|
||||||
UpdatedOn = recordAttendanceDot.Date
|
UpdatedOn = recordAttendanceDot.Date
|
||||||
};
|
};
|
||||||
@ -549,11 +555,13 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
CheckOutTime = attendance.OutTime,
|
CheckOutTime = attendance.OutTime,
|
||||||
EmployeeAvatar = null,
|
EmployeeAvatar = null,
|
||||||
EmployeeId = recordAttendanceDot.EmployeeID,
|
EmployeeId = recordAttendanceDot.EmployeeID,
|
||||||
|
ProjectId = attendance.ProjectID,
|
||||||
FirstName = employee.FirstName,
|
FirstName = employee.FirstName,
|
||||||
LastName = employee.LastName,
|
LastName = employee.LastName,
|
||||||
Id = attendance.Id,
|
Id = attendance.Id,
|
||||||
Activity = attendance.Activity,
|
Activity = attendance.Activity,
|
||||||
JobRoleName = employee.JobRole.Name
|
JobRoleName = employee.JobRole.Name,
|
||||||
|
OrganizationName = employee.Organization?.Name
|
||||||
};
|
};
|
||||||
var sendActivity = 0;
|
var sendActivity = 0;
|
||||||
if (recordAttendanceDot.Id == Guid.Empty)
|
if (recordAttendanceDot.Id == Guid.Empty)
|
||||||
@ -569,10 +577,10 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
// --- Push Notification Section ---
|
// --- Push Notification Section ---
|
||||||
// This section attempts to send a test push notification to the user's device.
|
// This section attempts to send a test push notification to the user's device.
|
||||||
// It's designed to fail gracefully and handle invalid Firebase Cloud Messaging (FCM) tokens.
|
// It's designed to fail gracefully and handle invalid Firebase Cloud Messaging (FCM) tokens.
|
||||||
|
var _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
|
||||||
var name = $"{vm.FirstName} {vm.LastName}";
|
var name = $"{vm.FirstName} {vm.LastName}";
|
||||||
|
|
||||||
await _firebase.SendAttendanceMessageAsync(attendance.ProjectID, name, recordAttendanceDot.Action, attendance.EmployeeId, TenantId);
|
await _firebase.SendAttendanceMessageAsync(attendance.ProjectID, name, recordAttendanceDot.Action, attendance.EmployeeId, tenantId);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -608,7 +616,12 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
Guid tenantId = GetTenantId();
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var _s3Service = scope.ServiceProvider.GetRequiredService<S3UploadService>();
|
||||||
|
var _employeeHelper = scope.ServiceProvider.GetRequiredService<EmployeeHelper>();
|
||||||
|
var _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
|
||||||
|
var _signalR = scope.ServiceProvider.GetRequiredService<IHubContext<MarcoHub>>();
|
||||||
|
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var batchId = Guid.NewGuid();
|
var batchId = Guid.NewGuid();
|
||||||
|
|
||||||
@ -672,6 +685,8 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
{
|
{
|
||||||
attendance.OutTime = finalDateTime;
|
attendance.OutTime = finalDateTime;
|
||||||
attendance.Activity = ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE;
|
attendance.Activity = ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE;
|
||||||
|
attendance.RequestedAt = DateTime.UtcNow;
|
||||||
|
attendance.RequestedById = loggedInEmployee.Id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -682,10 +697,14 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
case ATTENDANCE_MARK_TYPE.REGULARIZE:
|
case ATTENDANCE_MARK_TYPE.REGULARIZE:
|
||||||
attendance.IsApproved = true;
|
attendance.IsApproved = true;
|
||||||
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE;
|
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE;
|
||||||
|
attendance.ApprovedAt = DateTime.UtcNow;
|
||||||
|
attendance.ApprovedById = loggedInEmployee.Id;
|
||||||
break;
|
break;
|
||||||
case ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT:
|
case ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT:
|
||||||
attendance.IsApproved = false;
|
attendance.IsApproved = false;
|
||||||
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT;
|
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT;
|
||||||
|
attendance.ApprovedAt = DateTime.UtcNow;
|
||||||
|
attendance.ApprovedById = loggedInEmployee.Id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,6 +770,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
{
|
{
|
||||||
Id = attendance.Id,
|
Id = attendance.Id,
|
||||||
EmployeeId = employee.Id,
|
EmployeeId = employee.Id,
|
||||||
|
ProjectId = attendance.ProjectID,
|
||||||
FirstName = employee.FirstName,
|
FirstName = employee.FirstName,
|
||||||
LastName = employee.LastName,
|
LastName = employee.LastName,
|
||||||
CheckInTime = attendance.InTime,
|
CheckInTime = attendance.InTime,
|
||||||
@ -813,56 +833,54 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fetches attendance for an entire project team using a single, optimized database query.
|
/// Fetches attendance for an entire project team using a single, optimized database query.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<List<EmployeeAttendanceVM>> GetTeamAttendanceAsync(Guid tenantId, Guid projectId, Guid? organizationId, DateTime forDate, bool includeInactive)
|
private async Task<List<EmployeeAttendanceVM>> GetTeamAttendanceAsync(Guid tenantId, Guid? projectId, Guid organizationId, DateTime forDate, bool includeInactive)
|
||||||
{
|
{
|
||||||
// This single query joins ProjectAllocations with Employees and performs a LEFT JOIN with Attendances.
|
// This single query joins ProjectAllocations with Employees and performs a LEFT JOIN with Attendances.
|
||||||
// This is far more efficient than fetching collections and joining them in memory.
|
// This is far more efficient than fetching collections and joining them in memory.
|
||||||
var query = _context.ProjectAllocations
|
var query = _context.Employees
|
||||||
.Include(pa => pa.Employee)
|
.Include(e => e!.Organization)
|
||||||
.ThenInclude(e => e!.Organization)
|
.Include(e => e!.JobRole)
|
||||||
.Include(pa => pa.Employee)
|
.Where(e => e.OrganizationId == organizationId && e.Organization != null && e.JobRole != null && e.IsActive);
|
||||||
.ThenInclude(e => e!.JobRole)
|
|
||||||
.Where(pa => pa.TenantId == tenantId && pa.ProjectId == projectId);
|
|
||||||
|
|
||||||
// Apply filters based on optional parameters
|
|
||||||
if (!includeInactive)
|
var lstAttendanceQuery = _context.Attendes.Where(c => c.AttendanceDate.Date == forDate && c.TenantId == tenantId);
|
||||||
|
|
||||||
|
if (projectId.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(pa => pa.IsActive);
|
lstAttendanceQuery = lstAttendanceQuery.Where(a => a.ProjectID == projectId);
|
||||||
}
|
|
||||||
if (organizationId.HasValue)
|
|
||||||
{
|
|
||||||
query = query.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date == forDate && c.TenantId == tenantId).ToListAsync();
|
List<Attendance> lstAttendance = await lstAttendanceQuery.ToListAsync();
|
||||||
|
|
||||||
var teamAttendance = await query
|
var employees = await query
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var response = teamAttendance
|
var projectIds = lstAttendance.Select(a => a.ProjectID).ToList();
|
||||||
.Select(teamMember =>
|
var projects = await _context.Projects.Where(p => projectIds.Contains(p.Id) && p.TenantId == tenantId).ToListAsync();
|
||||||
|
|
||||||
|
var response = employees
|
||||||
|
.Select(employee =>
|
||||||
{
|
{
|
||||||
var result1 = new EmployeeAttendanceVM()
|
var result1 = new EmployeeAttendanceVM()
|
||||||
{
|
{
|
||||||
EmployeeAvatar = null,
|
EmployeeAvatar = null,
|
||||||
EmployeeId = teamMember.EmployeeId,
|
EmployeeId = employee.Id,
|
||||||
FirstName = teamMember.Employee?.FirstName,
|
FirstName = employee.FirstName,
|
||||||
LastName = teamMember.Employee?.LastName,
|
LastName = employee.LastName,
|
||||||
OrganizationName = teamMember.Employee?.Organization?.Name,
|
OrganizationName = employee.Organization!.Name,
|
||||||
JobRoleName = teamMember.Employee?.JobRole?.Name,
|
JobRoleName = employee.JobRole!.Name,
|
||||||
};
|
};
|
||||||
|
|
||||||
//var member = emp.Where(e => e.Id == teamMember.EmployeeId);
|
var attendance = lstAttendance.Find(x => x.EmployeeId == employee.Id) ?? new Attendance();
|
||||||
|
|
||||||
|
|
||||||
var attendance = lstAttendance.Find(x => x.EmployeeId == teamMember.EmployeeId) ?? new Attendance();
|
|
||||||
if (attendance != null)
|
if (attendance != null)
|
||||||
{
|
{
|
||||||
result1.Id = attendance.Id;
|
result1.Id = attendance.Id;
|
||||||
|
result1.ProjectId = attendance.ProjectID;
|
||||||
result1.CheckInTime = attendance.InTime;
|
result1.CheckInTime = attendance.InTime;
|
||||||
result1.CheckOutTime = attendance.OutTime;
|
result1.CheckOutTime = attendance.OutTime;
|
||||||
result1.Activity = attendance.Activity;
|
result1.Activity = attendance.Activity;
|
||||||
|
result1.ProjectName = projects.Where(p => p.Id == attendance.ProjectID).Select(p => p.Name).FirstOrDefault();
|
||||||
}
|
}
|
||||||
return result1;
|
return result1;
|
||||||
})
|
})
|
||||||
@ -875,42 +893,50 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fetches a single attendance record for the logged-in employee.
|
/// Fetches a single attendance record for the logged-in employee.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<List<EmployeeAttendanceVM>> GetSelfAttendanceAsync(Guid tenantId, Guid projectId, Guid employeeId, Guid? organizationId, DateTime forDate)
|
private async Task<List<EmployeeAttendanceVM>> GetSelfAttendanceAsync(Guid tenantId, Guid? projectId, Guid employeeId, DateTime forDate)
|
||||||
{
|
{
|
||||||
List<EmployeeAttendanceVM> result = new List<EmployeeAttendanceVM>();
|
List<EmployeeAttendanceVM> result = new List<EmployeeAttendanceVM>();
|
||||||
|
|
||||||
// This query fetches the employee's project allocation and their attendance in a single trip.
|
// This query fetches the employee's project allocation and their attendance in a single trip.
|
||||||
Attendance lstAttendance = await _context.Attendes
|
var lstAttendanceQuery = _context.Attendes
|
||||||
.FirstOrDefaultAsync(c => c.ProjectID == projectId && c.EmployeeId == employeeId && c.AttendanceDate.Date == forDate && c.TenantId == tenantId) ?? new Attendance();
|
.Where(c => c.EmployeeId == employeeId && c.AttendanceDate.Date == forDate && c.TenantId == tenantId);
|
||||||
|
|
||||||
var projectAllocationQuery = _context.ProjectAllocations
|
if (projectId.HasValue)
|
||||||
.Include(pa => pa.Employee)
|
|
||||||
.ThenInclude(e => e!.Organization)
|
|
||||||
.Where(pa => pa.ProjectId == projectId && pa.EmployeeId == employeeId && pa.TenantId == tenantId && pa.IsActive);
|
|
||||||
|
|
||||||
if (organizationId.HasValue)
|
|
||||||
{
|
{
|
||||||
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId);
|
lstAttendanceQuery = lstAttendanceQuery.Where(a => a.ProjectID == projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectAllocation = await projectAllocationQuery.FirstOrDefaultAsync();
|
List<Attendance> lstAttendances = await lstAttendanceQuery.ToListAsync() ?? new List<Attendance>();
|
||||||
|
|
||||||
if (projectAllocation != null)
|
var projectIds = lstAttendances.Select(a => a.ProjectID).ToList();
|
||||||
|
var projects = await _context.Projects.Where(p => projectIds.Contains(p.Id) && p.TenantId == tenantId).ToListAsync();
|
||||||
|
|
||||||
|
var employee = await _context.Employees
|
||||||
|
.Include(e => e.Organization)
|
||||||
|
.Include(e => e.JobRole)
|
||||||
|
.FirstOrDefaultAsync(e => e.Id == employeeId && e.IsActive);
|
||||||
|
|
||||||
|
if (employee != null && employee.JobRole != null && employee.Organization != null)
|
||||||
{
|
{
|
||||||
EmployeeAttendanceVM result1 = new EmployeeAttendanceVM
|
foreach (var lstAttendance in lstAttendances)
|
||||||
{
|
{
|
||||||
Id = lstAttendance.Id,
|
EmployeeAttendanceVM result1 = new EmployeeAttendanceVM
|
||||||
EmployeeAvatar = null,
|
{
|
||||||
EmployeeId = projectAllocation.EmployeeId,
|
Id = lstAttendance.Id,
|
||||||
FirstName = projectAllocation.Employee?.FirstName,
|
EmployeeAvatar = null,
|
||||||
OrganizationName = projectAllocation.Employee?.Organization?.Name,
|
ProjectId = lstAttendance.ProjectID,
|
||||||
LastName = projectAllocation.Employee?.LastName,
|
EmployeeId = employee.Id,
|
||||||
JobRoleName = projectAllocation.Employee?.JobRole?.Name,
|
FirstName = employee.FirstName,
|
||||||
CheckInTime = lstAttendance.InTime,
|
OrganizationName = employee.Organization.Name,
|
||||||
CheckOutTime = lstAttendance.OutTime,
|
ProjectName = projects.Where(p => p.Id == lstAttendance.ProjectID).Select(p => p.Name).FirstOrDefault(),
|
||||||
Activity = lstAttendance.Activity
|
LastName = employee.LastName,
|
||||||
};
|
JobRoleName = employee.JobRole.Name,
|
||||||
result.Add(result1);
|
CheckInTime = lstAttendance.InTime,
|
||||||
|
CheckOutTime = lstAttendance.OutTime,
|
||||||
|
Activity = lstAttendance.Activity
|
||||||
|
};
|
||||||
|
result.Add(result1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -59,7 +59,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
{
|
{
|
||||||
|
|
||||||
var user = await _context.ApplicationUsers
|
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)
|
if (user == null)
|
||||||
{
|
{
|
||||||
@ -103,9 +103,13 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return NotFound(ApiResponse<object>.ErrorResponse("Username not found", "Username not found", 404));
|
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
|
// Generate tokens
|
||||||
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);
|
||||||
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);
|
||||||
|
|
||||||
_logger.LogInfo("User login successful - UserId: {UserId}", user.Id);
|
_logger.LogInfo("User login successful - UserId: {UserId}", user.Id);
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(new
|
return Ok(ApiResponse<object>.SuccessResponse(new
|
||||||
@ -201,12 +205,17 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
_logger.LogInfo("Successfully found employee details for tenant ID: {TenantId}", emp.TenantId ?? Guid.Empty);
|
_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
|
// 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.
|
// Generate a new refresh token and store it in the database.
|
||||||
_logger.LogInfo("Generating and storing Refresh Token for user: {Username}", user.UserName);
|
_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
|
// Fetch MPIN Token
|
||||||
var mpinToken = await _context.MPINDetails.FirstOrDefaultAsync(p => p.UserId == Guid.Parse(user.Id));
|
var mpinToken = await _context.MPINDetails.FirstOrDefaultAsync(p => p.UserId == Guid.Parse(user.Id));
|
||||||
@ -264,31 +273,32 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
string? tokenType = claimsPrincipal.FindFirst("token_type")?.Value;
|
string? tokenType = claimsPrincipal.FindFirst("token_type")?.Value;
|
||||||
string? tokenTenantId = claimsPrincipal.FindFirst("TenantId")?.Value;
|
|
||||||
string? tokenUserId = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
string? tokenUserId = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||||||
|
|
||||||
// Validate essential claims
|
// 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");
|
_logger.LogWarning("MPIN token claims are incomplete");
|
||||||
return Unauthorized(ApiResponse<object>.ErrorResponse("Invalid token claims", "MPIN token does not match your identity", 401));
|
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
|
// Fetch employee by ID and tenant
|
||||||
var requestEmployee = await _context.Employees
|
var requestEmployee = await _context.Employees
|
||||||
.Include(e => e.ApplicationUser)
|
.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))
|
if (requestEmployee == null || string.IsNullOrWhiteSpace(requestEmployee.ApplicationUserId))
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Employee not found or invalid for verification - EmployeeId: {EmployeeId}", verifyMPIN.EmployeeId);
|
_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));
|
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
|
// 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);
|
_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));
|
return Unauthorized(ApiResponse<object>.ErrorResponse("Unauthorized", "MPIN token does not match your identity", 401));
|
||||||
@ -319,36 +329,6 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return Unauthorized(ApiResponse<object>.ErrorResponse("MPIN mismatch", "MPIN did not match", 401));
|
return Unauthorized(ApiResponse<object>.ErrorResponse("MPIN mismatch", "MPIN did not match", 401));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(verifyMPIN.FcmToken))
|
|
||||||
{
|
|
||||||
var existingFCMTokenMapping = await _context.FCMTokenMappings.Where(ft => ft.FcmToken == verifyMPIN.FcmToken).ToListAsync();
|
|
||||||
|
|
||||||
if (existingFCMTokenMapping.Any())
|
|
||||||
{
|
|
||||||
_context.FCMTokenMappings.RemoveRange(existingFCMTokenMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
var fcmTokenMapping = new FCMTokenMapping
|
|
||||||
{
|
|
||||||
EmployeeId = requestEmployee.Id,
|
|
||||||
FcmToken = verifyMPIN.FcmToken,
|
|
||||||
ExpiredAt = DateTime.UtcNow.AddDays(6),
|
|
||||||
TenantId = tenantId
|
|
||||||
};
|
|
||||||
_context.FCMTokenMappings.Add(fcmTokenMapping);
|
|
||||||
_logger.LogInfo("New FCM Token registering for employee {EmployeeId}", requestEmployee.Id);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Exception occured while saving FCM Token for employee {EmployeeId}", requestEmployee.Id);
|
|
||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Error", ex.Message, 500));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate new tokens
|
// Generate new tokens
|
||||||
var jwtToken = _refreshTokenService.GenerateJwtToken(requestEmployee.Email, tenantId, requestEmployee.OrganizationId, _jwtSettings);
|
var jwtToken = _refreshTokenService.GenerateJwtToken(requestEmployee.Email, tenantId, requestEmployee.OrganizationId, _jwtSettings);
|
||||||
var refreshToken = await _refreshTokenService.CreateRefreshToken(requestEmployee.ApplicationUserId, tenantId.ToString(), requestEmployee.OrganizationId, _jwtSettings);
|
var refreshToken = await _refreshTokenService.CreateRefreshToken(requestEmployee.ApplicationUserId, tenantId.ToString(), requestEmployee.OrganizationId, _jwtSettings);
|
||||||
@ -431,7 +411,9 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
//var accessToken = _refreshTokenService.GenerateJwtTokenWithOrganization(requestEmployee.ApplicationUser?.UserName, requestEmployee.OrganizationId, _jwtSettings);
|
//var accessToken = _refreshTokenService.GenerateJwtTokenWithOrganization(requestEmployee.ApplicationUser?.UserName, requestEmployee.OrganizationId, _jwtSettings);
|
||||||
//var refreshToken = await _refreshTokenService.CreateRefreshTokenWithOrganization(requestEmployee.ApplicationUserId, 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,
|
var accessToken = _refreshTokenService.GenerateJwtToken(requestEmployee.ApplicationUser?.UserName,
|
||||||
tenant?.Id ?? Guid.Empty, requestEmployee.OrganizationId, _jwtSettings);
|
tenant?.Id ?? Guid.Empty, requestEmployee.OrganizationId, _jwtSettings);
|
||||||
|
|||||||
1284
Marco.Pms.Services/Controllers/CollectionController.cs
Normal file
1284
Marco.Pms.Services/Controllers/CollectionController.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,8 @@
|
|||||||
using Marco.Pms.Model.Activities;
|
using Marco.Pms.Model.Activities;
|
||||||
using Marco.Pms.Model.Dtos.Attendance;
|
using Marco.Pms.Model.Dtos.Attendance;
|
||||||
using Marco.Pms.Model.Employees;
|
using Marco.Pms.Model.Employees;
|
||||||
|
using Marco.Pms.Model.Entitlements;
|
||||||
|
using Marco.Pms.Model.Expenses;
|
||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
using Marco.Pms.Model.ViewModels.DashBoard;
|
using Marco.Pms.Model.ViewModels.DashBoard;
|
||||||
@ -12,6 +14,7 @@ using MarcoBMS.Services.Service;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Marco.Pms.Services.Controllers
|
namespace Marco.Pms.Services.Controllers
|
||||||
{
|
{
|
||||||
@ -25,19 +28,35 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
private readonly IProjectServices _projectServices;
|
private readonly IProjectServices _projectServices;
|
||||||
private readonly ILoggingService _logger;
|
private readonly ILoggingService _logger;
|
||||||
private readonly PermissionServices _permissionServices;
|
private readonly PermissionServices _permissionServices;
|
||||||
|
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||||
public static readonly Guid ActiveId = Guid.Parse("b74da4c2-d07e-46f2-9919-e75e49b12731");
|
public static readonly Guid ActiveId = Guid.Parse("b74da4c2-d07e-46f2-9919-e75e49b12731");
|
||||||
public DashboardController(ApplicationDbContext context, UserHelper userHelper, IProjectServices projectServices, ILoggingService logger, PermissionServices permissionServices)
|
private static readonly Guid Draft = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8");
|
||||||
|
private static readonly Guid Review = Guid.Parse("6537018f-f4e9-4cb3-a210-6c3b2da999d7");
|
||||||
|
private static readonly Guid Approve = Guid.Parse("4068007f-c92f-4f37-a907-bc15fe57d4d8");
|
||||||
|
private static readonly Guid ProcessPending = Guid.Parse("f18c5cfd-7815-4341-8da2-2c2d65778e27");
|
||||||
|
private static readonly Guid Processed = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95");
|
||||||
|
private static readonly Guid RejectedByReviewer = Guid.Parse("965eda62-7907-4963-b4a1-657fb0b2724b");
|
||||||
|
private static readonly Guid RejectedByApprover = Guid.Parse("d1ee5eec-24b6-4364-8673-a8f859c60729");
|
||||||
|
private readonly Guid tenantId;
|
||||||
|
|
||||||
|
public DashboardController(ApplicationDbContext context,
|
||||||
|
UserHelper userHelper,
|
||||||
|
IProjectServices projectServices,
|
||||||
|
IServiceScopeFactory serviceScopeFactory,
|
||||||
|
ILoggingService logger,
|
||||||
|
PermissionServices permissionServices)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_userHelper = userHelper;
|
_userHelper = userHelper;
|
||||||
_projectServices = projectServices;
|
_projectServices = projectServices;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_serviceScopeFactory = serviceScopeFactory;
|
||||||
_permissionServices = permissionServices;
|
_permissionServices = permissionServices;
|
||||||
|
tenantId = userHelper.GetTenantId();
|
||||||
}
|
}
|
||||||
[HttpGet("progression")]
|
[HttpGet("progression")]
|
||||||
public async Task<IActionResult> GetGraph([FromQuery] double days, [FromQuery] string FromDate, [FromQuery] Guid? projectId)
|
public async Task<IActionResult> GetGraph([FromQuery] double days, [FromQuery] string FromDate, [FromQuery] Guid? projectId)
|
||||||
{
|
{
|
||||||
var tenantId = _userHelper.GetTenantId();
|
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
DateTime fromDate = new DateTime();
|
DateTime fromDate = new DateTime();
|
||||||
@ -149,7 +168,6 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
[HttpGet("projects")]
|
[HttpGet("projects")]
|
||||||
public async Task<IActionResult> GetProjectCount()
|
public async Task<IActionResult> GetProjectCount()
|
||||||
{
|
{
|
||||||
var tenantId = _userHelper.GetTenantId();
|
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
var projects = await _context.Projects.Where(p => p.TenantId == tenantId).ToListAsync();
|
var projects = await _context.Projects.Where(p => p.TenantId == tenantId).ToListAsync();
|
||||||
@ -176,7 +194,6 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tenantId = _userHelper.GetTenantId();
|
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
_logger.LogInfo("GetTotalEmployees called by user {UserId} for ProjectId: {ProjectId}", loggedInEmployee.Id, projectId ?? Guid.Empty);
|
_logger.LogInfo("GetTotalEmployees called by user {UserId} for ProjectId: {ProjectId}", loggedInEmployee.Id, projectId ?? Guid.Empty);
|
||||||
@ -269,7 +286,6 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tenantId = _userHelper.GetTenantId();
|
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
_logger.LogInfo("GetTotalTasks called by user {UserId} for ProjectId: {ProjectId}", loggedInEmployee.Id, projectId ?? Guid.Empty);
|
_logger.LogInfo("GetTotalTasks called by user {UserId} for ProjectId: {ProjectId}", loggedInEmployee.Id, projectId ?? Guid.Empty);
|
||||||
@ -348,10 +364,10 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("An internal server error occurred.", null, 500));
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("An internal server error occurred.", null, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("pending-attendance")]
|
[HttpGet("pending-attendance")]
|
||||||
public async Task<IActionResult> GetPendingAttendance()
|
public async Task<IActionResult> GetPendingAttendance()
|
||||||
{
|
{
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
var attendance = await _context.Attendes.Where(a => a.EmployeeId == LoggedInEmployee.Id && a.TenantId == tenantId).ToListAsync();
|
var attendance = await _context.Attendes.Where(a => a.EmployeeId == LoggedInEmployee.Id && a.TenantId == tenantId).ToListAsync();
|
||||||
@ -374,7 +390,6 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
[HttpGet("project-attendance/{projectId}")]
|
[HttpGet("project-attendance/{projectId}")]
|
||||||
public async Task<IActionResult> GetProjectAttendance(Guid projectId, [FromQuery] string? date)
|
public async Task<IActionResult> GetProjectAttendance(Guid projectId, [FromQuery] string? date)
|
||||||
{
|
{
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
DateTime currentDate = DateTime.UtcNow;
|
DateTime currentDate = DateTime.UtcNow;
|
||||||
@ -428,7 +443,6 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
[HttpGet("activities/{projectId}")]
|
[HttpGet("activities/{projectId}")]
|
||||||
public async Task<IActionResult> GetActivities(Guid projectId, [FromQuery] string? date)
|
public async Task<IActionResult> GetActivities(Guid projectId, [FromQuery] string? date)
|
||||||
{
|
{
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
DateTime currentDate = DateTime.UtcNow;
|
DateTime currentDate = DateTime.UtcNow;
|
||||||
@ -600,5 +614,317 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(sortedResult, $"{sortedResult.Count} records fetched for attendance overview", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(sortedResult, $"{sortedResult.Count} records fetched for attendance overview", 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("expense/monthly")]
|
||||||
|
public async Task<IActionResult> GetExpenseReportByProjectsAsync([FromQuery] Guid? projectId, [FromQuery] Guid? categoryId, [FromQuery] int months)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Read-only base filter with tenant scope and non-draft
|
||||||
|
var baseQuery = _context.Expenses
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(e =>
|
||||||
|
e.TenantId == tenantId
|
||||||
|
&& e.IsActive
|
||||||
|
&& e.StatusId != Draft); // [Server Filters]
|
||||||
|
|
||||||
|
if (months != 0)
|
||||||
|
{
|
||||||
|
months = 0 - months;
|
||||||
|
var end = DateTime.UtcNow.Date;
|
||||||
|
var start = end.AddMonths(months); // inclusive EOD
|
||||||
|
baseQuery = baseQuery.Where(e => e.TransactionDate >= start
|
||||||
|
&& e.TransactionDate <= end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectId.HasValue)
|
||||||
|
baseQuery = baseQuery.Where(e => e.ProjectId == projectId);
|
||||||
|
|
||||||
|
if (categoryId.HasValue)
|
||||||
|
baseQuery = baseQuery.Where(e => e.ExpensesTypeId == categoryId);
|
||||||
|
|
||||||
|
// Single server-side group/aggregate by project
|
||||||
|
var report = await baseQuery
|
||||||
|
.AsNoTracking()
|
||||||
|
.GroupBy(e => new { e.TransactionDate.Year, e.TransactionDate.Month })
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
Year = g.Key.Year,
|
||||||
|
Month = g.Key.Month,
|
||||||
|
Total = g.Sum(x => x.Amount),
|
||||||
|
Count = g.Count()
|
||||||
|
})
|
||||||
|
.OrderBy(x => x.Year).ThenBy(x => x.Month)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var culture = CultureInfo.GetCultureInfo("en-IN"); // pick desired locale
|
||||||
|
|
||||||
|
var response = report
|
||||||
|
.Select(x => new
|
||||||
|
{
|
||||||
|
MonthName = culture.DateTimeFormat.GetMonthName(x.Month), // e.g., "January"
|
||||||
|
Year = x.Year,
|
||||||
|
Total = x.Total,
|
||||||
|
Count = x.Count
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
_logger.LogInfo(
|
||||||
|
"GetExpenseReportByProjects completed. TenantId={TenantId}, Rows={Rows}",
|
||||||
|
tenantId, report.Count); // [Completion Log]
|
||||||
|
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Expense report by project fetched successfully", 200)); // [Success Response]
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("GetExpenseReportByProjects canceled by client. TenantId={TenantId}", tenantId); // [Cancel Log]
|
||||||
|
return StatusCode(499, ApiResponse<object>.ErrorResponse("Client has canceled the opration", "Client has canceled the opration", 499)); // [Cancel Response]
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex,
|
||||||
|
"GetExpenseReportByProjects failed. TenantId={TenantId}",
|
||||||
|
tenantId); // [Error Log]
|
||||||
|
return StatusCode(500,
|
||||||
|
ApiResponse<object>.ErrorResponse("An error occurred while fetching the expense report.", 500)); // [Error Response]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("expense/type")]
|
||||||
|
public async Task<IActionResult> GetExpenseReportByExpenseTypeAsync([FromQuery] Guid? projectId, [FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
|
||||||
|
{
|
||||||
|
// Structured log: entering action with filters
|
||||||
|
_logger.LogDebug(
|
||||||
|
"GetExpenseReportByExpenseType started. TenantId={TenantId}, ProjectId={ProjectId}, StartDate={StartDate}, EndDate={EndDate}",
|
||||||
|
tenantId, projectId ?? Guid.Empty, startDate, endDate); // [Start Log] [memory:4][memory:1]
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Compose base query: push filters to DB, avoid client evaluation
|
||||||
|
IQueryable<Expenses> baseQuery = _context.Expenses
|
||||||
|
.AsNoTracking() // Reduce tracking overhead for read-only endpoint
|
||||||
|
.Where(e => e.TenantId == tenantId
|
||||||
|
&& e.IsActive
|
||||||
|
&& e.StatusId != Draft
|
||||||
|
&& e.TransactionDate >= startDate
|
||||||
|
&& e.TransactionDate <= endDate.AddDays(1).AddTicks(-1));
|
||||||
|
|
||||||
|
if (projectId.HasValue)
|
||||||
|
baseQuery = baseQuery.Where(e => e.ProjectId == projectId.Value); // [Filter] [memory:7]
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
.Select(e => new
|
||||||
|
{
|
||||||
|
ExpenseTypeName = e.ExpensesType!.Name, // If enum, use e.ExpensesCategory.ToString()
|
||||||
|
Amount = e.Amount,
|
||||||
|
StatusId = e.StatusId
|
||||||
|
})
|
||||||
|
.GroupBy(x => x.ExpenseTypeName)
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
ProjectName = g.Key, // Original code used g.Key!.Name; here the grouping key is already a string
|
||||||
|
TotalApprovedAmount = g.Where(x => x.StatusId == Processed
|
||||||
|
|| x.StatusId == ProcessPending).Sum(x => x.Amount),
|
||||||
|
TotalPendingAmount = g.Where(x => x.StatusId != Processed
|
||||||
|
&& x.StatusId != RejectedByReviewer
|
||||||
|
&& x.StatusId != RejectedByApprover)
|
||||||
|
.Sum(x => x.Amount),
|
||||||
|
TotalRejectedAmount = g.Where(x => x.StatusId == RejectedByReviewer
|
||||||
|
|| x.StatusId == RejectedByApprover)
|
||||||
|
.Sum(x => x.Amount),
|
||||||
|
TotalProcessedAmount = g.Where(x => x.StatusId == Processed)
|
||||||
|
.Sum(x => x.Amount)
|
||||||
|
})
|
||||||
|
.OrderBy(r => r.ProjectName); // Server-side order [memory:7]
|
||||||
|
|
||||||
|
var report = await query.ToListAsync(); // Single round-trip [memory:7]
|
||||||
|
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
Report = report,
|
||||||
|
TotalAmount = report.Sum(r => r.TotalApprovedAmount)
|
||||||
|
};
|
||||||
|
|
||||||
|
_logger.LogInfo(
|
||||||
|
"GetExpenseReportByExpenseType completed. TenantId={TenantId}, Filters: ProjectId={ProjectId}, StartDate={StartDate}, EndDate={EndDate}, Rows={RowCount}, TotalAmount={TotalAmount}",
|
||||||
|
tenantId, projectId ?? Guid.Empty, startDate, endDate, report.Count, response.TotalAmount); // [Completion Log] [memory:4]
|
||||||
|
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Expense report by expense type fetched successfully", 200)); // [Success Response] [memory:1]
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("GetExpenseReportByExpenseType canceled by client. TenantId={TenantId}", tenantId); // [Cancel Log] [memory:4]
|
||||||
|
return StatusCode(499, ApiResponse<object>.ErrorResponse("Client has canceled the opration", "Client has canceled the opration", 499)); // [Cancel Response] [memory:1]
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex,
|
||||||
|
"GetExpenseReportByExpenseType failed. TenantId={TenantId}, ProjectId={ProjectId}, StartDate={StartDate}, EndDate={EndDate}",
|
||||||
|
tenantId, projectId ?? Guid.Empty, startDate, endDate); // [Error Log] [memory:4]
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError,
|
||||||
|
ApiResponse<object>.ErrorResponse("An error occurred while fetching the expense report.", 500)); // [Error Response] [memory:1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("expense/pendings")]
|
||||||
|
public async Task<IActionResult> GetPendingExpenseListAsync([FromQuery] Guid? projectId)
|
||||||
|
{
|
||||||
|
// Start log with correlation fields
|
||||||
|
_logger.LogDebug(
|
||||||
|
"GetPendingExpenseListAsync started. Project={ProjectId} TenantId={TenantId}", projectId ?? Guid.Empty, tenantId); // [Start Log]
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Resolve current employee once; avoid using scoped services inside Task.Run
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); // [User Context]
|
||||||
|
|
||||||
|
// Resolve permission service from current scope once
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
|
||||||
|
// Fire permission checks concurrently without Task.Run; these are async I/O methods
|
||||||
|
|
||||||
|
var hasReviewPermissionTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await _permission.HasPermission(PermissionsMaster.ExpenseReview, loggedInEmployee.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
var hasApprovePermissionTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await _permission.HasPermission(PermissionsMaster.ExpenseApprove, loggedInEmployee.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
var hasProcessPermissionTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await _permission.HasPermission(PermissionsMaster.ExpenseProcess, loggedInEmployee.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
var hasManagePermissionTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await _permission.HasPermission(PermissionsMaster.ExpenseManage, loggedInEmployee.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(hasReviewPermissionTask, hasApprovePermissionTask, hasProcessPermissionTask, hasManagePermissionTask); // [Parallel Await]
|
||||||
|
|
||||||
|
var hasReviewPermission = hasReviewPermissionTask.Result;
|
||||||
|
var hasApprovePermission = hasApprovePermissionTask.Result;
|
||||||
|
var hasProcessPermission = hasProcessPermissionTask.Result;
|
||||||
|
var hasManagePermission = hasManagePermissionTask.Result;
|
||||||
|
|
||||||
|
_logger.LogInfo(
|
||||||
|
"Permissions resolved: Review={Review}, Approve={Approve}, Process={Process}",
|
||||||
|
hasReviewPermission, hasApprovePermission, hasProcessPermission); // [Permissions Log]
|
||||||
|
|
||||||
|
// Build base query: read-only, tenant-scoped
|
||||||
|
var baseQuery = _context.Expenses
|
||||||
|
.Include(e => e.Status)
|
||||||
|
.AsNoTracking() // Reduce tracking overhead for read-only list
|
||||||
|
.Where(e => e.IsActive && e.TenantId == tenantId && e.StatusId != Processed && e.Status != null); // [Base Filter]
|
||||||
|
|
||||||
|
// Project to DTO in SQL to avoid heavy Include graph.
|
||||||
|
if (projectId.HasValue)
|
||||||
|
baseQuery = baseQuery.Where(e => e.ProjectId == projectId);
|
||||||
|
|
||||||
|
// Prefer ProjectTo when profiles exist; otherwise project minimal fields
|
||||||
|
var expenses = await baseQuery
|
||||||
|
.ToListAsync(); // Single round-trip; no Include needed for this shape
|
||||||
|
|
||||||
|
var draftExpenses = expenses.Where(e => e.StatusId == Draft && e.CreatedById == loggedInEmployee.Id).ToList();
|
||||||
|
var reviewExpenses = expenses.Where(e => (hasReviewPermission || e.CreatedById == loggedInEmployee.Id) && e.StatusId == Review).ToList();
|
||||||
|
var approveExpenses = expenses.Where(e => (hasApprovePermission || e.CreatedById == loggedInEmployee.Id) && e.StatusId == Approve).ToList();
|
||||||
|
var processPendingExpenses = expenses.Where(e => (hasProcessPermission || e.CreatedById == loggedInEmployee.Id) && e.StatusId == ProcessPending).ToList();
|
||||||
|
var submitedExpenses = expenses.Where(e => e.StatusId != Draft && e.CreatedById == loggedInEmployee.Id).ToList();
|
||||||
|
var totalAmount = expenses.Where(e => e.StatusId != Draft).Sum(e => e.Amount);
|
||||||
|
|
||||||
|
if (hasManagePermission)
|
||||||
|
{
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
Draft = new
|
||||||
|
{
|
||||||
|
Count = draftExpenses.Count,
|
||||||
|
TotalAmount = draftExpenses.Sum(e => e.Amount)
|
||||||
|
},
|
||||||
|
ReviewPending = new
|
||||||
|
{
|
||||||
|
Count = reviewExpenses.Count,
|
||||||
|
TotalAmount = reviewExpenses.Sum(e => e.Amount)
|
||||||
|
},
|
||||||
|
ApprovePending = new
|
||||||
|
{
|
||||||
|
Count = approveExpenses.Count,
|
||||||
|
TotalAmount = approveExpenses.Sum(e => e.Amount)
|
||||||
|
},
|
||||||
|
ProcessPending = new
|
||||||
|
{
|
||||||
|
Count = processPendingExpenses.Count,
|
||||||
|
TotalAmount = processPendingExpenses.Sum(e => e.Amount)
|
||||||
|
},
|
||||||
|
Submited = new
|
||||||
|
{
|
||||||
|
Count = submitedExpenses.Count,
|
||||||
|
TotalAmount = submitedExpenses.Sum(e => e.Amount)
|
||||||
|
},
|
||||||
|
TotalAmount = totalAmount
|
||||||
|
};
|
||||||
|
_logger.LogInfo(
|
||||||
|
"GetPendingExpenseListAsync completed. TenantId={TenantId}",
|
||||||
|
tenantId); // [Completion Log]
|
||||||
|
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Pending Expenses fetched successfully", 200)); // [Success Response]
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
Draft = new
|
||||||
|
{
|
||||||
|
Count = draftExpenses.Count
|
||||||
|
},
|
||||||
|
ReviewPending = new
|
||||||
|
{
|
||||||
|
Count = reviewExpenses.Count
|
||||||
|
},
|
||||||
|
ApprovePending = new
|
||||||
|
{
|
||||||
|
Count = approveExpenses.Count
|
||||||
|
},
|
||||||
|
ProcessPending = new
|
||||||
|
{
|
||||||
|
Count = processPendingExpenses.Count
|
||||||
|
},
|
||||||
|
Submited = new
|
||||||
|
{
|
||||||
|
Count = submitedExpenses.Count
|
||||||
|
},
|
||||||
|
TotalAmount = totalAmount
|
||||||
|
};
|
||||||
|
_logger.LogInfo(
|
||||||
|
"GetPendingExpenseListAsync completed. TenantId={TenantId}",
|
||||||
|
tenantId); // [Completion Log]
|
||||||
|
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Pending Expenses fetched successfully", 200)); // [Success Response]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("GetPendingExpenseListAsync canceled by client. TenantId={TenantId}", tenantId); // [Cancel Log]
|
||||||
|
return StatusCode(499, ApiResponse<object>.ErrorResponse("Client has canceled the opration", "Client has canceled the opration", 499)); // [Cancel Response]
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "GetPendingExpenseListAsync failed. TenantId={TenantId}", tenantId); // [Error Log]
|
||||||
|
return StatusCode(500,
|
||||||
|
ApiResponse<object>.ErrorResponse("An error occurred while fetching pending expenses.", "An error occurred while fetching pending expenses.", 500)); // [Error Response]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,25 +33,25 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
#region =================================================================== Contact Get APIs ===================================================================
|
#region =================================================================== Contact Get APIs ===================================================================
|
||||||
|
|
||||||
[HttpGet("list")]
|
[HttpGet("list")]
|
||||||
public async Task<IActionResult> GetContactList([FromQuery] string? search, [FromQuery] string? filter, [FromQuery] Guid? projectId, [FromQuery] bool active = true,
|
public async Task<IActionResult> GetContactList([FromQuery] string? searchString, [FromQuery] string? filter, [FromQuery] Guid? projectId, [FromQuery] bool active = true,
|
||||||
[FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20)
|
[FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20)
|
||||||
{
|
{
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var response = await _directoryService.GetListOfContactsAsync(search: search, filter: filter, projectId: projectId, active: active, pageSize: pageSize, pageNumber: pageNumber, tenantId, loggedInEmployee);
|
var response = await _directoryService.GetListOfContactsAsync(search: searchString, filter: filter, projectId: projectId, active: active, pageSize: pageSize, pageNumber: pageNumber, tenantId, loggedInEmployee);
|
||||||
|
|
||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> GetContactList([FromQuery] string? search, [FromQuery] List<Guid>? bucketIds, [FromQuery] List<Guid>? categoryIds, [FromQuery] Guid? projectId, [FromQuery] bool active = true)
|
public async Task<IActionResult> GetContactList([FromQuery] string? searchString, [FromQuery] List<Guid>? bucketIds, [FromQuery] List<Guid>? categoryIds, [FromQuery] Guid? projectId, [FromQuery] bool active = true)
|
||||||
{
|
{
|
||||||
ContactFilterDto filterDto = new ContactFilterDto
|
ContactFilterDto filterDto = new ContactFilterDto
|
||||||
{
|
{
|
||||||
BucketIds = bucketIds,
|
BucketIds = bucketIds,
|
||||||
CategoryIds = categoryIds
|
CategoryIds = categoryIds
|
||||||
};
|
};
|
||||||
var response = await _directoryService.GetListOfContactsOld(search, active, filterDto, projectId);
|
var response = await _directoryService.GetListOfContactsOld(searchString, active, filterDto, projectId);
|
||||||
|
|
||||||
|
|
||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
|
|||||||
@ -35,6 +35,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
private readonly ILoggingService _logger;
|
private readonly ILoggingService _logger;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
private readonly Guid tenantId;
|
private readonly Guid tenantId;
|
||||||
|
private readonly Guid organizationId;
|
||||||
|
|
||||||
private static readonly Guid ProjectEntity = Guid.Parse("c8fe7115-aa27-43bc-99f4-7b05fabe436e");
|
private static readonly Guid ProjectEntity = Guid.Parse("c8fe7115-aa27-43bc-99f4-7b05fabe436e");
|
||||||
private static readonly Guid EmployeeEntity = Guid.Parse("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7");
|
private static readonly Guid EmployeeEntity = Guid.Parse("dbb9555a-7a0c-40f2-a9ed-f0463f1ceed7");
|
||||||
@ -52,6 +53,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
|
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
|
||||||
tenantId = userHelper.GetTenantId();
|
tenantId = userHelper.GetTenantId();
|
||||||
|
organizationId = _userHelper.GetCurrentOrganizationId();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("list/{entityTypeId}/entity/{entityId}")]
|
[HttpGet("list/{entityTypeId}/entity/{entityId}")]
|
||||||
@ -93,21 +95,21 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return NotFound(ApiResponse<object>.ErrorResponse("Entity type not found", "Entity Type not found in database", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Entity type not found", "Entity Type not found in database", 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Project permission check
|
//// Project permission check
|
||||||
if (ProjectEntity == entityTypeId)
|
//if (ProjectEntity == entityTypeId)
|
||||||
{
|
//{
|
||||||
var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, entityId);
|
// var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, entityId);
|
||||||
if (!hasProjectPermission)
|
// if (!hasProjectPermission)
|
||||||
{
|
// {
|
||||||
_logger.LogWarning("Employee {EmployeeId} does not have project access for ProjectId {ProjectId}", loggedInEmployee.Id, entityId);
|
// _logger.LogWarning("Employee {EmployeeId} does not have project access for ProjectId {ProjectId}", loggedInEmployee.Id, entityId);
|
||||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to access project documents", 403));
|
// return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to access project documents", 403));
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
// Employee validation
|
// Employee validation
|
||||||
else if (EmployeeEntity == entityTypeId)
|
else if (EmployeeEntity == entityTypeId)
|
||||||
{
|
{
|
||||||
var isEmployeeExists = await _context.Employees
|
var isEmployeeExists = await _context.Employees
|
||||||
.AnyAsync(e => e.Id == entityId && e.TenantId == tenantId);
|
.AnyAsync(e => e.Id == entityId && e.OrganizationId == organizationId);
|
||||||
|
|
||||||
if (!isEmployeeExists)
|
if (!isEmployeeExists)
|
||||||
{
|
{
|
||||||
@ -691,7 +693,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
bool entityExists = false;
|
bool entityExists = false;
|
||||||
if (entityType.Equals(EmployeeEntity))
|
if (entityType.Equals(EmployeeEntity))
|
||||||
{
|
{
|
||||||
entityExists = await _context.Employees.AnyAsync(e => e.Id == model.EntityId && e.TenantId == tenantId);
|
entityExists = await _context.Employees.AnyAsync(e => e.Id == model.EntityId && e.OrganizationId == organizationId);
|
||||||
}
|
}
|
||||||
else if (entityType.Equals(ProjectEntity))
|
else if (entityType.Equals(ProjectEntity))
|
||||||
{
|
{
|
||||||
@ -1078,15 +1080,15 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
bool entityExists;
|
bool entityExists;
|
||||||
if (entityType.Equals(EmployeeEntity))
|
if (entityType.Equals(EmployeeEntity))
|
||||||
{
|
{
|
||||||
entityExists = await _context.Employees.AnyAsync(e => e.Id == oldAttachment.EntityId && e.TenantId == tenantId);
|
entityExists = await _context.Employees.AnyAsync(e => e.Id == oldAttachment.EntityId && e.OrganizationId == organizationId);
|
||||||
}
|
}
|
||||||
else if (entityType.Equals(ProjectEntity))
|
else if (entityType.Equals(ProjectEntity))
|
||||||
{
|
{
|
||||||
entityExists = await _context.Projects.AnyAsync(p => p.Id == oldAttachment.EntityId && p.TenantId == tenantId);
|
entityExists = await _context.Projects.AnyAsync(p => p.Id == oldAttachment.EntityId && p.TenantId == tenantId);
|
||||||
if (entityExists)
|
//if (entityExists)
|
||||||
{
|
//{
|
||||||
entityExists = await _permission.HasProjectPermission(loggedInEmployee, oldAttachment.EntityId);
|
// entityExists = await _permission.HasProjectPermission(loggedInEmployee, oldAttachment.EntityId);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -233,83 +233,11 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
_logger.LogInfo("GetEmployeesByProject called. EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, showInactive: {ShowInactive}",
|
_logger.LogInfo("GetEmployeesByProject called. EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, showInactive: {ShowInactive}",
|
||||||
loggedInEmployee.Id, projectId ?? Guid.Empty, showInactive);
|
loggedInEmployee.Id, projectId ?? Guid.Empty, showInactive);
|
||||||
|
|
||||||
// Step 3: Fetch permissions concurrently
|
var employees = await _context.Employees
|
||||||
var viewAllTask = Task.Run(async () =>
|
.Include(e => e.JobRole)
|
||||||
{
|
.Include(e => e.Organization)
|
||||||
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
.Where(e => e.OrganizationId == loggedInEmployee.OrganizationId && e.IsActive != showInactive)
|
||||||
return await _permission.HasPermission(PermissionsMaster.ViewAllEmployees, loggedInEmployee.Id);
|
.ToListAsync();
|
||||||
});
|
|
||||||
var viewTeamTask = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
|
||||||
return await _permission.HasPermission(PermissionsMaster.ViewTeamMembers, loggedInEmployee.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
await Task.WhenAll(viewAllTask, viewTeamTask);
|
|
||||||
|
|
||||||
var hasViewAllEmployeesPermission = viewAllTask.Result;
|
|
||||||
var hasViewTeamMembersPermission = viewTeamTask.Result;
|
|
||||||
|
|
||||||
List<Employee> employees = new List<Employee>();
|
|
||||||
|
|
||||||
// Step 4: Query based on permission
|
|
||||||
if (hasViewAllEmployeesPermission && !projectId.HasValue)
|
|
||||||
{
|
|
||||||
// OrganizationId needs to be retrieved from loggedInEmployee or context based on your app's structure
|
|
||||||
var employeeQuery = _context.Employees
|
|
||||||
.AsNoTracking() // Optimize EF query for read-only operation[web:1][web:13][web:18]
|
|
||||||
.Include(e => e.JobRole)
|
|
||||||
.Where(e => e.OrganizationId == organizationId);
|
|
||||||
|
|
||||||
employeeQuery = showInactive
|
|
||||||
? employeeQuery.Where(e => !e.IsActive)
|
|
||||||
: employeeQuery.Where(e => e.IsActive);
|
|
||||||
|
|
||||||
employees = await employeeQuery.ToListAsync();
|
|
||||||
_logger.LogInfo("Employee list fetched with full access. Count: {Count}", employees.Count);
|
|
||||||
}
|
|
||||||
else if (hasViewTeamMembersPermission && !showInactive && !projectId.HasValue)
|
|
||||||
{
|
|
||||||
// Only active team members with limited permission
|
|
||||||
var projectIds = await _projectServices.GetMyProjectIdsAsync(tenantId, loggedInEmployee);
|
|
||||||
|
|
||||||
employees = await _context.ProjectAllocations
|
|
||||||
.AsNoTracking()
|
|
||||||
.Include(pa => pa.Employee)
|
|
||||||
.ThenInclude(e => e!.JobRole)
|
|
||||||
.Where(pa =>
|
|
||||||
projectIds.Contains(pa.ProjectId)
|
|
||||||
&& pa.IsActive
|
|
||||||
&& pa.Employee != null
|
|
||||||
&& pa.Employee.IsActive
|
|
||||||
&& pa.TenantId == tenantId)
|
|
||||||
.Select(pa => pa.Employee!)
|
|
||||||
.Distinct()
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
_logger.LogInfo("Employee list fetched with limited access (active only). Count: {Count}", employees.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a specific projectId is provided, override employee fetching to ensure strict project context
|
|
||||||
if (projectId.HasValue)
|
|
||||||
{
|
|
||||||
employees = await _context.ProjectAllocations
|
|
||||||
.AsNoTracking()
|
|
||||||
.Include(pa => pa.Employee)
|
|
||||||
.ThenInclude(e => e!.JobRole)
|
|
||||||
.Where(pa =>
|
|
||||||
pa.ProjectId == projectId
|
|
||||||
&& pa.IsActive
|
|
||||||
&& pa.Employee != null
|
|
||||||
&& pa.Employee.IsActive
|
|
||||||
&& pa.TenantId == tenantId)
|
|
||||||
.Select(pa => pa.Employee!)
|
|
||||||
.Distinct()
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
_logger.LogInfo("Employee list fetched for specific project. ProjectId: {ProjectId}. Count: {Count}",
|
|
||||||
projectId, employees.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 5: Map to view model
|
// Step 5: Map to view model
|
||||||
result = employees.Select(e => _mapper.Map<EmployeeVM>(e)).Distinct().ToList();
|
result = employees.Select(e => _mapper.Map<EmployeeVM>(e)).Distinct().ToList();
|
||||||
@ -329,7 +257,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
|
|
||||||
[HttpGet("basic")]
|
[HttpGet("basic")]
|
||||||
public async Task<IActionResult> GetEmployeesByProjectBasic(Guid? projectId, [FromQuery] string? searchString)
|
public async Task<IActionResult> GetEmployeesByProjectBasic(Guid? projectId, [FromQuery] string? searchString, [FromQuery] bool sendAll = false)
|
||||||
{
|
{
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var employeeQuery = _context.Employees.Where(e => e.IsActive);
|
var employeeQuery = _context.Employees.Where(e => e.IsActive);
|
||||||
@ -353,8 +281,11 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
var searchStringLower = searchString.ToLower();
|
var searchStringLower = searchString.ToLower();
|
||||||
employeeQuery = employeeQuery.Where(e => (e.FirstName + " " + e.LastName).ToLower().Contains(searchStringLower));
|
employeeQuery = employeeQuery.Where(e => (e.FirstName + " " + e.LastName).ToLower().Contains(searchStringLower));
|
||||||
}
|
}
|
||||||
|
if (!sendAll)
|
||||||
var response = await employeeQuery.Take(10).Select(e => _mapper.Map<BasicEmployeeVM>(e)).ToListAsync();
|
{
|
||||||
|
employeeQuery = employeeQuery.Take(10);
|
||||||
|
}
|
||||||
|
var response = await employeeQuery.Select(e => _mapper.Map<BasicEmployeeVM>(e)).ToListAsync();
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(response, $"{response.Count} records of employees fetched successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(response, $"{response.Count} records of employees fetched successfully", 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,6 +401,9 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
Guid tenantId = _userHelper.GetTenantId();
|
Guid tenantId = _userHelper.GetTenantId();
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
Guid employeeId = Guid.Empty;
|
Guid employeeId = Guid.Empty;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (model == null)
|
if (model == null)
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", "Invaild Data", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", "Invaild Data", 400));
|
||||||
|
|
||||||
@ -602,6 +536,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
{
|
{
|
||||||
// Correlation and context capture for logs
|
// Correlation and context capture for logs
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
Guid organizationId = model.OrganizationId ?? loggedInEmployee.OrganizationId;
|
||||||
|
|
||||||
{
|
{
|
||||||
if (model == null)
|
if (model == null)
|
||||||
@ -625,10 +560,10 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
if (model.Id.HasValue && model.Id.Value != Guid.Empty)
|
if (model.Id.HasValue && model.Id.Value != Guid.Empty)
|
||||||
{
|
{
|
||||||
existingEmployee = await _context.Employees
|
existingEmployee = await _context.Employees
|
||||||
.FirstOrDefaultAsync(e => e.Id == model.Id && e.OrganizationId == model.OrganizationId);
|
.FirstOrDefaultAsync(e => e.Id == model.Id && e.OrganizationId == organizationId);
|
||||||
if (existingEmployee == null)
|
if (existingEmployee == null)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("Employee not found for update. Id={EmployeeId}, Org={OrgId}", model.Id, model.OrganizationId);
|
_logger.LogInfo("Employee not found for update. Id={EmployeeId}, Org={OrgId}", model.Id, organizationId);
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Employee not found", "Employee not found in database", 404));
|
return NotFound(ApiResponse<object>.ErrorResponse("Employee not found", "Employee not found in database", 404));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -680,10 +615,10 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
if (!string.IsNullOrWhiteSpace(model.Email))
|
if (!string.IsNullOrWhiteSpace(model.Email))
|
||||||
{
|
{
|
||||||
var emailExists = await _context.Employees
|
var emailExists = await _context.Employees
|
||||||
.AnyAsync(e => e.Email == model.Email && e.OrganizationId == model.OrganizationId);
|
.AnyAsync(e => e.Email == model.Email);
|
||||||
if (emailExists)
|
if (emailExists)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("Employee email already exists in org. Email={Email}, Org={OrgId}", model.Email, model.OrganizationId);
|
_logger.LogInfo("Employee email already exists. Email={Email}", model.Email);
|
||||||
return StatusCode(403, ApiResponse<object>.ErrorResponse(
|
return StatusCode(403, ApiResponse<object>.ErrorResponse(
|
||||||
"Employee with email already exists",
|
"Employee with email already exists",
|
||||||
"Employee with this email already exists", 403));
|
"Employee with this email already exists", 403));
|
||||||
@ -723,7 +658,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
existingEmployee.ApplicationUserId = createdIdentityUser.Id;
|
existingEmployee.ApplicationUserId = createdIdentityUser.Id;
|
||||||
await SendResetIfApplicableAsync(createdIdentityUser, existingEmployee.FirstName ?? "User");
|
await SendResetIfApplicableAsync(createdIdentityUser, existingEmployee.FirstName ?? "User");
|
||||||
}
|
}
|
||||||
|
existingEmployee.OrganizationId = organizationId;
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
employeeId = existingEmployee.Id;
|
employeeId = existingEmployee.Id;
|
||||||
@ -745,7 +680,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
newEmployee.ApplicationUserId = createdIdentityUser.Id;
|
newEmployee.ApplicationUserId = createdIdentityUser.Id;
|
||||||
await SendResetIfApplicableAsync(createdIdentityUser, newEmployee.FirstName ?? "User");
|
await SendResetIfApplicableAsync(createdIdentityUser, newEmployee.FirstName ?? "User");
|
||||||
}
|
}
|
||||||
|
newEmployee.OrganizationId = organizationId;
|
||||||
await _context.Employees.AddAsync(newEmployee);
|
await _context.Employees.AddAsync(newEmployee);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
@ -877,6 +812,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
public async Task<IActionResult> CreateUserMobileAsync([FromBody] MobileUserManageDto model)
|
public async Task<IActionResult> CreateUserMobileAsync([FromBody] MobileUserManageDto model)
|
||||||
{
|
{
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
Guid organizationId = model.OrganizationId ?? loggedInEmployee.OrganizationId;
|
||||||
if (tenantId == Guid.Empty)
|
if (tenantId == Guid.Empty)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Tenant resolution failed in CreateUserMobile"); // structured warning
|
_logger.LogWarning("Tenant resolution failed in CreateUserMobile"); // structured warning
|
||||||
@ -912,11 +848,11 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
if (model.Id == null || model.Id == Guid.Empty)
|
if (model.Id == null || model.Id == Guid.Empty)
|
||||||
{
|
{
|
||||||
var emailExists = await _context.Employees
|
var emailExists = await _context.Employees
|
||||||
.AnyAsync(e => e.Email == model.Email && e.OrganizationId == model.OrganizationId);
|
.AnyAsync(e => e.Email == model.Email);
|
||||||
|
|
||||||
if (emailExists)
|
if (emailExists)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("Employee email already exists in org. Email={Email}, Org={OrgId}", model.Email ?? string.Empty, model.OrganizationId);
|
_logger.LogInfo("Employee email already exists in org. Email={Email}, Org={OrgId}", model.Email ?? string.Empty, organizationId);
|
||||||
return StatusCode(409, ApiResponse<object>.ErrorResponse("Employee with email already exists", "Employee with this email already exists", 409));
|
return StatusCode(409, ApiResponse<object>.ErrorResponse("Employee with email already exists", "Employee with this email already exists", 409));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -933,7 +869,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
JoiningDate = model.JoiningDate,
|
JoiningDate = model.JoiningDate,
|
||||||
JobRoleId = model.JobRoleId,
|
JobRoleId = model.JobRoleId,
|
||||||
Photo = imageBytes,
|
Photo = imageBytes,
|
||||||
OrganizationId = model.OrganizationId,
|
OrganizationId = organizationId,
|
||||||
HasApplicationAccess = model.HasApplicationAccess,
|
HasApplicationAccess = model.HasApplicationAccess,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1001,7 +937,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
existingEmployee.PhoneNumber = model.PhoneNumber;
|
existingEmployee.PhoneNumber = model.PhoneNumber;
|
||||||
existingEmployee.JoiningDate = model.JoiningDate;
|
existingEmployee.JoiningDate = model.JoiningDate;
|
||||||
existingEmployee.JobRoleId = model.JobRoleId;
|
existingEmployee.JobRoleId = model.JobRoleId;
|
||||||
existingEmployee.OrganizationId = model.OrganizationId;
|
existingEmployee.OrganizationId = organizationId;
|
||||||
existingEmployee.HasApplicationAccess = model.HasApplicationAccess;
|
existingEmployee.HasApplicationAccess = model.HasApplicationAccess;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(existingEmployee.Email) && !string.IsNullOrWhiteSpace(model.Email))
|
if (string.IsNullOrWhiteSpace(existingEmployee.Email) && !string.IsNullOrWhiteSpace(model.Email))
|
||||||
@ -1011,7 +947,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
if (emailExists)
|
if (emailExists)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("Employee email already exists in org. Email={Email}, Org={OrgId}", model.Email, model.OrganizationId);
|
_logger.LogInfo("Employee email already exists in org. Email={Email}, Org={OrgId}", model.Email, organizationId);
|
||||||
return StatusCode(409, ApiResponse<object>.ErrorResponse("Employee with email already exists", "Employee with this email already exists", 409));
|
return StatusCode(409, ApiResponse<object>.ErrorResponse("Employee with email already exists", "Employee with this email already exists", 409));
|
||||||
}
|
}
|
||||||
existingEmployee.Email = model.Email;
|
existingEmployee.Email = model.Email;
|
||||||
@ -1075,7 +1011,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
Guid tenantId = _userHelper.GetTenantId();
|
||||||
var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
Employee? employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == id && e.TenantId == tenantId);
|
Employee? employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == id && e.OrganizationId == organizationId);
|
||||||
if (employee == null)
|
if (employee == null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Employee with ID {EmploueeId} not found in database", id);
|
_logger.LogWarning("Employee with ID {EmploueeId} not found in database", id);
|
||||||
@ -1249,10 +1185,13 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
// Prepare reset link sender helper
|
// Prepare reset link sender helper
|
||||||
private async Task SendResetIfApplicableAsync(ApplicationUser u, string firstName)
|
private async Task SendResetIfApplicableAsync(ApplicationUser u, string firstName)
|
||||||
{
|
{
|
||||||
var token = await _userManager.GeneratePasswordResetTokenAsync(u);
|
if (!string.IsNullOrWhiteSpace(u.Email))
|
||||||
var resetLink = $"{_configuration["AppSettings:WebFrontendUrl"]}/reset-password?token={WebUtility.UrlEncode(token)}";
|
{
|
||||||
await _emailSender.SendResetPasswordEmailOnRegister(u.Email ?? "", firstName, resetLink);
|
var token = await _userManager.GeneratePasswordResetTokenAsync(u);
|
||||||
_logger.LogInfo("Reset password email queued. Email={Email}", u.Email ?? "");
|
var resetLink = $"{_configuration["AppSettings:WebFrontendUrl"]}/reset-password?token={WebUtility.UrlEncode(token)}";
|
||||||
|
await _emailSender.SendResetPasswordEmailOnRegister(u.Email, firstName, resetLink);
|
||||||
|
_logger.LogInfo("Reset password email queued. Email={Email}", u.Email);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
tenantId = userHelper.GetTenantId();
|
tenantId = userHelper.GetTenantId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region =================================================================== Expense Functions ===================================================================
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves a paginated list of expenses based on user permissions and optional filters.
|
/// Retrieves a paginated list of expenses based on user permissions and optional filters.
|
||||||
@ -122,5 +123,21 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region =================================================================== Payment Request Functions ===================================================================
|
||||||
|
[HttpPost("payment-request/create")]
|
||||||
|
public async Task<IActionResult> CreatePaymentRequest([FromBody] PaymentRequestDto model)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _expensesService.CreatePaymentRequestAsync(model, loggedInEmployee, tenantId);
|
||||||
|
if (response.Success)
|
||||||
|
{
|
||||||
|
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Payment_Request", Response = response.Data };
|
||||||
|
await _signalR.SendNotificationAsync(notification);
|
||||||
|
}
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Marco.Pms.DataAccess.Data;
|
using Marco.Pms.DataAccess.Data;
|
||||||
using Marco.Pms.Model.Dtos.Activities;
|
using Marco.Pms.Model.Dtos.Activities;
|
||||||
|
using Marco.Pms.Model.Dtos.Collection;
|
||||||
using Marco.Pms.Model.Dtos.DocumentManager;
|
using Marco.Pms.Model.Dtos.DocumentManager;
|
||||||
using Marco.Pms.Model.Dtos.Master;
|
using Marco.Pms.Model.Dtos.Master;
|
||||||
using Marco.Pms.Model.Forum;
|
using Marco.Pms.Model.Forum;
|
||||||
@ -975,5 +976,38 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region =================================================================== Payment Adjustment Head APIs ===================================================================
|
||||||
|
[HttpGet("payment-adjustment-head/list")]
|
||||||
|
public async Task<IActionResult> GetpaymentAdjustmentHeadsList([FromQuery] bool isActive = true)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _masterService.GetPaymentAdjustmentHeadListAsync(isActive, loggedInEmployee, tenantId);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
[HttpPost("payment-adjustment-head")]
|
||||||
|
public async Task<IActionResult> CreatePaymentAdjustmentHead([FromBody] PaymentAdjustmentHeadDto dto)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _masterService.CreatePaymentAdjustmentHeadAsync(dto, loggedInEmployee, tenantId);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("payment-adjustment-head/edit/{id}")]
|
||||||
|
public async Task<IActionResult> UpdatePaymentAdjustmentHead(Guid id, [FromBody] PaymentAdjustmentHeadDto dto)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _masterService.UpdatePaymentAdjustmentHeadAsync(id, dto, loggedInEmployee, tenantId);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("payment-adjustment-head/delete/{id}")]
|
||||||
|
public async Task<IActionResult> DeletePaymentAdjustmentHead(Guid id, [FromQuery] bool isActive = false)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _masterService.DeletePaymentAdjustmentHeadAsync(id, isActive, loggedInEmployee, tenantId);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
108
Marco.Pms.Services/Controllers/PaymentController.cs
Normal file
108
Marco.Pms.Services/Controllers/PaymentController.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
using Marco.Pms.Model.Dtos.PaymentGetway;
|
||||||
|
using Marco.Pms.Model.Utilities;
|
||||||
|
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||||
|
using MarcoBMS.Services.Helpers;
|
||||||
|
using MarcoBMS.Services.Service;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Services.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class PaymentController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly UserHelper _userHelper;
|
||||||
|
private readonly ILoggingService _logger;
|
||||||
|
private readonly IRazorpayService _razorpayService;
|
||||||
|
private readonly Guid tenantId;
|
||||||
|
private readonly Guid organizaionId;
|
||||||
|
public PaymentController(UserHelper userHelper, ILoggingService logger, IRazorpayService razorpayService)
|
||||||
|
{
|
||||||
|
_userHelper = userHelper;
|
||||||
|
_logger = logger;
|
||||||
|
_razorpayService = razorpayService;
|
||||||
|
tenantId = userHelper.GetTenantId();
|
||||||
|
organizaionId = userHelper.GetCurrentOrganizationId();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("create-order")]
|
||||||
|
public async Task<IActionResult> CreateOrder([FromBody] CreateOrderDto model)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = _razorpayService.CreateOrder(model.Amount, loggedInEmployee, tenantId);
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Payment created successfully", 200));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Error occured While creating the payment", new
|
||||||
|
{
|
||||||
|
Message = ex.Message,
|
||||||
|
StackTrace = ex.StackTrace,
|
||||||
|
Source = ex.Source,
|
||||||
|
InnerException = new
|
||||||
|
{
|
||||||
|
Message = ex.InnerException?.Message,
|
||||||
|
StackTrace = ex.InnerException?.StackTrace,
|
||||||
|
Source = ex.InnerException?.Source,
|
||||||
|
}
|
||||||
|
}, 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("verify-payment")]
|
||||||
|
public async Task<IActionResult> VerifyPayment([FromBody] PaymentVerificationRequest request)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInfo("Payment verification started for OrderId: {OrderId}, PaymentId: {PaymentId}",
|
||||||
|
request.OrderId ?? "", request.PaymentId ?? "");
|
||||||
|
|
||||||
|
// Validate request
|
||||||
|
if (string.IsNullOrEmpty(request.OrderId) || string.IsNullOrEmpty(request.PaymentId) || string.IsNullOrEmpty(request.Signature))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Payment verification failed - Missing required parameters");
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse("Missing required parameters", 400));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify signature
|
||||||
|
string payload = request.OrderId + "|" + request.PaymentId;
|
||||||
|
string actualSignature = request.Signature;
|
||||||
|
string expectedSignature = _razorpayService.GetExpectedSignature(payload);
|
||||||
|
|
||||||
|
if (actualSignature == expectedSignature)
|
||||||
|
{
|
||||||
|
_logger.LogInfo("Payment signature verified successfully for OrderId: {OrderId}", request.OrderId);
|
||||||
|
|
||||||
|
// Fetch complete payment details from Razorpay including card details
|
||||||
|
var response = await _razorpayService.GetPaymentDetails(request.PaymentId);
|
||||||
|
|
||||||
|
_logger.LogInfo("Invoice generated and saved for OrderId: {OrderId}", request.OrderId);
|
||||||
|
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Payment verified successfully", 200));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Payment signature verification failed for OrderId: {OrderId}", request.OrderId);
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid signature - Payment verification failed", "Invalid signature - Payment verification failed", 400));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during payment verification for OrderId: {OrderId}", request.OrderId ?? "");
|
||||||
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("An error occurred during payment verification", "An error occurred during payment verification", 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("get/payment-details/{id}")]
|
||||||
|
public async Task<IActionResult> GetPaymentDetails(Guid id)
|
||||||
|
{
|
||||||
|
var paymentsDetails = await _razorpayService.GetPaymentDetailsFromDataBase(id);
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(paymentsDetails, "Payment fetched Successfully", 200));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -482,6 +482,13 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
taskAllocationQuery = taskAllocationQuery.Where(t => t.WorkItem != null &&
|
taskAllocationQuery = taskAllocationQuery.Where(t => t.WorkItem != null &&
|
||||||
taskFilter.ActivityIds.Contains(t.WorkItem.ActivityId));
|
taskFilter.ActivityIds.Contains(t.WorkItem.ActivityId));
|
||||||
}
|
}
|
||||||
|
if (taskFilter.ServiceIds?.Any() ?? false)
|
||||||
|
{
|
||||||
|
taskAllocationQuery = taskAllocationQuery.Where(t => t.WorkItem != null &&
|
||||||
|
t.WorkItem.ActivityMaster != null &&
|
||||||
|
t.WorkItem.ActivityMaster.ActivityGroup != null &&
|
||||||
|
taskFilter.ServiceIds.Contains(t.WorkItem.ActivityMaster.ActivityGroup.ServiceId));
|
||||||
|
}
|
||||||
if (taskFilter.dateFrom.HasValue && taskFilter.dateTo.HasValue)
|
if (taskFilter.dateFrom.HasValue && taskFilter.dateTo.HasValue)
|
||||||
{
|
{
|
||||||
taskAllocationQuery = taskAllocationQuery.Where(t => t.AssignmentDate.Date >= taskFilter.dateFrom.Value.Date &&
|
taskAllocationQuery = taskAllocationQuery.Where(t => t.AssignmentDate.Date >= taskFilter.dateFrom.Value.Date &&
|
||||||
@ -745,6 +752,97 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(taskVM, "Success", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(taskVM, "Success", 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("filter/{projectId}")]
|
||||||
|
public async Task<IActionResult> GetTaskFilterObject(Guid projectId)
|
||||||
|
{
|
||||||
|
// Get the current tenant from claims/context
|
||||||
|
Guid tenantId = GetTenantId();
|
||||||
|
|
||||||
|
// Log API invocation with the project and tenant for traceability
|
||||||
|
_logger.LogInfo("Fetching filter objects for ProjectId={ProjectId}, TenantId={TenantId}", projectId, tenantId);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// AsNoTracking for improved performance—no intention to update these records
|
||||||
|
// Only fetch & project properties actually required (DTO projection)
|
||||||
|
var tasks = await _context.TaskAllocations
|
||||||
|
.Include(t => t.WorkItem)
|
||||||
|
.ThenInclude(wi => wi!.WorkArea)
|
||||||
|
.ThenInclude(wa => wa!.Floor)
|
||||||
|
.ThenInclude(f => f!.Building)
|
||||||
|
.Include(t => t.WorkItem)
|
||||||
|
.ThenInclude(wi => wi!.ActivityMaster)
|
||||||
|
.ThenInclude(a => a!.ActivityGroup)
|
||||||
|
.ThenInclude(ag => ag!.Service)
|
||||||
|
.Where(t => t.WorkItem != null &&
|
||||||
|
t.WorkItem.WorkArea != null &&
|
||||||
|
t.WorkItem.WorkArea.Floor != null &&
|
||||||
|
t.WorkItem.WorkArea.Floor.Building != null &&
|
||||||
|
t.WorkItem.WorkArea.Floor.Building.ProjectId == projectId &&
|
||||||
|
t.TenantId == tenantId).ToListAsync();
|
||||||
|
|
||||||
|
// Distinct by Id (since projection doesn't guarantee uniqueness across different allocations)
|
||||||
|
var buildings = tasks.Where(t => t.WorkItem != null && t.WorkItem.WorkArea != null && t.WorkItem.WorkArea.Floor != null && t.WorkItem.WorkArea.Floor.Building != null)
|
||||||
|
.Select(t => t.WorkItem!.WorkArea!.Floor!.Building!)
|
||||||
|
.Select(b => new
|
||||||
|
{
|
||||||
|
Id = b.Id,
|
||||||
|
Name = b.Name
|
||||||
|
}).Distinct().ToList();
|
||||||
|
|
||||||
|
var floors = tasks.Where(t => t.WorkItem != null && t.WorkItem.WorkArea != null && t.WorkItem.WorkArea.Floor != null)
|
||||||
|
.Select(t => t.WorkItem!.WorkArea!.Floor!)
|
||||||
|
.Select(f => new
|
||||||
|
{
|
||||||
|
Id = f.Id,
|
||||||
|
Name = f.FloorName,
|
||||||
|
BuildingId = f.BuildingId
|
||||||
|
}).Distinct().ToList();
|
||||||
|
|
||||||
|
var activities = tasks.Where(t => t.WorkItem != null &&
|
||||||
|
t.WorkItem.ActivityMaster != null &&
|
||||||
|
t.WorkItem.ActivityMaster.ActivityGroup != null &&
|
||||||
|
t.WorkItem.ActivityMaster.ActivityGroup.Service != null)
|
||||||
|
.Select(t => t.WorkItem!.ActivityMaster!)
|
||||||
|
.Select(a => new
|
||||||
|
{
|
||||||
|
Id = a.Id,
|
||||||
|
Name = a.ActivityName
|
||||||
|
}).Distinct().ToList();
|
||||||
|
|
||||||
|
var services = tasks.Where(t => t.WorkItem != null &&
|
||||||
|
t.WorkItem.ActivityMaster != null &&
|
||||||
|
t.WorkItem.ActivityMaster.ActivityGroup != null &&
|
||||||
|
t.WorkItem.ActivityMaster.ActivityGroup.Service != null)
|
||||||
|
.Select(t => t.WorkItem!.ActivityMaster!.ActivityGroup!.Service!)
|
||||||
|
.Select(s => new
|
||||||
|
{
|
||||||
|
Id = s.Id,
|
||||||
|
Name = s.Name
|
||||||
|
}).Distinct().ToList();
|
||||||
|
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
Buildings = buildings,
|
||||||
|
Floors = floors,
|
||||||
|
Activities = activities,
|
||||||
|
Services = services
|
||||||
|
};
|
||||||
|
|
||||||
|
_logger.LogInfo("Successfully fetched filter objects for ProjectId={ProjectId}, TenantId={TenantId}", projectId, tenantId);
|
||||||
|
|
||||||
|
// Use DTO in API response for clarity and easier frontend usage
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Filter object for task fetched successfully", 200));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Failed to fetch filter objects for ProjectId={ProjectId}, TenantId={TenantId}", projectId, tenantId);
|
||||||
|
// Return a standard error result
|
||||||
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Failed to fetch filter object.", 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Approves a reported task after validation, updates status, and stores attachments/comments.
|
/// Approves a reported task after validation, updates status, and stores attachments/comments.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -16,6 +16,7 @@ using Marco.Pms.Model.ViewModels.Activities;
|
|||||||
using Marco.Pms.Model.ViewModels.Tenant;
|
using Marco.Pms.Model.ViewModels.Tenant;
|
||||||
using Marco.Pms.Services.Helpers;
|
using Marco.Pms.Services.Helpers;
|
||||||
using Marco.Pms.Services.Service;
|
using Marco.Pms.Services.Service;
|
||||||
|
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||||
using MarcoBMS.Services.Helpers;
|
using MarcoBMS.Services.Helpers;
|
||||||
using MarcoBMS.Services.Service;
|
using MarcoBMS.Services.Service;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
@ -230,6 +231,8 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
{
|
{
|
||||||
_logger.LogInfo("GetTenantDetails started for TenantId: {TenantId}", id);
|
_logger.LogInfo("GetTenantDetails started for TenantId: {TenantId}", id);
|
||||||
|
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
|
||||||
// Get currently logged-in employee info
|
// Get currently logged-in employee info
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
if (loggedInEmployee == null)
|
if (loggedInEmployee == null)
|
||||||
@ -240,32 +243,27 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
|
|
||||||
// Check permissions using a single service scope to avoid overhead
|
// Check permissions using a single service scope to avoid overhead
|
||||||
bool hasManagePermission, hasModifyPermission, hasViewPermission;
|
bool hasManagePermission, hasModifyPermission, hasViewPermission;
|
||||||
using (var scope = _serviceScopeFactory.CreateScope())
|
var manageTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
|
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id);
|
||||||
|
});
|
||||||
|
var modifyTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await permissionService.HasPermission(PermissionsMaster.ModifyTenant, loggedInEmployee.Id);
|
||||||
|
});
|
||||||
|
var viewTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await permissionService.HasPermission(PermissionsMaster.ViewTenant, loggedInEmployee.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(manageTask, modifyTask, viewTask);
|
||||||
|
|
||||||
var manageTask = Task.Run(async () =>
|
hasManagePermission = manageTask.Result;
|
||||||
{
|
hasModifyPermission = modifyTask.Result;
|
||||||
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
hasViewPermission = viewTask.Result;
|
||||||
return await permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id);
|
|
||||||
});
|
|
||||||
var modifyTask = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
|
||||||
return await permissionService.HasPermission(PermissionsMaster.ModifyTenant, loggedInEmployee.Id);
|
|
||||||
});
|
|
||||||
var viewTask = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
|
||||||
return await permissionService.HasPermission(PermissionsMaster.ViewTenant, loggedInEmployee.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
await Task.WhenAll(manageTask, modifyTask, viewTask);
|
|
||||||
|
|
||||||
hasManagePermission = manageTask.Result;
|
|
||||||
hasModifyPermission = modifyTask.Result;
|
|
||||||
hasViewPermission = viewTask.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasManagePermission && !hasModifyPermission && !hasViewPermission)
|
if (!hasManagePermission && !hasModifyPermission && !hasViewPermission)
|
||||||
{
|
{
|
||||||
@ -273,12 +271,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return StatusCode(403,
|
return StatusCode(403,
|
||||||
ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403));
|
ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403));
|
||||||
}
|
}
|
||||||
if (!hasManagePermission && (hasModifyPermission || hasViewPermission) && id != loggedInEmployee.TenantId)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Permission denied: User {EmployeeId} attempted to access tenant details of other tenant.", loggedInEmployee.Id);
|
|
||||||
return StatusCode(403,
|
|
||||||
ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a single DbContext for main tenant fetch and related data requests
|
// Create a single DbContext for main tenant fetch and related data requests
|
||||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
@ -297,6 +290,13 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
_logger.LogInfo("Tenant {TenantId} found.", tenant.Id);
|
_logger.LogInfo("Tenant {TenantId} found.", tenant.Id);
|
||||||
|
|
||||||
|
if (!hasManagePermission && (tenant.OrganizationId != loggedInEmployee.OrganizationId || (!hasModifyPermission && !hasViewPermission)))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Permission denied: User {EmployeeId} attempted to access tenant details of other tenant.", loggedInEmployee.Id);
|
||||||
|
return StatusCode(403,
|
||||||
|
ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403));
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch dependent data in parallel to improve performance
|
// Fetch dependent data in parallel to improve performance
|
||||||
var employeesTask = Task.Run(async () =>
|
var employeesTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@ -351,6 +351,11 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var plans = plansTask.Result;
|
var plans = plansTask.Result;
|
||||||
var projects = projectsTask.Result;
|
var projects = projectsTask.Result;
|
||||||
|
|
||||||
|
var _razorpayService = scope.ServiceProvider.GetRequiredService<IRazorpayService>();
|
||||||
|
|
||||||
|
var paymentDetailIds = plans.Where(ts => ts.PaymentDetailId.HasValue).Select(ts => ts.PaymentDetailId!.Value).ToList();
|
||||||
|
var paymentsDetails = await _razorpayService.GetPaymentDetailsListFromDataBase(paymentDetailIds);
|
||||||
|
|
||||||
// Calculate active/inactive employees count
|
// Calculate active/inactive employees count
|
||||||
var activeEmployeesCount = employees.Count(e => e.IsActive);
|
var activeEmployeesCount = employees.Count(e => e.IsActive);
|
||||||
var inActiveEmployeesCount = employees.Count - activeEmployeesCount;
|
var inActiveEmployeesCount = employees.Count - activeEmployeesCount;
|
||||||
@ -379,9 +384,16 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
response.CreatedBy = createdBy;
|
response.CreatedBy = createdBy;
|
||||||
|
|
||||||
response.CurrentPlan = _mapper.Map<SubscriptionPlanDetailsVM>(currentPlan);
|
response.CurrentPlan = _mapper.Map<SubscriptionPlanDetailsVM>(currentPlan);
|
||||||
|
response.CurrentPlan.PaymentDetail = paymentsDetails.FirstOrDefault(pd => currentPlan != null && pd.Id == currentPlan.PaymentDetailId);
|
||||||
|
|
||||||
response.CurrentPlanFeatures = await _featureDetailsHelper.GetFeatureDetails(currentPlan?.Plan?.FeaturesId ?? Guid.Empty);
|
response.CurrentPlanFeatures = await _featureDetailsHelper.GetFeatureDetails(currentPlan?.Plan?.FeaturesId ?? Guid.Empty);
|
||||||
// Map subscription history plans to DTO
|
// Map subscription history plans to DTO
|
||||||
response.SubscriptionHistery = _mapper.Map<List<SubscriptionPlanDetailsVM>>(plans);
|
response.SubscriptionHistery = plans.Select(ts =>
|
||||||
|
{
|
||||||
|
var result = _mapper.Map<SubscriptionPlanDetailsVM>(ts);
|
||||||
|
result.PaymentDetail = paymentsDetails.FirstOrDefault(pd => ts != null && pd.Id == ts.PaymentDetailId);
|
||||||
|
return result;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
_logger.LogInfo("Tenant details fetched successfully for TenantId: {TenantId}", tenant.Id);
|
_logger.LogInfo("Tenant details fetched successfully for TenantId: {TenantId}", tenant.Id);
|
||||||
|
|
||||||
@ -550,7 +562,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
JobRole = adminJobRole, // Link to the newly created role
|
JobRole = adminJobRole, // Link to the newly created role
|
||||||
CurrentAddress = model.BillingAddress,
|
CurrentAddress = model.BillingAddress,
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
IsSystem = false,
|
IsSystem = true,
|
||||||
IsPrimary = true,
|
IsPrimary = true,
|
||||||
OrganizationId = organization.Id,
|
OrganizationId = organization.Id,
|
||||||
HasApplicationAccess = true
|
HasApplicationAccess = true
|
||||||
@ -566,43 +578,36 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
};
|
};
|
||||||
_context.ApplicationRoles.Add(applicationRole);
|
_context.ApplicationRoles.Add(applicationRole);
|
||||||
|
|
||||||
var rolePermissionMappigs = new List<RolePermissionMappings> {
|
var featureIds = new List<Guid>
|
||||||
new RolePermissionMappings
|
{
|
||||||
{
|
new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), // Expense Management feature
|
||||||
ApplicationRoleId = applicationRole.Id,
|
new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), // Employee Management feature
|
||||||
FeaturePermissionId = PermissionsMaster.ModifyTenant
|
new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), // Attendance Management feature
|
||||||
},
|
new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), // Document Management feature
|
||||||
new RolePermissionMappings
|
new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), // Masters Management feature
|
||||||
{
|
new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), // Directory Management feature
|
||||||
ApplicationRoleId = applicationRole.Id,
|
new Guid("6d4c82d6-dbce-48ab-b8b8-f785f4d8c914") // Organization Management feature
|
||||||
FeaturePermissionId = PermissionsMaster.ViewTenant
|
|
||||||
},
|
|
||||||
new RolePermissionMappings
|
|
||||||
{
|
|
||||||
ApplicationRoleId = applicationRole.Id,
|
|
||||||
FeaturePermissionId = PermissionsMaster.ManageMasters
|
|
||||||
},
|
|
||||||
new RolePermissionMappings
|
|
||||||
{
|
|
||||||
ApplicationRoleId = applicationRole.Id,
|
|
||||||
FeaturePermissionId = PermissionsMaster.ViewMasters
|
|
||||||
},
|
|
||||||
new RolePermissionMappings
|
|
||||||
{
|
|
||||||
ApplicationRoleId = applicationRole.Id,
|
|
||||||
FeaturePermissionId = PermissionsMaster.ViewOrganization
|
|
||||||
},
|
|
||||||
new RolePermissionMappings
|
|
||||||
{
|
|
||||||
ApplicationRoleId = applicationRole.Id,
|
|
||||||
FeaturePermissionId = PermissionsMaster.AddOrganization
|
|
||||||
},
|
|
||||||
new RolePermissionMappings
|
|
||||||
{
|
|
||||||
ApplicationRoleId = applicationRole.Id,
|
|
||||||
FeaturePermissionId = PermissionsMaster.EditOrganization
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var permissionIds = await _context.FeaturePermissions.Where(fp => featureIds.Contains(fp.FeatureId)).Select(fp => fp.Id).ToListAsync();
|
||||||
|
|
||||||
|
var rolePermissionMappigs = permissionIds.Select(p => new RolePermissionMappings
|
||||||
|
{
|
||||||
|
ApplicationRoleId = applicationRole.Id,
|
||||||
|
FeaturePermissionId = p
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
rolePermissionMappigs.Add(new RolePermissionMappings
|
||||||
|
{
|
||||||
|
ApplicationRoleId = applicationRole.Id,
|
||||||
|
FeaturePermissionId = PermissionsMaster.ModifyTenant
|
||||||
|
});
|
||||||
|
rolePermissionMappigs.Add(new RolePermissionMappings
|
||||||
|
{
|
||||||
|
ApplicationRoleId = applicationRole.Id,
|
||||||
|
FeaturePermissionId = PermissionsMaster.ViewTenant
|
||||||
|
});
|
||||||
|
|
||||||
_context.RolePermissionMappings.AddRange(rolePermissionMappigs);
|
_context.RolePermissionMappings.AddRange(rolePermissionMappigs);
|
||||||
|
|
||||||
_context.EmployeeRoleMappings.Add(new EmployeeRoleMapping
|
_context.EmployeeRoleMappings.Add(new EmployeeRoleMapping
|
||||||
@ -651,6 +656,20 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_context.OrgServiceMappings.AddRange(serviceOrgMappings);
|
_context.OrgServiceMappings.AddRange(serviceOrgMappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _masteData = scope.ServiceProvider.GetRequiredService<MasterDataService>();
|
||||||
|
|
||||||
|
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
|
||||||
|
var documentCategoryMaster = _masteData.GetDocumentCategoryData(tenant.Id);
|
||||||
|
|
||||||
|
var employeeDocumentId = documentCategoryMaster.Where(dc => dc.Name == "Employee Documents").Select(dc => dc.Id).FirstOrDefault();
|
||||||
|
var projectDocumentId = documentCategoryMaster.Where(dc => dc.Name == "Project Documents").Select(dc => dc.Id).FirstOrDefault();
|
||||||
|
|
||||||
|
var documentTypeMaster = _masteData.GetDocumentTypeData(tenant.Id, employeeDocumentId, projectDocumentId);
|
||||||
|
|
||||||
|
_context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
|
||||||
|
_context.DocumentCategoryMasters.AddRange(documentCategoryMaster);
|
||||||
|
_context.DocumentTypeMasters.AddRange(documentTypeMaster);
|
||||||
|
|
||||||
// All entities are now added to the context. Save them all in a single database operation.
|
// All entities are now added to the context. Save them all in a single database operation.
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
@ -913,6 +932,58 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(responseData, successMessage, 200));
|
return Ok(ApiResponse<object>.SuccessResponse(responseData, successMessage, 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost("self/create")]
|
||||||
|
public async Task<IActionResult> SelfRegistrationTenant([FromBody] TenantEnquireDto model)
|
||||||
|
{
|
||||||
|
// Log the start of the registration attempt
|
||||||
|
_logger.LogInfo("Self-registration request received at {Timestamp}.", DateTime.UtcNow);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create db context asynchronously for optimized resource use
|
||||||
|
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
|
||||||
|
// 2. --- VALIDATION ---
|
||||||
|
// Check if a user with the same email already exists.
|
||||||
|
var existingUser = await _userManager.FindByEmailAsync(model.Email);
|
||||||
|
if (existingUser != null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Tenant creation failed for email {Email}: an application user with this email already exists.", model.Email);
|
||||||
|
return StatusCode(409, ApiResponse<object>.ErrorResponse("Tenant cannot be created", "A user with the specified email already exists.", 409));
|
||||||
|
}
|
||||||
|
|
||||||
|
var industry = await context.Industries.FirstOrDefaultAsync(i => i.Id == model.IndustryId);
|
||||||
|
if (industry == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Industry not found while creating the tenant enquire");
|
||||||
|
return NotFound(ApiResponse<object>.ErrorResponse("Industry not found", "Industry not found", 404));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map DTO to domain model and assign new Guid
|
||||||
|
var tenantEnquire = _mapper.Map<TenantEnquire>(model);
|
||||||
|
tenantEnquire.Id = Guid.NewGuid();
|
||||||
|
|
||||||
|
// Add new tenant enquiry to the database
|
||||||
|
await context.TenantEnquires.AddAsync(tenantEnquire);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
|
// Log successful registration
|
||||||
|
_logger.LogInfo("Tenant enquiry created successfully. ID: {TenantEnquireId}", tenantEnquire.Id);
|
||||||
|
|
||||||
|
// Return success response with proper status code and user information
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(tenantEnquire, "Tenant enquiry added successfully.", 201));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Log error with detailed exception information at Error level
|
||||||
|
_logger.LogError(ex, "Error occurred during self-registration: {Message}", ex.Message);
|
||||||
|
|
||||||
|
// Return standardized error response to the client
|
||||||
|
var errorResponse = ApiResponse<object>.ErrorResponse("Failed to add tenant enquiry, please try again later.", "Failed to add tenant enquiry, please try again later.", 500);
|
||||||
|
|
||||||
|
return StatusCode(500, errorResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -1127,6 +1198,9 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Removed {Count} role permission mappings for role {RoleId}", deleteMappings.Count, roleId);
|
_logger.LogInfo("Removed {Count} role permission mappings for role {RoleId}", deleteMappings.Count, roleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||||
|
await _cache.ClearAllEmployeesFromCacheByTenantId(tenant.Id);
|
||||||
|
|
||||||
var _masteData = scope.ServiceProvider.GetRequiredService<MasterDataService>();
|
var _masteData = scope.ServiceProvider.GetRequiredService<MasterDataService>();
|
||||||
|
|
||||||
if (features.Modules?.ProjectManagement?.Enabled ?? false)
|
if (features.Modules?.ProjectManagement?.Enabled ?? false)
|
||||||
@ -1140,10 +1214,8 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
if (features.Modules?.Expense?.Enabled ?? false)
|
if (features.Modules?.Expense?.Enabled ?? false)
|
||||||
{
|
{
|
||||||
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
|
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
|
||||||
var paymentModeMatser = _masteData.GetPaymentModesData(tenant.Id);
|
|
||||||
|
|
||||||
_context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
|
_context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
|
||||||
_context.PaymentModeMatser.AddRange(paymentModeMatser);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
@ -1301,7 +1373,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
PlanId = model.PlanId,
|
PlanId = model.PlanId,
|
||||||
StatusId = activePlanStatus,
|
StatusId = activePlanStatus,
|
||||||
CreatedAt = utcNow,
|
CreatedAt = utcNow,
|
||||||
MaxUsers = model.MaxUsers ?? (currentSubscription?.MaxUsers ?? subscriptionPlan.MaxUser),
|
MaxUsers = subscriptionPlan.MaxUser,
|
||||||
CreatedById = loggedInEmployee.Id,
|
CreatedById = loggedInEmployee.Id,
|
||||||
CurrencyId = model.CurrencyId,
|
CurrencyId = model.CurrencyId,
|
||||||
StartDate = utcNow,
|
StartDate = utcNow,
|
||||||
@ -1439,6 +1511,9 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogInfo("Permissions revoked: {Count} for Role={RoleId}", mappingsToRemove.Count, rootRoleId);
|
_logger.LogInfo("Permissions revoked: {Count} for Role={RoleId}", mappingsToRemove.Count, rootRoleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||||
|
await _cache.ClearAllEmployeesFromCacheByTenantId(tenant.Id);
|
||||||
|
|
||||||
var _masteData = scope.ServiceProvider.GetRequiredService<MasterDataService>();
|
var _masteData = scope.ServiceProvider.GetRequiredService<MasterDataService>();
|
||||||
|
|
||||||
if (features.Modules?.ProjectManagement?.Enabled ?? false)
|
if (features.Modules?.ProjectManagement?.Enabled ?? false)
|
||||||
@ -1473,7 +1548,6 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
if (features.Modules?.Expense?.Enabled ?? false)
|
if (features.Modules?.Expense?.Enabled ?? false)
|
||||||
{
|
{
|
||||||
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
|
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
|
||||||
var paymentModeMatser = _masteData.GetPaymentModesData(tenant.Id);
|
|
||||||
|
|
||||||
var expensesTypeTask = Task.Run(async () =>
|
var expensesTypeTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@ -1481,25 +1555,14 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var expensesTypeNames = expensesTypeMaster.Select(et => et.Name).ToList();
|
var expensesTypeNames = expensesTypeMaster.Select(et => et.Name).ToList();
|
||||||
return await _context.ExpensesTypeMaster.AnyAsync(et => expensesTypeNames.Contains(et.Name) && et.TenantId == tenant.Id);
|
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
await Task.WhenAll(expensesTypeTask, paymentModeTask);
|
await Task.WhenAll(expensesTypeTask);
|
||||||
|
|
||||||
var expensesTypeExist = expensesTypeTask.Result;
|
var expensesTypeExist = expensesTypeTask.Result;
|
||||||
var paymentModeExist = paymentModeTask.Result;
|
|
||||||
if (!expensesTypeExist)
|
if (!expensesTypeExist)
|
||||||
{
|
{
|
||||||
context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
|
context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
|
||||||
}
|
}
|
||||||
if (!paymentModeExist)
|
|
||||||
{
|
|
||||||
context.PaymentModeMatser.AddRange(paymentModeMatser);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
@ -1523,6 +1586,43 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost("self/subscription")]
|
||||||
|
public async Task<IActionResult> SelfSubscriptionAsync(SelfSubscriptionDto model)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var _tenantService = scope.ServiceProvider.GetRequiredService<ITenantService>();
|
||||||
|
var response = await _tenantService.CreateTenantAsync(model.TenantEnquireId, model.PaymentDetailId, model.PlanId);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occured while add self subscription");
|
||||||
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Error Occured while self subscription", "Error Occured while self subscription", 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("renew/subscription")]
|
||||||
|
public async Task<IActionResult> RenewSubscriptionAsync(RenewSubscriptionDto model)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var _tenantService = scope.ServiceProvider.GetRequiredService<ITenantService>();
|
||||||
|
var response = await _tenantService.RenewSubscriptionAsync(tenantId, loggedInEmployee.Id, model.PaymentDetailId, model.PlanId);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occured while add renewing subscription");
|
||||||
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Error Occured while renewing subscription", "Error Occured while renewing subscription", 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Subscription Plan APIs ===================================================================
|
#region =================================================================== Subscription Plan APIs ===================================================================
|
||||||
|
|||||||
@ -956,6 +956,18 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
_logger.LogError(ex, "Error occured while deleting all employees from Cache");
|
_logger.LogError(ex, "Error occured while deleting all employees from Cache");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task ClearAllEmployeesFromCacheByTenantId(Guid tenantId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await _employeeCache.ClearAllEmployeesFromCacheByTenantId(tenantId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error occured while deleting all employees from Cache");
|
||||||
|
}
|
||||||
|
}
|
||||||
public async Task ClearAllEmployees()
|
public async Task ClearAllEmployees()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -1178,7 +1190,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
var paymentModeTask = Task.Run(async () =>
|
var paymentModeTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
|
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 () =>
|
var statusMappingTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@ -1308,7 +1320,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
var paymentModeTask = Task.Run(async () =>
|
var paymentModeTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
|
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 () =>
|
var statusMappingTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -24,7 +24,7 @@ namespace MarcoBMS.Services.Helpers
|
|||||||
public async Task<Employee> GetEmployeeByID(Guid EmployeeID)
|
public async Task<Employee> GetEmployeeByID(Guid EmployeeID)
|
||||||
{
|
{
|
||||||
|
|
||||||
return await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.Id == EmployeeID) ?? new Employee { };
|
return await _context.Employees.Include(e => e.JobRole).Include(e => e.Organization).FirstOrDefaultAsync(e => e.Id == EmployeeID) ?? new Employee { };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Employee> GetEmployeeByApplicationUserID(string ApplicationUserID)
|
public async Task<Employee> GetEmployeeByApplicationUserID(string ApplicationUserID)
|
||||||
|
|||||||
@ -253,17 +253,29 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
!ts.IsCancelled &&
|
!ts.IsCancelled &&
|
||||||
ts.EndDate.Date >= DateTime.UtcNow.Date); // FIX: Subscription should not be expired
|
ts.EndDate.Date >= DateTime.UtcNow.Date); // FIX: Subscription should not be expired
|
||||||
|
|
||||||
|
//var featureIds = new List<Guid>
|
||||||
|
//{
|
||||||
|
// new Guid("a4e25142-449b-4334-a6e5-22f70e4732d7"), // Expense Management feature
|
||||||
|
// new Guid("81ab8a87-8ccd-4015-a917-0627cee6a100"), // Employee Management feature
|
||||||
|
// new Guid("52c9cf54-1eb2-44d2-81bb-524cf29c0a94"), // Attendance Management feature
|
||||||
|
// new Guid("a8cf4331-8f04-4961-8360-a3f7c3cc7462"), // Document Management feature
|
||||||
|
// new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be"), // Masters Management feature
|
||||||
|
// new Guid("39e66f81-efc6-446c-95bd-46bff6cfb606"), // Directory Management feature
|
||||||
|
// new Guid("6d4c82d6-dbce-48ab-b8b8-f785f4d8c914") // Organization Management feature
|
||||||
|
// //new Guid("2f3509b7-160d-410a-b9b6-daadd96c986d") // Tenant Management feature
|
||||||
|
//};
|
||||||
|
|
||||||
|
var featureIds = new List<Guid> { new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be") };
|
||||||
|
|
||||||
if (tenantSubscription == null)
|
if (tenantSubscription == null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("No active subscription found for tenant: {TenantId}", tenantId);
|
_logger.LogWarning("No active subscription found for tenant: {TenantId}", tenantId);
|
||||||
return new List<Guid>();
|
return featureIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("Active subscription found for tenant: {TenantId}, PlanId: {PlanId}",
|
_logger.LogDebug("Active subscription found for tenant: {TenantId}, PlanId: {PlanId}",
|
||||||
tenantId, tenantSubscription.Plan!.Id);
|
tenantId, tenantSubscription.Plan!.Id);
|
||||||
|
|
||||||
var featureIds = new List<Guid> { new Guid("2f3509b7-160d-410a-b9b6-daadd96c986d"), new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be") };
|
|
||||||
|
|
||||||
// Step 2: Get feature details from Plan
|
// Step 2: Get feature details from Plan
|
||||||
var featureDetails = await _featureDetailsHelper.GetFeatureDetails(tenantSubscription.Plan!.FeaturesId);
|
var featureDetails = await _featureDetailsHelper.GetFeatureDetails(tenantSubscription.Plan!.FeaturesId);
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
using MarcoBMS.Services.Service;
|
using MarcoBMS.Services.Service;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
namespace Marco.Pms.Services.Hubs
|
namespace Marco.Pms.Services.Hubs
|
||||||
{
|
{
|
||||||
[Authorize]
|
//[Authorize]
|
||||||
public class MarcoHub : Hub
|
public class MarcoHub : Hub
|
||||||
{
|
{
|
||||||
private readonly ILoggingService _logger;
|
private readonly ILoggingService _logger;
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Marco.Pms.Model.AppMenu;
|
using Marco.Pms.Model.AppMenu;
|
||||||
|
using Marco.Pms.Model.Collection;
|
||||||
using Marco.Pms.Model.Directory;
|
using Marco.Pms.Model.Directory;
|
||||||
using Marco.Pms.Model.DocumentManager;
|
using Marco.Pms.Model.DocumentManager;
|
||||||
using Marco.Pms.Model.Dtos.Activities;
|
using Marco.Pms.Model.Dtos.Activities;
|
||||||
using Marco.Pms.Model.Dtos.AppMenu;
|
using Marco.Pms.Model.Dtos.AppMenu;
|
||||||
|
using Marco.Pms.Model.Dtos.Collection;
|
||||||
using Marco.Pms.Model.Dtos.Directory;
|
using Marco.Pms.Model.Dtos.Directory;
|
||||||
using Marco.Pms.Model.Dtos.DocumentManager;
|
using Marco.Pms.Model.Dtos.DocumentManager;
|
||||||
using Marco.Pms.Model.Dtos.Employees;
|
using Marco.Pms.Model.Dtos.Employees;
|
||||||
@ -26,6 +28,7 @@ using Marco.Pms.Model.Projects;
|
|||||||
using Marco.Pms.Model.TenantModels;
|
using Marco.Pms.Model.TenantModels;
|
||||||
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
||||||
using Marco.Pms.Model.ViewModels.Activities;
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
using Marco.Pms.Model.ViewModels.Collection;
|
||||||
using Marco.Pms.Model.ViewModels.Directory;
|
using Marco.Pms.Model.ViewModels.Directory;
|
||||||
using Marco.Pms.Model.ViewModels.DocumentManager;
|
using Marco.Pms.Model.ViewModels.DocumentManager;
|
||||||
using Marco.Pms.Model.ViewModels.Employee;
|
using Marco.Pms.Model.ViewModels.Employee;
|
||||||
@ -58,6 +61,7 @@ namespace Marco.Pms.Services.MappingProfiles
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ======================================================= Tenant =======================================================
|
#region ======================================================= Tenant =======================================================
|
||||||
|
CreateMap<TenantEnquireDto, TenantEnquire>();
|
||||||
CreateMap<Tenant, TenantVM>();
|
CreateMap<Tenant, TenantVM>();
|
||||||
CreateMap<Tenant, TenantListVM>();
|
CreateMap<Tenant, TenantListVM>();
|
||||||
CreateMap<Tenant, TenantDetailsVM>();
|
CreateMap<Tenant, TenantDetailsVM>();
|
||||||
@ -248,13 +252,31 @@ namespace Marco.Pms.Services.MappingProfiles
|
|||||||
dest => dest.Id,
|
dest => dest.Id,
|
||||||
opt => opt.MapFrom(src => Guid.Parse(src.Id)));
|
opt => opt.MapFrom(src => Guid.Parse(src.Id)));
|
||||||
|
|
||||||
|
CreateMap<Expenses, ExpenseDetailsVM>();
|
||||||
CreateMap<ExpenseDetailsMongoDB, ExpenseDetailsVM>()
|
CreateMap<ExpenseDetailsMongoDB, ExpenseDetailsVM>()
|
||||||
.ForMember(
|
.ForMember(
|
||||||
dest => dest.Id,
|
dest => dest.Id,
|
||||||
opt => opt.MapFrom(src => Guid.Parse(src.Id)));
|
opt => opt.MapFrom(src => Guid.Parse(src.Id)));
|
||||||
|
#region ======================================================= Payment Request =======================================================
|
||||||
|
CreateMap<PaymentRequestDto, PaymentRequest>();
|
||||||
|
CreateMap<PaymentRequest, PaymentRequestVM>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Collection =======================================================
|
||||||
|
CreateMap<InvoiceDto, Invoice>();
|
||||||
|
CreateMap<Invoice, InvoiceListVM>();
|
||||||
|
CreateMap<Invoice, InvoiceDetailsVM>();
|
||||||
|
|
||||||
|
CreateMap<ReceivedInvoicePaymentDto, ReceivedInvoicePayment>();
|
||||||
|
CreateMap<ReceivedInvoicePayment, ReceivedInvoicePaymentVM>();
|
||||||
|
|
||||||
|
CreateMap<InvoiceComment, InvoiceCommentVM>();
|
||||||
|
|
||||||
|
CreateMap<InvoiceAttachment, InvoiceAttachmentVM>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region ======================================================= Master =======================================================
|
#region ======================================================= Master =======================================================
|
||||||
|
|
||||||
CreateMap<FeaturePermission, FeaturePermissionVM>();
|
CreateMap<FeaturePermission, FeaturePermissionVM>();
|
||||||
@ -316,7 +338,22 @@ namespace Marco.Pms.Services.MappingProfiles
|
|||||||
// Explicitly and safely convert nullable Guid to non-nullable Guid
|
// Explicitly and safely convert nullable Guid to non-nullable Guid
|
||||||
opt => opt.MapFrom(src => src.Id ?? Guid.Empty)
|
opt => opt.MapFrom(src => src.Id ?? Guid.Empty)
|
||||||
);
|
);
|
||||||
|
CreateMap<ExpensesTypeMasterDto, 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<ExpensesTypeMaster, ExpensesTypeMasterVM>();
|
||||||
|
CreateMap<ExpenseCategoryMaster, ExpensesTypeMasterVM>();
|
||||||
|
|
||||||
|
CreateMap<ExpenseCategoryMaster, ExpensesTypeMasterMongoDB>()
|
||||||
|
.ForMember(
|
||||||
|
dest => dest.Id,
|
||||||
|
opt => opt.MapFrom(src => src.Id.ToString()))
|
||||||
|
.ForMember(
|
||||||
|
dest => dest.TenantId,
|
||||||
|
opt => opt.MapFrom(src => src.TenantId.ToString()));
|
||||||
|
|
||||||
CreateMap<ExpensesTypeMaster, ExpensesTypeMasterMongoDB>()
|
CreateMap<ExpensesTypeMaster, ExpensesTypeMasterMongoDB>()
|
||||||
.ForMember(
|
.ForMember(
|
||||||
@ -367,10 +404,7 @@ namespace Marco.Pms.Services.MappingProfiles
|
|||||||
CreateMap<PaymentModeMatser, PaymentModeMatserMongoDB>()
|
CreateMap<PaymentModeMatser, PaymentModeMatserMongoDB>()
|
||||||
.ForMember(
|
.ForMember(
|
||||||
dest => dest.Id,
|
dest => dest.Id,
|
||||||
opt => opt.MapFrom(src => src.Id.ToString()))
|
opt => opt.MapFrom(src => src.Id.ToString()));
|
||||||
.ForMember(
|
|
||||||
dest => dest.TenantId,
|
|
||||||
opt => opt.MapFrom(src => src.TenantId.ToString()));
|
|
||||||
|
|
||||||
CreateMap<PaymentModeMatserMongoDB, PaymentModeMatserVM>()
|
CreateMap<PaymentModeMatserMongoDB, PaymentModeMatserVM>()
|
||||||
.ForMember(
|
.ForMember(
|
||||||
@ -379,6 +413,35 @@ namespace Marco.Pms.Services.MappingProfiles
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Contact Category Master =======================================================
|
||||||
|
CreateMap<CreateContactCategoryDto, ContactCategoryMaster>();
|
||||||
|
CreateMap<UpdateContactCategoryDto, ContactCategoryMaster>();
|
||||||
|
CreateMap<ContactCategoryMaster, ContactCategoryVM>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Contact Tag Master =======================================================
|
||||||
|
CreateMap<CreateContactTagDto, ContactTagMaster>();
|
||||||
|
CreateMap<UpdateContactTagDto, ContactTagMaster>();
|
||||||
|
CreateMap<ContactTagMaster, ContactTagVM>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Payment Adjustment Head Master =======================================================
|
||||||
|
CreateMap<PaymentAdjustmentHeadDto, PaymentAdjustmentHead>();
|
||||||
|
CreateMap<PaymentAdjustmentHead, PaymentAdjustmentHeadVM>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Expenses Status Master =======================================================
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Expenses Status Master =======================================================
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Expenses Status Master =======================================================
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ======================================================= Expenses Status Master =======================================================
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ======================================================= Document =======================================================
|
#region ======================================================= Document =======================================================
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
<PackageReference Include="Mime-Detective" Version="24.12.2" />
|
<PackageReference Include="Mime-Detective" Version="24.12.2" />
|
||||||
<PackageReference Include="Mime-Detective.Definitions.Exhaustive" Version="24.12.2" />
|
<PackageReference Include="Mime-Detective.Definitions.Exhaustive" Version="24.12.2" />
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
||||||
|
<PackageReference Include="Razorpay" Version="3.3.2" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
|
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using Marco.Pms.CacheHelper;
|
|
||||||
using FirebaseAdmin;
|
using FirebaseAdmin;
|
||||||
using Google.Apis.Auth.OAuth2;
|
using Google.Apis.Auth.OAuth2;
|
||||||
|
using Marco.Pms.CacheHelper;
|
||||||
using Marco.Pms.DataAccess.Data;
|
using Marco.Pms.DataAccess.Data;
|
||||||
using Marco.Pms.Helpers;
|
using Marco.Pms.Helpers;
|
||||||
using Marco.Pms.Helpers.CacheHelper;
|
using Marco.Pms.Helpers.CacheHelper;
|
||||||
@ -55,7 +55,7 @@ builder.Services.AddCors(options =>
|
|||||||
policy.AllowAnyOrigin()
|
policy.AllowAnyOrigin()
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
.AllowAnyHeader()
|
.AllowAnyHeader()
|
||||||
.WithExposedHeaders("Authorization");
|
.WithExposedHeaders("Authorization", "X-Request-ID", "X-Correlation-ID");
|
||||||
});
|
});
|
||||||
|
|
||||||
// A stricter policy for production (loaded from config)
|
// A stricter policy for production (loaded from config)
|
||||||
@ -65,7 +65,8 @@ builder.Services.AddCors(options =>
|
|||||||
{
|
{
|
||||||
policy.WithOrigins(allowedOrigins)
|
policy.WithOrigins(allowedOrigins)
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
.AllowAnyHeader();
|
.AllowAnyHeader()
|
||||||
|
.WithExposedHeaders("Authorization", "X-Request-ID", "X-Correlation-ID");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
#endregion
|
#endregion
|
||||||
@ -182,6 +183,9 @@ builder.Services.AddScoped<IExpensesService, ExpensesService>();
|
|||||||
builder.Services.AddScoped<IMasterService, MasterService>();
|
builder.Services.AddScoped<IMasterService, MasterService>();
|
||||||
builder.Services.AddScoped<IDirectoryService, DirectoryService>();
|
builder.Services.AddScoped<IDirectoryService, DirectoryService>();
|
||||||
builder.Services.AddScoped<IFirebaseService, FirebaseService>();
|
builder.Services.AddScoped<IFirebaseService, FirebaseService>();
|
||||||
|
builder.Services.AddScoped<IRazorpayService, RazorpayService>();
|
||||||
|
builder.Services.AddScoped<IAesEncryption, AesEncryption>();
|
||||||
|
builder.Services.AddScoped<ITenantService, TenantService>();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Helpers
|
#region Helpers
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user