Hi, there
I have sent the project via email.
The issue is with https://localhost:44302/App/Visas
Hello, I configured Hangfire and I have this job running: RecurringJob.AddOrUpdate<IMyDomainServices>( service => service.UpdateVentesAsync(), "*/2 * * * *"); // Cron expression for every 2 minutes
I have this in my module: public override void PreInitialize() { //Adding authorization providers Configuration.Authorization.Providers.Add<AppAuthorizationProvider>();
//Adding custom AutoMapper configuration
Configuration.Modules.AbpAutoMapper().Configurators.Add(CustomDtoMapper.CreateMappings);
IocManager.Register<IMyDomainServices, MyDomainServices>();
}
Here is my interface: namespace DocuPro.DomainServices { public interface IMyDomainServices: IDomainService { Task UpdateVentesAsync(); } }
And this is my Service:
using Abp.Authorization; using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.Runtime.Session; using DocuPro; using DocuPro.Authorization.Users; using DocuPro.CommonBases; using DocuPro.DomainServices; using DocuPro.SortiesLocalesBases; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; using System.Threading.Tasks;
public class MyDomainServices : DocuProAppServiceBase, IMyDomainServices { private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IRepository<StatsVente> _statsVenteRepository;
private readonly IRepository<SortiesLocales> _sortiesLocalesRepository;
public MyDomainServices(
IUnitOfWorkManager unitOfWorkManager,
IServiceScopeFactory serviceScopeFactory,
IRepository<StatsVente> statsVenteRepository,
IRepository<SortiesLocales> sortiesLocalesRepository)
{
_unitOfWorkManager = unitOfWorkManager;
_serviceScopeFactory = serviceScopeFactory;
_statsVenteRepository = statsVenteRepository;
_sortiesLocalesRepository = sortiesLocalesRepository;
}
[AbpAllowAnonymous]
public async Task UpdateVentesAsync()
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var userManager = scope.ServiceProvider.GetRequiredService<UserManager>();
var abpSession = scope.ServiceProvider.GetRequiredService<IAbpSession>();
var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
var sortiesLocalesesAppService = scope.ServiceProvider.GetRequiredService<ISortiesLocalesesAppService>();
var periodesAppService = scope.ServiceProvider.GetRequiredService<IPeriodesAppService>();
var adminUser = await userManager.FindByNameAsync("admin");
if (adminUser == null)
{
throw new InvalidOperationException("Admin user not found.");
}
using (var unitOfWork = unitOfWorkManager.Begin())
{
using (abpSession.Use(adminUser.TenantId, adminUser.Id))
{
var periodeId = await GetLatestPeriodeId();
await sortiesLocalesesAppService.UpdateStatsVentesMois(periodeId);
}
await unitOfWork.CompleteAsync();
}
}
}
public async Task<int> GetLatestPeriodeId()
{
var usedPeriodeIds = await _statsVenteRepository
.GetAll()
.Select(sv => sv.PeriodeId)
.Distinct()
.ToListAsync();
var latestPeriodeId = await _sortiesLocalesRepository
.GetAll()
.Where(p => !usedPeriodeIds.Contains(p.PeriodeId)) // Exclude PeriodeIds that are in _statsVenteRepository
.OrderByDescending(p => p.PeriodeId) // Order by PeriodeId descending
.Select(p => p.PeriodeId)
.FirstOrDefaultAsync(); // Get the first (latest) PeriodeId that is not used
return latestPeriodeId; // This will be the latest PeriodeId not used in _statsVenteRepository
}
}
My problem is that any database call returns 0 rows even though there are data there.
As you can see I struggled with authorization, unitofwork, etc. to make it work.
What is the best way to do this?
Hello, sorry was away for a while.
No ProduitLibelle is a regular model propertie.
public class Produit : AuditedEntity, IMayHaveTenant { public int? TenantId { get; set; }
[Required]
public virtual string Libelle { get; set; }
[Required]
public virtual string Code { get; set; }
public virtual bool Sommeil { get; set; }=false;
public virtual double PrixAchat { get; set; }
public virtual int? MoleculeId { get; set; }
[ForeignKey("MoleculeId")]
public Molecule MoleculeFk { get; set; }
public virtual int? ClasseTherapeutiqueId { get; set; }
[ForeignKey("ClasseTherapeutiqueId")]
public ClasseTherapeutique ClasseTherapeutiqueFk { get; set; }
public virtual int? CategoryId { get; set; }
[ForeignKey("CategoryId")]
public Category CategoryFk { get; set; }
}
public class Pays : AuditedEntity, IMayHaveTenant
{
public int? TenantId { get; set; }
[Required]
public virtual string Libelle { get; set; }
public virtual int ReseauId { get; set; }
[ForeignKey("ReseauId")]
public Reseau ReseauFk { get; set; }
}
public class Visa : FullAuditedEntity, IMayHaveTenant { public int? TenantId { get; set; }
[Required]
public virtual string Numero { get; set; }
public virtual DateTime DateObtention { get; set; }
public virtual DateTime DateValidite { get; set; }
//File
public virtual Guid? Fichier { get; set; } //File, (BinaryObjectId)
public virtual int ProduitId { get; set; }
[ForeignKey("ProduitId")]
public Produit ProduitFk { get; set; }
public virtual int PaysId { get; set; }
[ForeignKey("PaysId")]
public Pays PaysFk { get; set; }
}
Sample Produit values:
361 1 ARTEDIAM 400MG CPR B/12 ARTE154 False 40761 NULL NULL 2023-10-28 20:37:48.9148423 NULL NULL NULL 1,82 363 1 ARTEDIAM 75MG/5ML SP F/30ML ARTE156 False 40761 NULL NULL 2023-10-28 20:37:48.9148426 NULL NULL NULL 1,35 364 1 CEVIT VIT C 100MG CPR B/10 CEVI102 False 40766 NULL NULL 2023-10-28 20:37:48.9148427 NULL NULL NULL 0,53 367 1 OXAPEN 500MG CPR B/12 OXAP105 False 42041 NULL NULL 2023-10-28 20:37:48.9148428 NULL NULL NULL 1,6
Hello,
I created this:
public class Visa : FullAuditedEntity, IMayHaveTenant { public int? TenantId { get; set; }
[Required]
public virtual string Numero { get; set; }
public virtual DateTime DateObtention { get; set; }
public virtual DateTime DateValidite { get; set; }
//File
public virtual Guid? Fichier { get; set; } //File, (BinaryObjectId)
public virtual int ProduitId { get; set; }
[ForeignKey("ProduitId")]
public Produit ProduitFk { get; set; }
public virtual int PaysId { get; set; }
[ForeignKey("PaysId")]
public Pays PaysFk { get; set; }
} from powertools and it created this view:
<div class="@(await GetContainerClass())"> <div class="card card-custom gutter-b"> <div class="card-body"> <div class="form"> <div class="row align-items-center mb-4"> <div class="col-xl-12">
<div class="my-3">
<div class="input-group">
<input type="text" id="VisasTableFilter" class="form-control reload-on-change" placeholder='@L("SearchWithThreeDot")' value="@Model.FilterText">
<button id="GetVisasButton" class="btn btn-primary" type="submit"><i class="flaticon-search-1"></i></button>
</div>
</div>
</div>
</div>
</div>
<div id="AdvacedAuditFiltersArea" style="display: none" class="row mb-4">
<div class="col-md-12">
</div>
<div class="col-md-3">
<div class="my-3">
<label class="form-label" for="NumeroFilterId">@L("Numero")</label>
<input type="text" class="form-control reload-on-keyup" name="numeroFilter" id="NumeroFilterId">
</div>
</div>
<div class="col-md-3">
<div class="my-3">
<label class="form-label" for="MinDateObtentionFilterId">@L("DateObtentionRange")</label>
<div class="input-group">
<input class="form-control m-input date-picker startDate" type="text" placeholder="@L(" MinValue")" id="MinDateObtentionFilterId">
<span style="line-height: 40px;padding: 0 15px 0 15px;"> — </span>
<input class="form-control m-input date-picker endDate" type="text" placeholder="@L(" MaxValue")" id="MaxDateObtentionFilterId">
</div>
</div>
</div>
<div class="col-md-3">
<div class="my-3">
<label class="form-label" for="MinDateValiditeFilterId">@L("DateValiditeRange")</label>
<div class="input-group">
<input class="form-control m-input date-picker startDate" type="text" placeholder="@L(" MinValue")" id="MinDateValiditeFilterId">
<span style="line-height: 40px;padding: 0 15px 0 15px;"> — </span>
<input class="form-control m-input date-picker endDate" type="text" placeholder="@L(" MaxValue")" id="MaxDateValiditeFilterId">
</div>
</div>
</div>
<div class="col-md-3">
<div class="my-3">
<label class="form-label" for="ProduitLibelleFilterId">(@L("Produit")) @L("Libelle")</label>
<input type="text" class="form-control" name="produitLibelleFilter" id="ProduitLibelleFilterId">
</div>
</div>
<div class="col-md-3">
<div class="my-3">
<label class="form-label" for="PaysLibelleFilterId">(@L("Pays")) @L("Libelle")</label>
<input type="text" class="form-control" name="paysLibelleFilter" id="PaysLibelleFilterId">
</div>
</div>
<div class="col-md-12 mt-5">
<button class="btn btn-secondary btn-sm" id="btn-reset-filters">Reset</button>
</div>
</div>
<div class="row my-4">
<div class="col-xl-12">
<span id="ShowAdvancedFiltersSpan" class="text-muted clickable-item"><i class="fa fa-angle-down"></i> @L("ShowAdvancedFilters")</span>
<span id="HideAdvancedFiltersSpan" class="text-muted clickable-item" style="display: none"><i class="fa fa-angle-up"></i> @L("HideAdvancedFilters")</span>
</div>
</div>
<div class="row align-items-center">
<table id="VisasTable" class="table align-middle table-row-dashed fs-6 gy-5 dataTable no-footer">
<thead>
<tr>
<th></th>
<th>@L("Actions")</th>
<th>@L("Numero")</th>
<th>@L("DateObtention")</th>
<th>@L("DateValidite")</th>
<th>@L("Fichier")</th>
<th>@L("ProduitLibelle")</th>
<th>@L("PaysLibelle")</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
in my js i have
listAction: { ajaxFunction: _visasService.getAll, inputFilter: function () { return { //filter: $('#VisasTableFilter').val(), //numeroFilter: $('#NumeroFilterId').val(), filter: $('#VisasTableFilter').val(), numeroFilter: $('#NumeroFilterId').val() ? '' + $('#NumeroFilterId').val() + '' : '',
minDateObtentionFilter: getDateFilter($('#MinDateObtentionFilterId')),
maxDateObtentionFilter: getMaxDateFilter($('#MaxDateObtentionFilterId')),
minDateValiditeFilter: getDateFilter($('#MinDateValiditeFilterId')),
maxDateValiditeFilter: getMaxDateFilter($('#MaxDateValiditeFilterId')),
fichierFilter: $('#FichierFilterId').val(),
//produitLibelleFilter: $('#ProduitLibelleFilterId').val(),
//paysLibelleFilter: $('#PaysLibelleFilterId').val(),
produitLibelleFilter: $('#ProduitLibelleFilterId').val() ? '*' + $('#ProduitLibelleFilterId').val() + '*' : '',
paysLibelleFilter: $('#PaysLibelleFilterId').val() ? '*' + $('#PaysLibelleFilterId').val() + '*' : '',
};
}, },
and in my service I have
var filteredVisas = _visaRepository.GetAll()
.Include(e => e.ProduitFk)
.Include(e => e.PaysFk)
.WhereIf(!string.IsNullOrWhiteSpace(input.Filter), e => false || e.Numero.Contains(input.Filter))
.WhereIf(!string.IsNullOrWhiteSpace(input.NumeroFilter), e => e.Numero.Contains(input.NumeroFilter))
.WhereIf(input.MinDateObtentionFilter != null, e => e.DateObtention >= input.MinDateObtentionFilter)
.WhereIf(input.MaxDateObtentionFilter != null, e => e.DateObtention <= input.MaxDateObtentionFilter)
.WhereIf(input.MinDateValiditeFilter != null, e => e.DateValidite >= input.MinDateValiditeFilter)
.WhereIf(input.MaxDateValiditeFilter != null, e => e.DateValidite <= input.MaxDateValiditeFilter)
.WhereIf(!string.IsNullOrWhiteSpace(input.ProduitLibelleFilter), e => e.ProduitFk != null && e.ProduitFk.Libelle.ToLower().Contains(input.ProduitLibelleFilter.ToLower()))
.WhereIf(!string.IsNullOrWhiteSpace(input.PaysLibelleFilter), e => e.PaysFk != null && e.PaysFk.Libelle.Contains(input.PaysLibelleFilter));
When I filter Numero, I am able to get correct data but not with ProduitLibelle and PaysLibelle.
Please help
Thanks for the clear and thorough answer. Chose option 1 and it worked.
Hello,
I used this https://aspnetboilerplate.com/Pages/Documents/Hangfire-Integration Hi get this error on Hangfire dashboard
An exception occurred during performance of the job. Abp.Authorization.AbpAuthorizationException (desktop-5bai7bg:34012)
L'utilisateur courant ne peut pas s'authentifier à l'application!
Abp.Authorization.AbpAuthorizationException: L'utilisateur courant ne peut pas s'authentifier à l'application! at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(IEnumerable`1 authorizeAttributes) at Abp.Authorization.AuthorizationHelper.CheckPermissionsAsync(MethodInfo methodInfo, Type type) at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(MethodInfo methodInfo, Type type) at Abp.Authorization.AuthorizationInterceptor.InternalInterceptAsynchronous(IInvocation invocation) at SendNotificationJob.SendTestNotification() in xxxxl\src\DocuPro.Application\HelperControllers\NotificationBase.cs:line 61 at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor) at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
Here is my method:
using Abp.Configuration.Startup; using Abp.Domain.Repositories; using Abp.Runtime.Session; using Abp; using DocuPro.Authorization.Users; using DocuPro.Notifications; using System.Threading.Tasks; using System.Linq; using Abp.Domain.Uow; using System;
public class SendNotificationJob { private readonly INotificationAppService _notificationAppService; private readonly IAbpSession _abpSession; private readonly IRepository<User, long> _userRepository; private readonly UserManager _userManager; private readonly IMultiTenancyConfig _multiTenancyConfig; private readonly IUnitOfWorkManager _unitOfWorkManager; public SendNotificationJob( INotificationAppService notificationAppService, IAbpSession abpSession, IRepository<User, long> userRepository, UserManager userManager, IMultiTenancyConfig multiTenancyConfig, IUnitOfWorkManager unitOfWorkManager) { _notificationAppService = notificationAppService; _abpSession = abpSession; _userRepository = userRepository; _userManager = userManager; _multiTenancyConfig = multiTenancyConfig; _unitOfWorkManager = unitOfWorkManager; }
public async Task SendNotifications()
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
try
{
var users = _userRepository.GetAll().ToList();
foreach (var user in users)
{
var userIdentifier = new UserIdentifier(1, user.Id);
var message = "Your New Hangfire notification message"; // Replace with your message
await _notificationAppService.SendNotificationUsingHangfireAsync(userIdentifier, message);
}
// Commit the unit of work if everything is successful
unitOfWork.Complete();
}
catch (Exception ex)
{
// Handle exceptions or roll back the unit of work if necessary
unitOfWork.Dispose();
throw;
}
}
}
}
Hi there, how do I seed data like countries?
This is a feature request if it applies: Actually Power Tools allows you to:
My question is it possible to automate just:
for an existing model using Power Tool?
Hi, I have these entities: namespace DocuPro.DocumentBase { [Table("DocumentVersions")] [Audited] public class DocumentVersion : Entity, IMayHaveTenant { public int? TenantId { get; set; }
public virtual int? DocumentId { get; set; }
[ForeignKey("DocumentId")]
public Document DocumentFk { get; set; }
public virtual ICollection<DocumentVersionFile> DocumentVersionFiles { get; set; }
}
} namespace DocuPro.DocumentBase { [Table("DocumentVersionFiles")] [Audited] public class DocumentVersionFile : Entity, IMayHaveTenant { public int? TenantId { get; set; }
public virtual string OCR { get; set; }
public virtual string FileName { get; set; }
public virtual int? DocumentVersionId { get; set; }
[ForeignKey("DocumentVersionId")]
public DocumentVersion DocumentVersionFk { get; set; }
public virtual int? FileTypeId { get; set; }
[ForeignKey("FileTypeId")]
public FileType FileTypeFk { get; set; }
}
} namespace DocuPro.DocumentBase { [Table("FileTypes")] public class FileType : Entity {
[Required]
public virtual string Extension { get; set; }
}
}
I have this DTO: namespace DocuPro.DocumentBase.Dtos { public class GetDocumentVersionForViewDto { public DocumentVersionDto DocumentVersion { get; set; }
public string DocumentLibelle { get; set; }
}
}
In my service I have this method:
public virtual async Task<List<GetDocumentVersionForViewDto>> GetAllDocumentVersion(int documentId) { // Fetching all DocumentVersions (and associated DocumentVersionFiles) for a specific documentId var documentVersions = await _documentVersionRepository.GetAllIncluding(dv => dv.DocumentVersionFiles) .Where(dv => dv.DocumentId == documentId) .ToListAsync();
// Mapping to DTO
var documentVersionDtos = ObjectMapper.Map<List<GetDocumentVersionForViewDto>>(documentVersions);
return documentVersionDtos;
}
I get this error: XHRGET https://localhost:44302/App/DocumentTabs/TabViewInfomations?documentId=8 [HTTP/2 500 Internal Server Error 250ms]
AutoMapper.AutoMapperMappingException: Error mapping types.
Mapping types:
List1 -> List
1
System.Collections.Generic.List1[[DocuPro.DocumentBase.DocumentVersion, DocuPro.Core, Version=12.3.0.0, Culture=neutral, PublicKeyToken=null]] -> System.Collections.Generic.List
1[[DocuPro.DocumentBase.Dtos.GetDocumentVersionForViewDto, DocuPro.Application.Shared, Version=12.3.0.0, Culture=neutral, PublicKeyToken=null]]
---> AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types: DocumentVersion -> GetDocumentVersionForViewDto DocuPro.DocumentBase.DocumentVersion -> DocuPro.DocumentBase.Dtos.GetDocumentVersionForViewDto at lambda_method3201(Closure, DocumentVersion, GetDocumentVersionForViewDto, ResolutionContext) at lambda_method3200(Closure, Object, List`1, ResolutionContext)
--- End of inner exception stack trace ---
at lambda_method3200(Closure, Object, List1, ResolutionContext) at Abp.AutoMapper.AutoMapperObjectMapper.Map[TDestination](Object source) at DocuPro.DocumentBase.DocumentVersionsAppService.GetAllDocumentVersion(Int32 documentId) in C:\Users\hp\OneDrive\APPS\DocuProV10\src\DocuPro.Application\DocumentBase\DocumentVersionsAppService.cs:line 43 at Abp.Authorization.AuthorizationInterceptor.InternalInterceptAsynchronous[TResult](IInvocation invocation) at DocuPro.Web.Areas.App.Controllers.Documents.DocumentTabsController.TabViewInfomations(Nullable
1 state, Int32 documentId) in C:\Users\hp\OneDrive\APPS\DocuProV10\src\DocuPro.Web.Mvc\Areas\App\Controllers\Documents\DocumentTabsController.cs:line 84
at lambda_method3030(Closure, Object)
Yes, that did it. Thanks