using Distribution.Features.BankAccount; using Distribution.Features.ChequeBook; using Distribution.Features.GeneralLedger; using Distribution.Infra.UoW; using Distribution.Models; namespace Distribution.Features.ReceivedCheque; public class ReceivedChequeService( IReceivedChequeRepository repo, IBankAccountRepository bankAccountRepo, IUnitOfWork uow, GlPostingService gl) { private static ReceivedChequeResponse ToResponse(Models.ReceivedCheque c) => new(c.Id, c.CompanyId, c.BranchId, c.ReceivedFromType, c.ReceivedFromId, c.ReceivedFromName, c.DrawerBankName, c.DrawerBankBranch, c.AccountHolderName, c.ChequeNo, c.ChequeDate, c.Amount, c.ReceivedDate, c.ReferenceType, c.ReferenceId, c.Notes, c.CreatedBy, c.Status, c.FK_DepositBankAccountId, c.DepositDate); public async Task> ListAsync( int? companyId, int? branchId, ReceivedChequeStatus? status, ReceivedFromType? receivedFromType, int page, int pageSize) { if (page < 1) page = 1; if (pageSize < 1 || pageSize > 200) pageSize = 50; var (items, total) = await repo.ListAsync(companyId, branchId, status, receivedFromType, page, pageSize); return new PagedResult( items.Select(ToResponse).ToList(), total, page, pageSize); } public async Task CreateAsync(CreateReceivedChequeRequest request, CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(request.ReceivedFromName)) throw new InvalidOperationException("ReceivedFromName is required"); if (string.IsNullOrWhiteSpace(request.ChequeNo)) throw new InvalidOperationException("ChequeNo is required"); if (request.Amount <= 0) throw new InvalidOperationException("Amount must be greater than zero"); var cheque = new Models.ReceivedCheque { CompanyId = request.CompanyId, BranchId = request.BranchId, ReceivedFromType = request.ReceivedFromType, ReceivedFromId = request.ReceivedFromId, ReceivedFromName = request.ReceivedFromName, DrawerBankName = request.DrawerBankName, DrawerBankBranch = request.DrawerBankBranch, AccountHolderName = request.AccountHolderName, ChequeNo = request.ChequeNo, ChequeDate = request.ChequeDate, Amount = request.Amount, ReceivedDate = request.ReceivedDate, ReferenceType = request.ReferenceType, ReferenceId = request.ReferenceId, Notes = request.Notes, CreatedBy = request.CreatedBy, Status = ReceivedChequeStatus.Received }; await repo.AddAsync(cheque); await uow.CommitAsync(ct); return ToResponse(cheque); } public async Task UpdateStatusAsync(Guid id, UpdateReceivedChequeStatusRequest request, CancellationToken ct = default) { var cheque = await repo.GetByIdAsync(id); if (cheque is null) return null; switch (request.Action) { case ReceivedChequeStatusAction.Deposit: if (cheque.Status != ReceivedChequeStatus.Received) throw new InvalidOperationException("Only received cheques can be deposited"); if (request.DepositBankAccountId is null) throw new InvalidOperationException("DepositBankAccountId is required when depositing"); if (request.DepositDate is null) throw new InvalidOperationException("DepositDate is required when depositing"); var bankAccount = await bankAccountRepo.GetByIdAsync(request.DepositBankAccountId.Value); if (bankAccount is null || bankAccount.AccountType != BankAccountType.Bank) throw new InvalidOperationException("DepositBankAccountId does not reference a valid bank account"); cheque.Status = ReceivedChequeStatus.Deposited; cheque.FK_DepositBankAccountId = request.DepositBankAccountId; cheque.DepositDate = request.DepositDate; break; case ReceivedChequeStatusAction.Clear: if (cheque.Status != ReceivedChequeStatus.Deposited) throw new InvalidOperationException("Only deposited cheques can be cleared"); cheque.Status = ReceivedChequeStatus.Cleared; break; case ReceivedChequeStatusAction.Return: if (cheque.Status != ReceivedChequeStatus.Deposited) throw new InvalidOperationException("Only deposited cheques can be returned"); cheque.Status = ReceivedChequeStatus.Returned; break; case ReceivedChequeStatusAction.Cancel: if (cheque.Status != ReceivedChequeStatus.Received) throw new InvalidOperationException("Only received cheques can be cancelled"); cheque.Status = ReceivedChequeStatus.Cancelled; break; } if (!string.IsNullOrWhiteSpace(request.Notes)) cheque.Notes = request.Notes; repo.Update(cheque); await uow.CommitAsync(ct); await gl.PostReceivedChequeAsync(cheque, request.Action, ct); return ToResponse(cheque); } }