bill
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Yavsc.Billing
|
namespace Yavsc.Billing
|
||||||
@ -7,5 +8,16 @@ namespace Yavsc.Billing
|
|||||||
List<IBillItem> GetBillItems();
|
List<IBillItem> GetBillItems();
|
||||||
long Id { get; set; }
|
long Id { get; set; }
|
||||||
|
|
||||||
|
string ActivityCode { get; set; }
|
||||||
|
|
||||||
|
string PerformerId { get; set; }
|
||||||
|
string ClientId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Date de validation de la demande par le client
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
|
||||||
|
DateTime? ValidationDate { get; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
namespace Yavsc
|
namespace Yavsc
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
public interface IEstimate
|
|
||||||
|
public interface IEstimate
|
||||||
{
|
{
|
||||||
List<string> AttachedFiles { get; set; }
|
List<string> AttachedFiles { get; set; }
|
||||||
List<string> AttachedGraphics { get; }
|
List<string> AttachedGraphics { get; }
|
||||||
|
@ -110,6 +110,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="project.json" />
|
<Content Include="project.json" />
|
||||||
|
<Content Include="Workflow\IQuery.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
@ -19,8 +19,11 @@ namespace Yavsc.ApiControllers
|
|||||||
|
|
||||||
using Models.Messaging;
|
using Models.Messaging;
|
||||||
using ViewModels.Auth;
|
using ViewModels.Auth;
|
||||||
[Route("api/pdfestimate"), Authorize]
|
using Yavsc.ViewComponents;
|
||||||
public class PdfEstimateController : Controller
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
[Route("api/bill"), Authorize]
|
||||||
|
public class BillingController : Controller
|
||||||
{
|
{
|
||||||
ApplicationDbContext dbContext;
|
ApplicationDbContext dbContext;
|
||||||
private IStringLocalizer _localizer;
|
private IStringLocalizer _localizer;
|
||||||
@ -28,59 +31,64 @@ namespace Yavsc.ApiControllers
|
|||||||
private IGoogleCloudMessageSender _GCMSender;
|
private IGoogleCloudMessageSender _GCMSender;
|
||||||
private IAuthorizationService authorizationService;
|
private IAuthorizationService authorizationService;
|
||||||
|
|
||||||
private ILogger logger;
|
|
||||||
|
|
||||||
public PdfEstimateController(
|
private ILogger logger;
|
||||||
|
private IBillingService billingService;
|
||||||
|
|
||||||
|
public BillingController(
|
||||||
IAuthorizationService authorizationService,
|
IAuthorizationService authorizationService,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
IStringLocalizer<Yavsc.Resources.YavscLocalisation> SR,
|
IStringLocalizer<Yavsc.Resources.YavscLocalisation> SR,
|
||||||
ApplicationDbContext context,
|
ApplicationDbContext context,
|
||||||
IOptions<GoogleAuthSettings> googleSettings,
|
IOptions<GoogleAuthSettings> googleSettings,
|
||||||
IGoogleCloudMessageSender GCMSender
|
IGoogleCloudMessageSender GCMSender,
|
||||||
|
IBillingService billingService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_googleSettings=googleSettings.Value;
|
_googleSettings=googleSettings.Value;
|
||||||
this.authorizationService = authorizationService;
|
this.authorizationService = authorizationService;
|
||||||
dbContext = context;
|
dbContext = context;
|
||||||
logger = loggerFactory.CreateLogger<PdfEstimateController>();
|
logger = loggerFactory.CreateLogger<BillingController>();
|
||||||
this._localizer = SR;
|
this._localizer = SR;
|
||||||
_GCMSender=GCMSender;
|
_GCMSender=GCMSender;
|
||||||
|
this.billingService=billingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("get/{id}", Name = "Get"), Authorize]
|
[HttpGet("pdf/facture-{billingCode}-{id}.pdf"), Authorize]
|
||||||
public async Task<IActionResult> Get(long id)
|
public async Task<IActionResult> GetPdf(string billingCode, long id)
|
||||||
{
|
{
|
||||||
var estimate = dbContext.Estimates.Include(
|
var bill = await billingService.GetBillAsync(billingCode, id);
|
||||||
e=>e.Query
|
|
||||||
).FirstOrDefault(e=>e.Id == id);
|
if (!await authorizationService.AuthorizeAsync(User, bill, new ViewRequirement()))
|
||||||
if (!await authorizationService.AuthorizeAsync(User, estimate, new ViewRequirement()))
|
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
var filename = $"estimate-{id}.pdf";
|
var filename = $"facture-{billingCode}-{id}.pdf";
|
||||||
|
|
||||||
FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName, filename));
|
FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName, filename));
|
||||||
if (!fi.Exists) return Ok(new { Error = "Not generated" });
|
if (!fi.Exists) return Ok(new { Error = "Not generated" });
|
||||||
return File(fi.OpenRead(), "application/x-pdf", filename); ;
|
return File(fi.OpenRead(), "application/x-pdf", filename); ;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("estimate-{id}.tex", Name = "GetTex"), Authorize]
|
[HttpGet("tex/{billingCode}-{id}.tex"), Authorize]
|
||||||
public async Task<IActionResult> GetTex(long id)
|
public async Task<IActionResult> GetTex(string billingCode, long id)
|
||||||
{
|
{
|
||||||
var estimate = dbContext.Estimates.Include(
|
var bill = await billingService.GetBillAsync(billingCode, id);
|
||||||
e=>e.Query
|
|
||||||
).FirstOrDefault(e=>e.Id == id);
|
if (bill==null) return this.HttpNotFound();
|
||||||
if (!await authorizationService.AuthorizeAsync(User, estimate, new ViewRequirement()))
|
logger.LogVerbose(JsonConvert.SerializeObject(bill));
|
||||||
|
|
||||||
|
if (!await authorizationService.AuthorizeAsync(User, bill, new ViewRequirement()))
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
Response.ContentType = "text/x-tex";
|
Response.ContentType = "text/x-tex";
|
||||||
return ViewComponent("Estimate",new object[] { id, "LaTeX" });
|
return ViewComponent("Bill",new object[] { billingCode, bill , OutputFormat.LaTeX, true, false });
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("gen/{id}")]
|
[HttpPost("genpdf/{billingCode}/{id}")]
|
||||||
public async Task<IActionResult> GeneratePdf(long id)
|
public async Task<IActionResult> GeneratePdf(string billingCode, long id)
|
||||||
{
|
{
|
||||||
var estimate = dbContext.Estimates.Include(
|
var estimate = dbContext.Estimates.Include(
|
||||||
e=>e.Query
|
e=>e.Query
|
||||||
@ -89,12 +97,12 @@ namespace Yavsc.ApiControllers
|
|||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
return ViewComponent("Estimate",new object[] { id, "Pdf" } );
|
return ViewComponent("Bill",new object[] { billingCode, id, OutputFormat.Pdf } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpPost("prosign/{id}")]
|
[HttpPost("prosign/{billingCode}/{id}")]
|
||||||
public async Task<IActionResult> ProSign(long id)
|
public async Task<IActionResult> ProSign(string billingCode, long id)
|
||||||
{
|
{
|
||||||
var estimate = dbContext.Estimates.
|
var estimate = dbContext.Estimates.
|
||||||
Include(e=>e.Client).Include(e=>e.Client.Devices)
|
Include(e=>e.Client).Include(e=>e.Client.Devices)
|
||||||
@ -108,7 +116,7 @@ namespace Yavsc.ApiControllers
|
|||||||
}
|
}
|
||||||
if (Request.Form.Files.Count!=1)
|
if (Request.Form.Files.Count!=1)
|
||||||
return new BadRequestResult();
|
return new BadRequestResult();
|
||||||
User.ReceiveProSignature(id,Request.Form.Files[0],"pro");
|
User.ReceiveProSignature(billingCode,id,Request.Form.Files[0],"pro");
|
||||||
estimate.ProviderValidationDate = DateTime.Now;
|
estimate.ProviderValidationDate = DateTime.Now;
|
||||||
dbContext.SaveChanges(User.GetUserId());
|
dbContext.SaveChanges(User.GetUserId());
|
||||||
// Notify the client
|
// Notify the client
|
||||||
@ -125,8 +133,8 @@ namespace Yavsc.ApiControllers
|
|||||||
return Ok (new { ProviderValidationDate = estimate.ProviderValidationDate, GCMSent = gcmSent });
|
return Ok (new { ProviderValidationDate = estimate.ProviderValidationDate, GCMSent = gcmSent });
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("prosign/{id}")]
|
[HttpGet("prosign/{billingCode}/{id}")]
|
||||||
public async Task<IActionResult> GetProSign(long id)
|
public async Task<IActionResult> GetProSign(string billingCode, long id)
|
||||||
{
|
{
|
||||||
// For authorization purpose
|
// For authorization purpose
|
||||||
var estimate = dbContext.Estimates.FirstOrDefault(e=>e.Id == id);
|
var estimate = dbContext.Estimates.FirstOrDefault(e=>e.Id == id);
|
||||||
@ -135,14 +143,14 @@ namespace Yavsc.ApiControllers
|
|||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
var filename = FileSystemHelpers.SignFileNameFormat("pro",id);
|
var filename = FileSystemHelpers.SignFileNameFormat("pro",billingCode,id);
|
||||||
FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName, filename));
|
FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName, filename));
|
||||||
if (!fi.Exists) return HttpNotFound(new { Error = "Professional signature not found" });
|
if (!fi.Exists) return HttpNotFound(new { Error = "Professional signature not found" });
|
||||||
return File(fi.OpenRead(), "application/x-pdf", filename); ;
|
return File(fi.OpenRead(), "application/x-pdf", filename); ;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("clisign/{id}")]
|
[HttpPost("clisign/{billingCode}/{id}")]
|
||||||
public async Task<IActionResult> CliSign(long id)
|
public async Task<IActionResult> CliSign(string billingCode, long id)
|
||||||
{
|
{
|
||||||
var uid = User.GetUserId();
|
var uid = User.GetUserId();
|
||||||
var estimate = dbContext.Estimates.Include( e=>e.Query
|
var estimate = dbContext.Estimates.Include( e=>e.Query
|
||||||
@ -154,14 +162,14 @@ namespace Yavsc.ApiControllers
|
|||||||
}
|
}
|
||||||
if (Request.Form.Files.Count!=1)
|
if (Request.Form.Files.Count!=1)
|
||||||
return new BadRequestResult();
|
return new BadRequestResult();
|
||||||
User.ReceiveProSignature(id,Request.Form.Files[0],"cli");
|
User.ReceiveProSignature(billingCode,id,Request.Form.Files[0],"cli");
|
||||||
estimate.ClientValidationDate = DateTime.Now;
|
estimate.ClientValidationDate = DateTime.Now;
|
||||||
dbContext.SaveChanges(User.GetUserId());
|
dbContext.SaveChanges(User.GetUserId());
|
||||||
return Ok (new { ClientValidationDate = estimate.ClientValidationDate });
|
return Ok (new { ClientValidationDate = estimate.ClientValidationDate });
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("clisign/{id}")]
|
[HttpGet("clisign/{billingCode}/{id}")]
|
||||||
public async Task<IActionResult> GetCliSign(long id)
|
public async Task<IActionResult> GetCliSign(string billingCode, long id)
|
||||||
{
|
{
|
||||||
// For authorization purpose
|
// For authorization purpose
|
||||||
var estimate = dbContext.Estimates.FirstOrDefault(e=>e.Id == id);
|
var estimate = dbContext.Estimates.FirstOrDefault(e=>e.Id == id);
|
||||||
@ -170,7 +178,7 @@ namespace Yavsc.ApiControllers
|
|||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
var filename = FileSystemHelpers.SignFileNameFormat("pro",id);
|
var filename = FileSystemHelpers.SignFileNameFormat("pro",billingCode,id);
|
||||||
FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName, filename));
|
FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName, filename));
|
||||||
if (!fi.Exists) return HttpNotFound(new { Error = "Professional signature not found" });
|
if (!fi.Exists) return HttpNotFound(new { Error = "Professional signature not found" });
|
||||||
return File(fi.OpenRead(), "application/x-pdf", filename); ;
|
return File(fi.OpenRead(), "application/x-pdf", filename); ;
|
@ -39,7 +39,7 @@ namespace Yavsc.Controllers
|
|||||||
var uid = User.GetUserId();
|
var uid = User.GetUserId();
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
|
|
||||||
var result = _context.Commands.Include(c => c.Location).
|
var result = _context.RdvQueries.Include(c => c.Location).
|
||||||
Include(c => c.Client).Where(c => c.PerformerId == uid && c.Id < maxId && c.EventDate > now
|
Include(c => c.Client).Where(c => c.PerformerId == uid && c.Id < maxId && c.EventDate > now
|
||||||
&& c.ValidationDate == null).
|
&& c.ValidationDate == null).
|
||||||
Select(c => new RdvQueryProviderInfo
|
Select(c => new RdvQueryProviderInfo
|
||||||
@ -71,7 +71,7 @@ namespace Yavsc.Controllers
|
|||||||
}
|
}
|
||||||
var uid = User.GetUserId();
|
var uid = User.GetUserId();
|
||||||
|
|
||||||
RdvQuery bookQuery = _context.Commands.Where(c => c.ClientId == uid || c.PerformerId == uid).Single(m => m.Id == id);
|
RdvQuery bookQuery = _context.RdvQueries.Where(c => c.ClientId == uid || c.PerformerId == uid).Single(m => m.Id == id);
|
||||||
|
|
||||||
if (bookQuery == null)
|
if (bookQuery == null)
|
||||||
{
|
{
|
||||||
@ -133,7 +133,7 @@ namespace Yavsc.Controllers
|
|||||||
ModelState.AddModelError("ClientId", "You must be the client at creating a book query");
|
ModelState.AddModelError("ClientId", "You must be the client at creating a book query");
|
||||||
return new BadRequestObjectResult(ModelState);
|
return new BadRequestObjectResult(ModelState);
|
||||||
}
|
}
|
||||||
_context.Commands.Add(bookQuery);
|
_context.RdvQueries.Add(bookQuery);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_context.SaveChanges(User.GetUserId());
|
_context.SaveChanges(User.GetUserId());
|
||||||
@ -162,7 +162,7 @@ namespace Yavsc.Controllers
|
|||||||
return HttpBadRequest(ModelState);
|
return HttpBadRequest(ModelState);
|
||||||
}
|
}
|
||||||
var uid = User.GetUserId();
|
var uid = User.GetUserId();
|
||||||
RdvQuery bookQuery = _context.Commands.Single(m => m.Id == id);
|
RdvQuery bookQuery = _context.RdvQueries.Single(m => m.Id == id);
|
||||||
|
|
||||||
if (bookQuery == null)
|
if (bookQuery == null)
|
||||||
{
|
{
|
||||||
@ -170,7 +170,7 @@ namespace Yavsc.Controllers
|
|||||||
}
|
}
|
||||||
if (bookQuery.ClientId != uid) return HttpNotFound();
|
if (bookQuery.ClientId != uid) return HttpNotFound();
|
||||||
|
|
||||||
_context.Commands.Remove(bookQuery);
|
_context.RdvQueries.Remove(bookQuery);
|
||||||
_context.SaveChanges(User.GetUserId());
|
_context.SaveChanges(User.GetUserId());
|
||||||
|
|
||||||
return Ok(bookQuery);
|
return Ok(bookQuery);
|
||||||
@ -187,7 +187,7 @@ namespace Yavsc.Controllers
|
|||||||
|
|
||||||
private bool BookQueryExists(long id)
|
private bool BookQueryExists(long id)
|
||||||
{
|
{
|
||||||
return _context.Commands.Count(e => e.Id == id) > 0;
|
return _context.RdvQueries.Count(e => e.Id == id) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
19
Yavsc/Attributes/ActivityBillingAttribute.cs
Normal file
19
Yavsc/Attributes/ActivityBillingAttribute.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Yavsc.Attributes
|
||||||
|
{
|
||||||
|
public class ActivityBillingAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string BillingCode { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifie une entité de facturation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="billingCode">Code de facturation,
|
||||||
|
/// Il doit avoir une valeur unique par usage.
|
||||||
|
/// </param>
|
||||||
|
public ActivityBillingAttribute(string billingCode) {
|
||||||
|
BillingCode = billingCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,10 @@ using Microsoft.AspNet.Authorization;
|
|||||||
|
|
||||||
namespace Yavsc.ViewModels.Auth.Handlers
|
namespace Yavsc.ViewModels.Auth.Handlers
|
||||||
{
|
{
|
||||||
using Models.Workflow;
|
using Billing;
|
||||||
public class CommandEditHandler : AuthorizationHandler<EditRequirement, RdvQuery>
|
public class BillEditHandler : AuthorizationHandler<EditRequirement, IBillable>
|
||||||
{
|
{
|
||||||
protected override void Handle(AuthorizationContext context, EditRequirement requirement, RdvQuery resource)
|
protected override void Handle(AuthorizationContext context, EditRequirement requirement, IBillable resource)
|
||||||
{
|
{
|
||||||
if (context.User.IsInRole("FrontOffice"))
|
if (context.User.IsInRole("FrontOffice"))
|
||||||
context.Succeed(requirement);
|
context.Succeed(requirement);
|
@ -3,10 +3,11 @@ using Microsoft.AspNet.Authorization;
|
|||||||
|
|
||||||
namespace Yavsc.ViewModels.Auth.Handlers
|
namespace Yavsc.ViewModels.Auth.Handlers
|
||||||
{
|
{
|
||||||
using Models.Workflow;
|
using Billing;
|
||||||
public class CommandViewHandler : AuthorizationHandler<ViewRequirement, RdvQuery>
|
|
||||||
|
public class BillViewHandler : AuthorizationHandler<ViewRequirement, IBillable>
|
||||||
{
|
{
|
||||||
protected override void Handle(AuthorizationContext context, ViewRequirement requirement, RdvQuery resource)
|
protected override void Handle(AuthorizationContext context, ViewRequirement requirement, IBillable resource)
|
||||||
{
|
{
|
||||||
if (context.User.IsInRole("FrontOffice"))
|
if (context.User.IsInRole("FrontOffice"))
|
||||||
context.Succeed(requirement);
|
context.Succeed(requirement);
|
@ -10,20 +10,25 @@ namespace Yavsc.Controllers
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Models;
|
using Models;
|
||||||
using Models.Workflow;
|
using Models.Workflow;
|
||||||
using Yavsc.Exceptions;
|
|
||||||
using Yavsc.ViewModels.Workflow;
|
using Yavsc.ViewModels.Workflow;
|
||||||
using Yavsc;
|
using Yavsc.Services;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class DoController : Controller
|
public class DoController : Controller
|
||||||
{
|
{
|
||||||
private ApplicationDbContext _context;
|
private ApplicationDbContext dbContext;
|
||||||
ILogger _logger;
|
ILogger logger;
|
||||||
|
IBillingService billing;
|
||||||
public DoController(ApplicationDbContext context,ILogger<DoController> logger)
|
public DoController(
|
||||||
|
ApplicationDbContext context,
|
||||||
|
IBillingService billing,
|
||||||
|
ILogger<DoController> logger)
|
||||||
{
|
{
|
||||||
_context = context;
|
dbContext = context;
|
||||||
_logger = logger;
|
this.billing = billing;
|
||||||
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: /Do/Index
|
// GET: /Do/Index
|
||||||
@ -33,14 +38,14 @@ namespace Yavsc.Controllers
|
|||||||
if (id == null)
|
if (id == null)
|
||||||
id = User.GetUserId();
|
id = User.GetUserId();
|
||||||
|
|
||||||
var userActivities = _context.UserActivities.Include(u => u.Does)
|
var userActivities = dbContext.UserActivities.Include(u => u.Does)
|
||||||
.Include(u => u.User).Where(u=> u.UserId == id)
|
.Include(u => u.User).Where(u=> u.UserId == id)
|
||||||
.OrderByDescending(u => u.Weight);
|
.OrderByDescending(u => u.Weight);
|
||||||
return View(userActivities.ToList());
|
return View(userActivities.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: Do/Details/5
|
// GET: Do/Details/5
|
||||||
public IActionResult Details(string id, string activityCode)
|
public async Task<IActionResult> Details(string id, string activityCode)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (id == null || activityCode == null)
|
if (id == null || activityCode == null)
|
||||||
@ -48,29 +53,23 @@ namespace Yavsc.Controllers
|
|||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
UserActivity userActivity = _context.UserActivities.Include(m=>m.Does)
|
UserActivity userActivity = dbContext.UserActivities.Include(m=>m.Does)
|
||||||
.Include(m=>m.User).Single(m => m.DoesCode == activityCode && m.UserId == id);
|
.Include(m=>m.User).Single(m => m.DoesCode == activityCode && m.UserId == id);
|
||||||
if (userActivity == null)
|
if (userActivity == null)
|
||||||
{
|
{
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasConfigurableSettings = (userActivity.Does.SettingsClassName != null);
|
bool hasConfigurableSettings = (userActivity.Does.SettingsClassName != null);
|
||||||
if (hasConfigurableSettings) {
|
var settings = await billing.GetPerformerSettingsAsync(activityCode,id);
|
||||||
ViewBag.ProfileType = Startup.ProfileTypes.Single(t=>t.FullName==userActivity.Does.SettingsClassName);
|
ViewBag.ProfileType = Startup.ProfileTypes.Single(t=>t.FullName==userActivity.Does.SettingsClassName);
|
||||||
var dbset = (IQueryable<ISpecializationSettings>) _context.GetDbSet(userActivity.Does.SettingsClassName);
|
|
||||||
if (dbset == null) throw new InvalidWorkflowModelException($"pas de db set pour {userActivity.Does.SettingsClassName}, vous avez peut-être besoin de décorer votre propriété avec l'attribut [ActivitySettings]");
|
var gift = new UserActivityViewModel {
|
||||||
return View(new UserActivityViewModel {
|
|
||||||
Declaration = userActivity,
|
Declaration = userActivity,
|
||||||
HasSettings = dbset.Any(ua=>ua.UserId==id),
|
Settings = settings,
|
||||||
NeedsSettings = hasConfigurableSettings
|
NeedsSettings = hasConfigurableSettings
|
||||||
} );
|
};
|
||||||
}
|
logger.LogInformation(JsonConvert.SerializeObject(gift.Settings));
|
||||||
return View(new UserActivityViewModel {
|
return View (gift);
|
||||||
Declaration = userActivity,
|
|
||||||
HasSettings = false,
|
|
||||||
NeedsSettings = hasConfigurableSettings
|
|
||||||
} );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: Do/Create
|
// GET: Do/Create
|
||||||
@ -80,9 +79,9 @@ namespace Yavsc.Controllers
|
|||||||
if (userId==null)
|
if (userId==null)
|
||||||
userId = User.GetUserId();
|
userId = User.GetUserId();
|
||||||
var model = new UserActivity { UserId = userId };
|
var model = new UserActivity { UserId = userId };
|
||||||
ViewBag.DoesCode = new SelectList(_context.Activities, "Code", "Name");
|
ViewBag.DoesCode = new SelectList(dbContext.Activities, "Code", "Name");
|
||||||
//ViewData["UserId"] = userId;
|
//ViewData["UserId"] = userId;
|
||||||
ViewBag.UserId = new SelectList(_context.Performers.Include(p=>p.Performer), "PerformerId", "Performer", userId);
|
ViewBag.UserId = new SelectList(dbContext.Performers.Include(p=>p.Performer), "PerformerId", "Performer", userId);
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,12 +97,12 @@ namespace Yavsc.Controllers
|
|||||||
if (userActivity.UserId == null) userActivity.UserId = uid;
|
if (userActivity.UserId == null) userActivity.UserId = uid;
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
_context.UserActivities.Add(userActivity);
|
dbContext.UserActivities.Add(userActivity);
|
||||||
_context.SaveChanges(User.GetUserId());
|
dbContext.SaveChanges(User.GetUserId());
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
ViewBag.DoesCode = new SelectList(_context.Activities, "Code", "Name", userActivity.DoesCode);
|
ViewBag.DoesCode = new SelectList(dbContext.Activities, "Code", "Name", userActivity.DoesCode);
|
||||||
ViewBag.UserId = new SelectList(_context.Performers.Include(p=>p.Performer), "PerformerId", "User", userActivity.UserId);
|
ViewBag.UserId = new SelectList(dbContext.Performers.Include(p=>p.Performer), "PerformerId", "User", userActivity.UserId);
|
||||||
return View(userActivity);
|
return View(userActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +115,7 @@ namespace Yavsc.Controllers
|
|||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
UserActivity userActivity = _context.UserActivities.Include(
|
UserActivity userActivity = dbContext.UserActivities.Include(
|
||||||
u=>u.Does
|
u=>u.Does
|
||||||
).Include(
|
).Include(
|
||||||
u=>u.User
|
u=>u.User
|
||||||
@ -125,8 +124,8 @@ namespace Yavsc.Controllers
|
|||||||
{
|
{
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
ViewData["DoesCode"] = new SelectList(_context.Activities, "Code", "Does", userActivity.DoesCode);
|
ViewData["DoesCode"] = new SelectList(dbContext.Activities, "Code", "Does", userActivity.DoesCode);
|
||||||
ViewData["UserId"] = new SelectList(_context.Performers, "PerformerId", "User", userActivity.UserId);
|
ViewData["UserId"] = new SelectList(dbContext.Performers, "PerformerId", "User", userActivity.UserId);
|
||||||
return View(userActivity);
|
return View(userActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,12 +139,12 @@ namespace Yavsc.Controllers
|
|||||||
ModelState.AddModelError("User","You're not admin.");
|
ModelState.AddModelError("User","You're not admin.");
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
_context.Update(userActivity);
|
dbContext.Update(userActivity);
|
||||||
_context.SaveChanges(User.GetUserId());
|
dbContext.SaveChanges(User.GetUserId());
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
ViewData["DoesCode"] = new SelectList(_context.Activities, "Code", "Does", userActivity.DoesCode);
|
ViewData["DoesCode"] = new SelectList(dbContext.Activities, "Code", "Does", userActivity.DoesCode);
|
||||||
ViewData["UserId"] = new SelectList(_context.Performers, "PerformerId", "User", userActivity.UserId);
|
ViewData["UserId"] = new SelectList(dbContext.Performers, "PerformerId", "User", userActivity.UserId);
|
||||||
return View(userActivity);
|
return View(userActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +157,7 @@ namespace Yavsc.Controllers
|
|||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
UserActivity userActivity = _context.UserActivities.Single(m => m.UserId == id && m.DoesCode == activityCode);
|
UserActivity userActivity = dbContext.UserActivities.Single(m => m.UserId == id && m.DoesCode == activityCode);
|
||||||
|
|
||||||
if (userActivity == null)
|
if (userActivity == null)
|
||||||
{
|
{
|
||||||
@ -182,8 +181,8 @@ namespace Yavsc.Controllers
|
|||||||
ModelState.AddModelError("User","You're not admin.");
|
ModelState.AddModelError("User","You're not admin.");
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
_context.UserActivities.Remove(userActivity);
|
dbContext.UserActivities.Remove(userActivity);
|
||||||
_context.SaveChanges(User.GetUserId());
|
dbContext.SaveChanges(User.GetUserId());
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
using Yavsc.Controllers.Generic;
|
using Yavsc.Controllers.Generic;
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
using Yavsc.Models.Workflow.Profiles;
|
using Yavsc.Models.Workflow.Profiles;
|
||||||
|
using Yavsc.Services;
|
||||||
|
|
||||||
namespace Yavsc.Controllers
|
namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
public class FormationSettingsController : SettingsController<FormationSettings>
|
public class FormationSettingsController : SettingsController<FormationSettings>
|
||||||
{
|
{
|
||||||
|
|
||||||
public FormationSettingsController(ApplicationDbContext context) : base(context)
|
public FormationSettingsController(ApplicationDbContext context, IBillingService billing) : base(context, billing)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ namespace Yavsc.Controllers
|
|||||||
|
|
||||||
var model = new FrontOfficeIndexViewModel
|
var model = new FrontOfficeIndexViewModel
|
||||||
{
|
{
|
||||||
EstimateToProduceCount = _context.Commands.Where(c => c.PerformerId == uid && c.EventDate > now
|
EstimateToProduceCount = _context.RdvQueries.Where(c => c.PerformerId == uid && c.EventDate > now
|
||||||
&& c.ValidationDate == null && !_context.Estimates.Any(e => (e.CommandId == c.Id && e.ProviderValidationDate != null))).Count(),
|
&& c.ValidationDate == null && !_context.Estimates.Any(e => (e.CommandId == c.Id && e.ProviderValidationDate != null))).Count(),
|
||||||
EstimateToSignAsProCount = _context.Commands.Where(c => (c.PerformerId == uid && c.EventDate > now
|
EstimateToSignAsProCount = _context.RdvQueries.Where(c => (c.PerformerId == uid && c.EventDate > now
|
||||||
&& c.ValidationDate == null && _context.Estimates.Any(e => (e.CommandId == c.Id && e.ProviderValidationDate != null)))).Count(),
|
&& c.ValidationDate == null && _context.Estimates.Any(e => (e.CommandId == c.Id && e.ProviderValidationDate != null)))).Count(),
|
||||||
EstimateToSignAsCliCount = _context.Estimates.Where(e => e.ClientId == uid && e.ClientValidationDate == null).Count(),
|
EstimateToSignAsCliCount = _context.Estimates.Where(e => e.ClientId == uid && e.ClientValidationDate == null).Count(),
|
||||||
BillToSignAsProCount = 0,
|
BillToSignAsProCount = 0,
|
||||||
|
@ -6,25 +6,31 @@ using Microsoft.Data.Entity;
|
|||||||
|
|
||||||
namespace Yavsc.Controllers.Generic
|
namespace Yavsc.Controllers.Generic
|
||||||
{
|
{
|
||||||
using Exceptions;
|
|
||||||
using Models;
|
using Models;
|
||||||
|
using Yavsc.Services;
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public abstract class SettingsController<TSettings> : Controller where TSettings : class, ISpecializationSettings, new()
|
public abstract class SettingsController<TSettings> : Controller where TSettings : class, ISpecializationSettings, new()
|
||||||
{
|
{
|
||||||
protected ApplicationDbContext _context;
|
protected ApplicationDbContext _context;
|
||||||
private object dbSet;
|
IBillingService billing;
|
||||||
|
DbSet<TSettings> dbSet=null;
|
||||||
|
|
||||||
|
protected string activityCode=null;
|
||||||
|
|
||||||
protected DbSet<TSettings> Settings { get {
|
protected DbSet<TSettings> Settings { get {
|
||||||
return (DbSet<TSettings>) dbSet;
|
if (dbSet == null) Task.Run( async () => {
|
||||||
|
dbSet = (DbSet<TSettings>) await billing.GetPerformersSettingsAsync(activityCode);
|
||||||
|
});
|
||||||
|
return dbSet;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
public SettingsController(ApplicationDbContext context)
|
public SettingsController(ApplicationDbContext context, IBillingService billing)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
dbSet=_context.GetDbSet<TSettings>();
|
this.billing = billing;
|
||||||
if (dbSet==null) throw new InvalidWorkflowModelException(this.GetType().Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IActionResult> Index()
|
public async Task<IActionResult> Index()
|
||||||
{
|
{
|
||||||
var existing = await this.Settings.SingleOrDefaultAsync(p=>p.UserId == User.GetUserId());
|
var existing = await this.Settings.SingleOrDefaultAsync(p=>p.UserId == User.GetUserId());
|
||||||
|
@ -2,6 +2,7 @@ using Yavsc.Models;
|
|||||||
using Yavsc.Models.Haircut;
|
using Yavsc.Models.Haircut;
|
||||||
using Microsoft.AspNet.Authorization;
|
using Microsoft.AspNet.Authorization;
|
||||||
using Yavsc.Controllers.Generic;
|
using Yavsc.Controllers.Generic;
|
||||||
|
using Yavsc.Services;
|
||||||
|
|
||||||
namespace Yavsc.Controllers
|
namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
@ -9,7 +10,7 @@ namespace Yavsc.Controllers
|
|||||||
public class BrusherProfileController : SettingsController<BrusherProfile>
|
public class BrusherProfileController : SettingsController<BrusherProfile>
|
||||||
{
|
{
|
||||||
|
|
||||||
public BrusherProfileController(ApplicationDbContext context) : base(context)
|
public BrusherProfileController(ApplicationDbContext context, IBillingService billing) : base(context, billing)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
|
||||||
using Microsoft.Data.Entity;
|
using Microsoft.Data.Entity;
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
using Yavsc.Models.Relationship;
|
using Yavsc.Models.Relationship;
|
||||||
|
@ -184,13 +184,13 @@ namespace Yavsc.Helpers
|
|||||||
dir, xsmallname), ImageFormat.Png);
|
dir, xsmallname), ImageFormat.Png);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Func<string,long,string>
|
public static Func<string,string,long,string>
|
||||||
SignFileNameFormat = new Func<string,long,string> ((signType,estimateId) => $"estimate-{signType}sign-{estimateId}.png");
|
SignFileNameFormat = new Func<string,string,long,string> ((signType,billingCode,estimateId) => $"sign-{billingCode}-{signType}-{estimateId}.png");
|
||||||
|
|
||||||
public static FileRecievedInfo ReceiveProSignature(this ClaimsPrincipal user, long estimateId, IFormFile formFile, string signtype)
|
public static FileRecievedInfo ReceiveProSignature(this ClaimsPrincipal user, string billingCode, long estimateId, IFormFile formFile, string signtype)
|
||||||
{
|
{
|
||||||
var item = new FileRecievedInfo();
|
var item = new FileRecievedInfo();
|
||||||
item.FileName = SignFileNameFormat("pro",estimateId);
|
item.FileName = SignFileNameFormat("pro",billingCode,estimateId);
|
||||||
var destFileName = Path.Combine(Startup.SiteSetup.UserFiles.Bills, item.FileName);
|
var destFileName = Path.Combine(Startup.SiteSetup.UserFiles.Bills, item.FileName);
|
||||||
|
|
||||||
var fi = new FileInfo(destFileName);
|
var fi = new FileInfo(destFileName);
|
||||||
|
@ -170,5 +170,8 @@ namespace Yavsc.Helpers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsSuccess(PaymentInfo info) {
|
||||||
|
return info.DbContent.State == PayPal.PayPalAPIInterfaceService.Model.PaymentStatusCodeType.COMPLETED.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ namespace Yavsc.Helpers
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TeXString operator+ (TeXString a, TeXString b) {
|
||||||
|
return new TeXString(a.ToString()+b.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public class Replacement
|
public class Replacement
|
||||||
|
@ -6,15 +6,10 @@ default: pushInPre
|
|||||||
watch:
|
watch:
|
||||||
ASPNET_ENV=Development dnx-watch web --configuration=Debug
|
ASPNET_ENV=Development dnx-watch web --configuration=Debug
|
||||||
|
|
||||||
cleanRelease:
|
clean:
|
||||||
rm -rf bin/Release
|
rm -rf bin/Release
|
||||||
|
|
||||||
cleanoutput:
|
|
||||||
rm -rf bin/output
|
rm -rf bin/output
|
||||||
|
|
||||||
clean: cleanoutput cleanRelease
|
|
||||||
gulp clean
|
|
||||||
|
|
||||||
bin/Release:
|
bin/Release:
|
||||||
dnu build --configuration=Release
|
dnu build --configuration=Release
|
||||||
|
|
||||||
@ -31,9 +26,13 @@ pushInPre: bin/output/wwwroot/version
|
|||||||
ssh root@localhost sync
|
ssh root@localhost sync
|
||||||
ssh root@localhost systemctl start kestrel-pre
|
ssh root@localhost systemctl start kestrel-pre
|
||||||
|
|
||||||
push: bin/output/wwwroot/version
|
pushInProd: bin/output/wwwroot/version
|
||||||
ssh root@localhost systemctl stop kestrel
|
ssh root@localhost systemctl stop kestrel
|
||||||
ssh root@localhost rm -rf $(PRODDESTDIR)/approot
|
ssh root@localhost rm -rf $(PRODDESTDIR)/approot
|
||||||
(cd bin/output && rsync -ravu ./ root@localhost:$(PRODDESTDIR) >/dev/null)
|
(cd bin/output && rsync -ravu ./ root@localhost:$(PRODDESTDIR) >/dev/null)
|
||||||
ssh root@localhost sync
|
ssh root@localhost sync
|
||||||
ssh root@localhost systemctl start kestrel
|
ssh root@localhost systemctl start kestrel
|
||||||
|
|
||||||
|
status:
|
||||||
|
git status -s --porcelain
|
||||||
|
|
||||||
|
@ -60,21 +60,7 @@ namespace Yavsc.Models
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public DbSet<TSettings> GetDbSet<TSettings>() where TSettings : class, ISpecializationSettings
|
|
||||||
|
|
||||||
{
|
|
||||||
return (DbSet<TSettings>) GetDbSet(typeof(TSettings).FullName);
|
|
||||||
}
|
|
||||||
public IQueryable<ISpecializationSettings> GetDbSet(string settingsClassName)
|
|
||||||
{
|
|
||||||
var dbSetPropInfo = Startup.GetUserSettingPropertyInfo(settingsClassName);
|
|
||||||
if (dbSetPropInfo == null) return null;
|
|
||||||
// var settingType = dbSetPropInfo.PropertyType;
|
|
||||||
// var dbSetType = typeof(DbSet<>).MakeGenericType(new Type[] { settingType } );
|
|
||||||
// avec une info method Remove et Update, ça le ferait ...
|
|
||||||
|
|
||||||
return (IQueryable<ISpecializationSettings>) dbSetPropInfo.GetValue(this);
|
|
||||||
}
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
optionsBuilder.UseNpgsql(Startup.ConnectionString);
|
optionsBuilder.UseNpgsql(Startup.ConnectionString);
|
||||||
@ -107,23 +93,18 @@ namespace Yavsc.Models
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public DbSet<CircleMember> CircleMembers { get; set; }
|
public DbSet<CircleMember> CircleMembers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Commands, from an user, to a performer
|
|
||||||
/// (A performer is an user who's actived a main activity
|
|
||||||
/// on his profile).
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public DbSet<RdvQuery> Commands { get; set; }
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Special commands, talking about
|
/// Special commands, talking about
|
||||||
/// a given place and date.
|
/// a given place and date.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
|
||||||
public DbSet<RdvQuery> RdvQueries { get; set; }
|
public DbSet<RdvQuery> RdvQueries { get; set; }
|
||||||
|
|
||||||
public DbSet<HairCutQuery> HairCutQueries { get; set; }
|
public DbSet<HairCutQuery> HairCutQueries { get; set; }
|
||||||
public DbSet<HairPrestation> HairPrestation { get; set; }
|
public DbSet<HairPrestation> HairPrestation { get; set; }
|
||||||
|
|
||||||
public DbSet<HairMultiCutQuery> HairMultiCutQueries { get; set; }
|
public DbSet<HairMultiCutQuery> HairMultiCutQueries { get; set; }
|
||||||
public DbSet<PerformerProfile> Performers { get; set; }
|
public DbSet<PerformerProfile> Performers { get; set; }
|
||||||
|
|
||||||
public DbSet<Estimate> Estimates { get; set; }
|
public DbSet<Estimate> Estimates { get; set; }
|
||||||
public DbSet<AccountBalance> BankStatus { get; set; }
|
public DbSet<AccountBalance> BankStatus { get; set; }
|
||||||
public DbSet<BalanceImpact> BankBook { get; set; }
|
public DbSet<BalanceImpact> BankBook { get; set; }
|
||||||
|
@ -82,5 +82,6 @@ namespace Yavsc.Models.Billing
|
|||||||
|
|
||||||
[ForeignKey("PaymentId"), Display(Name = "Acquittement de la facture")]
|
[ForeignKey("PaymentId"), Display(Name = "Acquittement de la facture")]
|
||||||
public virtual PayPalPayment Regularisation { get; set; }
|
public virtual PayPalPayment Regularisation { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Yavsc.Models.Billing
|
|
||||||
{
|
|
||||||
public partial class satisfaction
|
|
||||||
{
|
|
||||||
[Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
|
||||||
public long _id { get; set; }
|
|
||||||
public string comnt { get; set; }
|
|
||||||
public int? rate { get; set; }
|
|
||||||
|
|
||||||
[ForeignKey("Skill.Id")]
|
|
||||||
public long? userskillid { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
namespace Yavsc.Models.Billing
|
|
||||||
{
|
|
||||||
public partial class writtings
|
|
||||||
{
|
|
||||||
public long _id { get; set; }
|
|
||||||
public int? count { get; set; }
|
|
||||||
public string description { get; set; }
|
|
||||||
public long estimid { get; set; }
|
|
||||||
public string productid { get; set; }
|
|
||||||
public decimal? ucost { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
namespace Yavsc.Models.Billing
|
|
||||||
{
|
|
||||||
public partial class wrtags
|
|
||||||
{
|
|
||||||
public long wrid { get; set; }
|
|
||||||
public long tagid { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,7 @@ namespace Yavsc.Models.Relationship
|
|||||||
[ForeignKey("OwnerId"),JsonIgnore,NotMapped]
|
[ForeignKey("OwnerId"),JsonIgnore,NotMapped]
|
||||||
public virtual ApplicationUser Owner { get; set; }
|
public virtual ApplicationUser Owner { get; set; }
|
||||||
|
|
||||||
[InverseProperty("Circle")]
|
[InverseProperty("Circle"),JsonIgnore]
|
||||||
public virtual List<CircleMember> Members { get; set; }
|
public virtual List<CircleMember> Members { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ namespace Yavsc.Models.Workflow
|
|||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using Models.Relationship;
|
using Models.Relationship;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Yavsc.Workflow;
|
using Yavsc.Workflow;
|
||||||
|
|
||||||
public class PerformerProfile : IPerformerProfile {
|
public class PerformerProfile : IPerformerProfile {
|
||||||
@ -16,7 +17,7 @@ namespace Yavsc.Models.Workflow
|
|||||||
public virtual ApplicationUser Performer { get; set; }
|
public virtual ApplicationUser Performer { get; set; }
|
||||||
|
|
||||||
[InverseProperty("User")]
|
[InverseProperty("User")]
|
||||||
[Display(Name="Activity")]
|
[Display(Name="Activity"), JsonIgnore]
|
||||||
public virtual List<UserActivity> Activity { get; set; }
|
public virtual List<UserActivity> Activity { get; set; }
|
||||||
|
|
||||||
[Required,StringLength(14),Display(Name="SIREN"),
|
[Required,StringLength(14),Display(Name="SIREN"),
|
||||||
|
62
Yavsc/Services/BillingService.cs
Normal file
62
Yavsc/Services/BillingService.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Data.Entity;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Yavsc.Billing;
|
||||||
|
using Yavsc.Models;
|
||||||
|
|
||||||
|
namespace Yavsc.Services
|
||||||
|
{
|
||||||
|
public class BillingService : IBillingService
|
||||||
|
{
|
||||||
|
public ApplicationDbContext DbContext { get; private set; }
|
||||||
|
private ILogger logger;
|
||||||
|
|
||||||
|
public BillingService(ILoggerFactory loggerFactory, ApplicationDbContext dbContext)
|
||||||
|
{
|
||||||
|
logger = loggerFactory.CreateLogger<BillingService>();
|
||||||
|
DbContext = dbContext;
|
||||||
|
}
|
||||||
|
public async Task<IQueryable<ISpecializationSettings>> GetPerformersSettings(string activityCode)
|
||||||
|
{
|
||||||
|
logger.LogDebug("searching for "+activityCode);
|
||||||
|
var activity = await DbContext.Activities.SingleAsync(a=>a.Code == activityCode);
|
||||||
|
logger.LogDebug(JsonConvert.SerializeObject(activity));
|
||||||
|
|
||||||
|
|
||||||
|
if (activity.SettingsClassName==null) return null;
|
||||||
|
var dbSetPropInfo = Startup.UserSettings.SingleOrDefault(s => s.PropertyType.GenericTypeArguments[0].FullName == activity.SettingsClassName);
|
||||||
|
|
||||||
|
|
||||||
|
if (dbSetPropInfo == null) return null;
|
||||||
|
// var settingType = dbSetPropInfo.PropertyType;
|
||||||
|
// var dbSetType = typeof(DbSet<>).MakeGenericType(new Type[] { settingType } );
|
||||||
|
// avec une info method Remove et Update, ça le ferait ...
|
||||||
|
|
||||||
|
return (IQueryable<ISpecializationSettings>) dbSetPropInfo.GetValue(DbContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IBillable> GetBillAsync(string billingCode, long queryId)
|
||||||
|
{
|
||||||
|
var dbFunc = Startup.Billing[billingCode];
|
||||||
|
IBillable query = null;
|
||||||
|
await Task.Run(()=> dbFunc(DbContext, queryId));
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ISpecializationSettings> GetPerformerSettingsAsync(string activityCode, string userId)
|
||||||
|
{
|
||||||
|
return await (await GetPerformersSettings(activityCode)).SingleOrDefaultAsync(s=> s.UserId == userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IQueryable<ISpecializationSettings>> GetPerformersSettingsAsync(string activityCode)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
26
Yavsc/Services/IBillingService.cs
Normal file
26
Yavsc/Services/IBillingService.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace Yavsc.Services
|
||||||
|
{
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Billing;
|
||||||
|
public interface IBillingService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Renvoye la facture associée à une clé de facturation:
|
||||||
|
/// le couple suivant :
|
||||||
|
///
|
||||||
|
/// * un code de facturation
|
||||||
|
/// (identifiant associé à un type de facturation d'un flux de travail)
|
||||||
|
/// * un entier long identifiant la demande du client
|
||||||
|
/// (à une demande, on associe au maximum une seule facture)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="billingCode">Identifiant du type de facturation</param>
|
||||||
|
/// <param name="queryId">Identifiant de la demande du client</param>
|
||||||
|
/// <returns>La facture</returns>
|
||||||
|
Task<IBillable> GetBillAsync(string billingCode, long queryId);
|
||||||
|
Task<IQueryable<ISpecializationSettings>> GetPerformersSettingsAsync(string activityCode);
|
||||||
|
|
||||||
|
Task<ISpecializationSettings> GetPerformerSettingsAsync(string activityCode, string userId);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -7,65 +7,83 @@ using Microsoft.Extensions.Logging;
|
|||||||
|
|
||||||
namespace Yavsc
|
namespace Yavsc
|
||||||
{
|
{
|
||||||
using Exceptions;
|
using Microsoft.Data.Entity;
|
||||||
using Models;
|
using Models;
|
||||||
|
using Yavsc.Billing;
|
||||||
public partial class Startup
|
public partial class Startup
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Lists Available user profile classes,
|
/// Lists Available user profile classes,
|
||||||
/// populated at startup, using reflexion.
|
/// populated at startup, using reflexion.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static List<Type> ProfileTypes = new List<Type>() ;
|
public static List<Type> ProfileTypes = new List<Type>();
|
||||||
public static List<PropertyInfo> UserSettings = new List<PropertyInfo> ();
|
public static List<PropertyInfo> UserSettings = new List<PropertyInfo>();
|
||||||
|
public static Dictionary<string,Func<ApplicationDbContext,long,IBillable>> Billing =
|
||||||
|
new Dictionary<string,Func<ApplicationDbContext,long,IBillable>> ();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Lists available command forms.
|
/// Lists available command forms.
|
||||||
/// This is hard coded.
|
/// This is hard coded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string [] Forms = new string [] { "Profiles" , "HairCut" };
|
public static readonly string[] Forms = new string[] { "Profiles", "HairCut" };
|
||||||
|
|
||||||
public static PropertyInfo GetUserSettingPropertyInfo(string settingsClassName)
|
|
||||||
{
|
|
||||||
return UserSettings.SingleOrDefault(s => s.PropertyType.GenericTypeArguments[0].FullName == settingsClassName ) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConfigureWorkflow(IApplicationBuilder app, SiteSettings settings, ILogger logger)
|
private void ConfigureWorkflow(IApplicationBuilder app, SiteSettings settings, ILogger logger)
|
||||||
{
|
{
|
||||||
System.AppDomain.CurrentDomain.ResourceResolve += OnYavscResourceResolve;
|
System.AppDomain.CurrentDomain.ResourceResolve += OnYavscResourceResolve;
|
||||||
|
|
||||||
foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies()) {
|
foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies())
|
||||||
foreach (var c in a.GetTypes()) {
|
{
|
||||||
|
foreach (var c in a.GetTypes())
|
||||||
|
{
|
||||||
if (c.IsClass && !c.IsAbstract &&
|
if (c.IsClass && !c.IsAbstract &&
|
||||||
c.GetInterface("ISpecializationSettings")!=null) {
|
c.GetInterface("ISpecializationSettings") != null)
|
||||||
|
{
|
||||||
ProfileTypes.Add(c);
|
ProfileTypes.Add(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (var propinfo in typeof(ApplicationDbContext).GetProperties()) {
|
|
||||||
foreach (var attr in propinfo.CustomAttributes) {
|
foreach (var propinfo in typeof(ApplicationDbContext).GetProperties())
|
||||||
if (attr.AttributeType == typeof(Yavsc.Attributes.ActivitySettingsAttribute)) {
|
{
|
||||||
// bingo
|
foreach (var attr in propinfo.CustomAttributes)
|
||||||
if (typeof(IQueryable<ISpecializationSettings>).IsAssignableFrom(propinfo.PropertyType))
|
{
|
||||||
{
|
// something like a DbSet?
|
||||||
logger.LogVerbose($"Paramêtres utilisateur déclaré: {propinfo.Name}");
|
if (attr.AttributeType == typeof(Yavsc.Attributes.ActivitySettingsAttribute))
|
||||||
UserSettings.Add(propinfo);
|
{
|
||||||
} else
|
// TODO swith () case {}
|
||||||
// Design time error
|
if (typeof(IQueryable<ISpecializationSettings>).IsAssignableFrom(propinfo.PropertyType))
|
||||||
{
|
{// double-bingo
|
||||||
var msg =
|
logger.LogVerbose($"Pro: {propinfo.Name}");
|
||||||
$@"La propriété {propinfo.Name} du contexte de la
|
UserSettings.Add(propinfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// Design time error
|
||||||
|
{
|
||||||
|
var msg =
|
||||||
|
$@"La propriété {propinfo.Name} du contexte de la
|
||||||
base de donnée porte l'attribut [ActivitySetting],
|
base de donnée porte l'attribut [ActivitySetting],
|
||||||
mais n'implemente pas l'interface IQueryable<ISpecializationSettings>
|
mais n'implemente pas l'interface IQueryable<ISpecializationSettings>
|
||||||
({propinfo.MemberType.GetType()})";
|
({propinfo.MemberType.GetType()})";
|
||||||
logger.LogCritical(msg);
|
logger.LogCritical(msg);
|
||||||
|
|
||||||
throw new InvalidWorkflowModelException(msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Billing.Add("Brush", new Func<ApplicationDbContext,long,IBillable>
|
||||||
|
( ( db, id) =>
|
||||||
|
{
|
||||||
|
var query = db.HairCutQueries.Include(q=>q.Prestation).Single(q=>q.Id == id) ;
|
||||||
|
query.SelectedProfile = db.BrusherProfile.Single(b=>b.UserId == query.PerformerId);
|
||||||
|
return query;
|
||||||
|
})) ;
|
||||||
|
|
||||||
|
Billing.Add("MBrush",new Func<ApplicationDbContext,long,IBillable>
|
||||||
|
( (db, id) => db.HairMultiCutQueries.Single(q=>q.Id == id)));
|
||||||
|
Billing.Add("Rdv", new Func<ApplicationDbContext,long,IBillable>
|
||||||
|
( (db, id) => db.RdvQueries.Single(q=>q.Id == id)));
|
||||||
}
|
}
|
||||||
public static System.Reflection.Assembly OnYavscResourceResolve (object sender, ResolveEventArgs ev)
|
public static System.Reflection.Assembly OnYavscResourceResolve(object sender, ResolveEventArgs ev)
|
||||||
{
|
{
|
||||||
return AppDomain.CurrentDomain.GetAssemblies()[0];
|
return AppDomain.CurrentDomain.GetAssemblies()[0];
|
||||||
}
|
}
|
||||||
|
@ -189,10 +189,9 @@ namespace Yavsc
|
|||||||
services.AddSingleton<IAuthorizationHandler, HasTemporaryPassHandler>();
|
services.AddSingleton<IAuthorizationHandler, HasTemporaryPassHandler>();
|
||||||
services.AddSingleton<IAuthorizationHandler, BlogEditHandler>();
|
services.AddSingleton<IAuthorizationHandler, BlogEditHandler>();
|
||||||
services.AddSingleton<IAuthorizationHandler, BlogViewHandler>();
|
services.AddSingleton<IAuthorizationHandler, BlogViewHandler>();
|
||||||
services.AddSingleton<IAuthorizationHandler, CommandEditHandler>();
|
services.AddSingleton<IAuthorizationHandler, BillEditHandler>();
|
||||||
services.AddSingleton<IAuthorizationHandler, CommandViewHandler>();
|
services.AddSingleton<IAuthorizationHandler, BillViewHandler>();
|
||||||
services.AddSingleton<IAuthorizationHandler, PostUserFileHandler>();
|
services.AddSingleton<IAuthorizationHandler, PostUserFileHandler>();
|
||||||
services.AddSingleton<IAuthorizationHandler, EstimateViewHandler>();
|
|
||||||
services.AddSingleton<IAuthorizationHandler, ViewFileHandler>();
|
services.AddSingleton<IAuthorizationHandler, ViewFileHandler>();
|
||||||
|
|
||||||
services.AddMvc(config =>
|
services.AddMvc(config =>
|
||||||
@ -227,6 +226,9 @@ namespace Yavsc
|
|||||||
// Add application services.
|
// Add application services.
|
||||||
services.AddTransient<IEmailSender, AuthMessageSender>();
|
services.AddTransient<IEmailSender, AuthMessageSender>();
|
||||||
services.AddTransient<IGoogleCloudMessageSender, AuthMessageSender>();
|
services.AddTransient<IGoogleCloudMessageSender, AuthMessageSender>();
|
||||||
|
services.AddTransient<IBillingService, BillingService>((servs) =>
|
||||||
|
new BillingService(servs.GetRequiredService<ILoggerFactory>(), servs.GetService<ApplicationDbContext>())
|
||||||
|
);
|
||||||
// TODO for SMS: services.AddTransient<ISmsSender, AuthMessageSender>();
|
// TODO for SMS: services.AddTransient<ISmsSender, AuthMessageSender>();
|
||||||
|
|
||||||
services.AddLocalization(options =>
|
services.AddLocalization(options =>
|
||||||
@ -333,9 +335,7 @@ namespace Yavsc
|
|||||||
// before fixing the security protocol, let beleive our lib it's done with it.
|
// before fixing the security protocol, let beleive our lib it's done with it.
|
||||||
var cxmgr = ConnectionManager.Instance;
|
var cxmgr = ConnectionManager.Instance;
|
||||||
// then, fix it.
|
// then, fix it.
|
||||||
ServicePointManager.SecurityProtocol = (SecurityProtocolType) 0xC00;
|
ServicePointManager.SecurityProtocol = (SecurityProtocolType) 0xC00; // Tls12, required by PayPal
|
||||||
|
|
||||||
logger.LogInformation($"ServicePointManager.SecurityProtocol: {ServicePointManager.SecurityProtocol}");
|
|
||||||
|
|
||||||
app.UseIISPlatformHandler(options =>
|
app.UseIISPlatformHandler(options =>
|
||||||
{
|
{
|
||||||
|
108
Yavsc/ViewComponents/BillViewComponent.cs
Normal file
108
Yavsc/ViewComponents/BillViewComponent.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
using Microsoft.Data.Entity;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Yavsc.Billing;
|
||||||
|
using Yavsc.Helpers;
|
||||||
|
using Yavsc.Models;
|
||||||
|
using Yavsc.Services;
|
||||||
|
using Yavsc.ViewModels.Gen;
|
||||||
|
|
||||||
|
namespace Yavsc.ViewComponents
|
||||||
|
{
|
||||||
|
public enum OutputFormat {
|
||||||
|
Html,
|
||||||
|
LaTeX,
|
||||||
|
Pdf
|
||||||
|
}
|
||||||
|
public class BillViewComponent : ViewComponent
|
||||||
|
{
|
||||||
|
ApplicationDbContext dbContext;
|
||||||
|
IBillingService billingService;
|
||||||
|
IStringLocalizer<Yavsc.Resources.YavscLocalisation> localizer;
|
||||||
|
|
||||||
|
public BillViewComponent(ApplicationDbContext dbContext,
|
||||||
|
IStringLocalizer<Yavsc.Resources.YavscLocalisation> localizer)
|
||||||
|
{
|
||||||
|
this.dbContext = dbContext;
|
||||||
|
this.localizer = localizer;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
public async Task<IViewComponentResult> InvokeAsync(string code, long id)
|
||||||
|
{
|
||||||
|
return await InvokeAsync(code, id, OutputFormat.Html);
|
||||||
|
}
|
||||||
|
public async Task<IViewComponentResult> InvokeAsync(string code, long id, OutputFormat outputFormat)
|
||||||
|
{
|
||||||
|
return await InvokeAsync(code,id,outputFormat,false,false);
|
||||||
|
}
|
||||||
|
public async Task<IViewComponentResult> InvokeAsync(string code, long id, OutputFormat outputFormat, bool asBill, bool acquitted)
|
||||||
|
{
|
||||||
|
var billable = await Task.Run( () => billingService.GetBillAsync(code,id));
|
||||||
|
|
||||||
|
if (billable == null)
|
||||||
|
throw new Exception("No data");
|
||||||
|
return await InvokeAsync(code, billable, outputFormat,asBill,acquitted);
|
||||||
|
|
||||||
|
} */
|
||||||
|
|
||||||
|
public async Task<IViewComponentResult> InvokeAsync(string code, IBillable billable, OutputFormat format, bool asBill, bool acquitted)
|
||||||
|
{
|
||||||
|
var di = new DirectoryInfo(Startup.SiteSetup.UserFiles.Bills);
|
||||||
|
var dia = new DirectoryInfo(Startup.SiteSetup.UserFiles.Avatars);
|
||||||
|
ViewBag.BillsDir = di.FullName;
|
||||||
|
ViewBag.AvatarsDir = dia.FullName;
|
||||||
|
ViewBag.AsBill = asBill; // vrai pour une facture, sinon, c'est un devis
|
||||||
|
ViewBag.Acquitted = acquitted;
|
||||||
|
ViewBag.BillingCode = code;
|
||||||
|
switch (format) {
|
||||||
|
case OutputFormat.LaTeX :
|
||||||
|
var client = await dbContext.Users
|
||||||
|
.Include(u=>u.PostalAddress)
|
||||||
|
.SingleAsync(u=>u.Id == billable.ClientId);
|
||||||
|
ViewBag.Client = client;
|
||||||
|
var performer = await dbContext.Users
|
||||||
|
.Include(u=>u.BankInfo)
|
||||||
|
.Include(u=>u.PostalAddress)
|
||||||
|
.SingleAsync(u=>u.Id == billable.PerformerId);
|
||||||
|
ViewBag.Performer = performer;
|
||||||
|
|
||||||
|
ViewBag.ClientAddress = client.PostalAddress?.Address.SplitAddressToTeX();
|
||||||
|
|
||||||
|
var profile = await dbContext.Performers
|
||||||
|
.Include(p=>p.OrganizationAddress)
|
||||||
|
.SingleAsync(p=>p.PerformerId == billable.PerformerId);
|
||||||
|
ViewBag.PerformerProfile = profile;
|
||||||
|
ViewBag.ActivityLabel = localizer[billable.ActivityCode];
|
||||||
|
ViewBag.PerformerOrganizationAddress = profile.OrganizationAddress.Address.SplitAddressToTeX() ;
|
||||||
|
ViewBag.PerformerAddress = performer.PostalAddress?.Address.SplitAddressToTeX() ;
|
||||||
|
return this.View("Bill_tex", billable);
|
||||||
|
case OutputFormat.Pdf :
|
||||||
|
string tex = null;
|
||||||
|
var oldWriter = ViewComponentContext.ViewContext.Writer;
|
||||||
|
using (var writer = new StringWriter())
|
||||||
|
{
|
||||||
|
this.ViewComponentContext.ViewContext.Writer = writer;
|
||||||
|
|
||||||
|
var resultTex = View("Bill_tex", billable);
|
||||||
|
await resultTex.ExecuteAsync(this.ViewComponentContext);
|
||||||
|
tex = writer.ToString();
|
||||||
|
|
||||||
|
}
|
||||||
|
ViewComponentContext.ViewContext.Writer = oldWriter;
|
||||||
|
|
||||||
|
return this.View("Bill_pdf",
|
||||||
|
new PdfGenerationViewModel{
|
||||||
|
Temp = Startup.Temp,
|
||||||
|
TeXSource = tex,
|
||||||
|
DestDir = Startup.UserBillsDirName,
|
||||||
|
BaseFileName = $"bill-{code}-{billable.Id}"
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
return View("Default",billable);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,79 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNet.Mvc;
|
|
||||||
using Microsoft.Data.Entity;
|
|
||||||
using Yavsc.Models;
|
|
||||||
using Yavsc.Models.Billing;
|
|
||||||
using Yavsc.ViewModels.Gen;
|
|
||||||
|
|
||||||
namespace Yavsc.ViewComponents
|
|
||||||
{
|
|
||||||
public class EstimateViewComponent : ViewComponent
|
|
||||||
{
|
|
||||||
ApplicationDbContext dbContext;
|
|
||||||
public EstimateViewComponent(ApplicationDbContext dbContext)
|
|
||||||
{
|
|
||||||
this.dbContext = dbContext;
|
|
||||||
}
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(long id)
|
|
||||||
{
|
|
||||||
return await InvokeAsync(id,"Html");
|
|
||||||
}
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(long id, string outputFormat ="Html")
|
|
||||||
{
|
|
||||||
return await InvokeAsync(id,outputFormat,false,false);
|
|
||||||
}
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(long id, string outputFormat ="Html", bool asBill = false, bool acquitted = false)
|
|
||||||
{
|
|
||||||
return await Task.Run( ()=> {
|
|
||||||
Estimate estimate =
|
|
||||||
dbContext.Estimates.Include(x => x.Query)
|
|
||||||
.Include(x => x.Query.Client)
|
|
||||||
.Include(x => x.Query.PerformerProfile)
|
|
||||||
.Include(x => x.Query.PerformerProfile.OrganizationAddress)
|
|
||||||
.Include(x => x.Query.PerformerProfile.Performer)
|
|
||||||
.Include(e => e.Bill).FirstOrDefault(x => x.Id == id);
|
|
||||||
if (estimate == null)
|
|
||||||
throw new Exception("No data");
|
|
||||||
var di = new DirectoryInfo(Startup.SiteSetup.UserFiles.Bills);
|
|
||||||
var dia = new DirectoryInfo(Startup.SiteSetup.UserFiles.Avatars);
|
|
||||||
ViewBag.BillsDir = di.FullName;
|
|
||||||
ViewBag.AvatarsDir = dia.FullName;
|
|
||||||
ViewBag.AsBill = asBill;
|
|
||||||
ViewBag.Acquitted = acquitted;
|
|
||||||
if (outputFormat == "LaTeX") {
|
|
||||||
return this.View("Estimate_tex", estimate);
|
|
||||||
}
|
|
||||||
else if (outputFormat == "Pdf")
|
|
||||||
{
|
|
||||||
// Sorry for this code
|
|
||||||
string tex = null;
|
|
||||||
var oldWriter = ViewComponentContext.ViewContext.Writer;
|
|
||||||
using (var writer = new StringWriter())
|
|
||||||
{
|
|
||||||
this.ViewComponentContext.ViewContext.Writer = writer;
|
|
||||||
|
|
||||||
var resultTex = View("Estimate_tex", estimate);
|
|
||||||
resultTex.Execute(this.ViewComponentContext);
|
|
||||||
tex = writer.ToString();
|
|
||||||
|
|
||||||
}
|
|
||||||
ViewComponentContext.ViewContext.Writer = oldWriter;
|
|
||||||
|
|
||||||
return this.View("Estimate_pdf",
|
|
||||||
new PdfGenerationViewModel{
|
|
||||||
Temp = Startup.Temp,
|
|
||||||
TeXSource = tex,
|
|
||||||
DestDir = Startup.UserBillsDirName,
|
|
||||||
BaseFileName = $"estimate-{id}"
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
return View("Default",estimate);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
using System.Security.Claims;
|
|
||||||
using Microsoft.AspNet.Authorization;
|
|
||||||
using Yavsc.Models.Billing;
|
|
||||||
|
|
||||||
namespace Yavsc.ViewModels.Auth.Handlers
|
|
||||||
{
|
|
||||||
public class EstimateViewHandler : AuthorizationHandler<ViewRequirement, Estimate>
|
|
||||||
{
|
|
||||||
protected override void Handle(AuthorizationContext context, ViewRequirement requirement, Estimate resource)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (context.User.IsInRole(Constants.AdminGroupName)
|
|
||||||
|| context.User.IsInRole(Constants.FrontOfficeGroupName))
|
|
||||||
context.Succeed(requirement);
|
|
||||||
else if (context.User.Identity.IsAuthenticated) {
|
|
||||||
var uid = context.User.GetUserId();
|
|
||||||
if (resource.OwnerId == uid || resource.ClientId == uid)
|
|
||||||
context.Succeed(requirement);
|
|
||||||
// TODO && ( resource.Circles == null || context.User belongs to resource.Circles )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,6 +6,6 @@ namespace Yavsc.ViewModels.Workflow
|
|||||||
{
|
{
|
||||||
public UserActivity Declaration { get; set; }
|
public UserActivity Declaration { get; set; }
|
||||||
public bool NeedsSettings { get; set; }
|
public bool NeedsSettings { get; set; }
|
||||||
public bool HasSettings { get; set; }
|
public ISpecializationSettings Settings { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,10 +15,10 @@
|
|||||||
@if (Model.NeedsSettings) {
|
@if (Model.NeedsSettings) {
|
||||||
<a asp-controller="@ViewBag.ProfileType.Name" asp-action="Index" class="btn btn-default">
|
<a asp-controller="@ViewBag.ProfileType.Name" asp-action="Index" class="btn btn-default">
|
||||||
@SR[Model.Declaration.Does.SettingsClassName]
|
@SR[Model.Declaration.Does.SettingsClassName]
|
||||||
@if (!Model.HasSettings) {
|
@if (Model.Settings==null) {
|
||||||
<span class="badge">Non renseigné: Cliquez vite<br/> ici pour positionner les<br/> paramêtres de cette activité</span>
|
<span class="badge">Non renseigné: Cliquez vite<br/> ici pour positionner les<br/>
|
||||||
|
paramêtres de cette activité</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@model HairCutQuery
|
@model Yavsc.Models.Haircut.HairCutQuery
|
||||||
@{ ViewData["Title"] = $"{ViewBag.Activity.Name}: Votre commande"; }
|
@{ ViewData["Title"] = $"{ViewBag.Activity.Name}: Votre commande"; }
|
||||||
@await Html.PartialAsync("BrusherProfileScript",ViewData["PerfPrefs"])
|
@await Html.PartialAsync("BrusherProfileScript",ViewData["PerfPrefs"])
|
||||||
|
|
||||||
@ -186,8 +186,8 @@
|
|||||||
var pos = loc.geometry.location;
|
var pos = loc.geometry.location;
|
||||||
var lat = new Number(pos.lat);
|
var lat = new Number(pos.lat);
|
||||||
var lng = new Number(pos.lng);
|
var lng = new Number(pos.lng);
|
||||||
$('#' + config.latId).val(lat.toLocaleString('en'));
|
$('#' + config.latId).val(lat);
|
||||||
$('#' + config.longId).val(lng.toLocaleString('en'));
|
$('#' + config.longId).val(lng);
|
||||||
gmap.setCenter(pos);
|
gmap.setCenter(pos);
|
||||||
if (marker) {
|
if (marker) {
|
||||||
marker.setMap(null);
|
marker.setMap(null);
|
||||||
@ -335,7 +335,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="EventDate" class="col-md-2 control-label">
|
<label for="EventDate" class="col-md-2 control-label">
|
||||||
@SR["Event date"]
|
@SR["Event date"]
|
||||||
|
22
Yavsc/Views/Shared/Components/Bill/Bill_pdf.cshtml
Normal file
22
Yavsc/Views/Shared/Components/Bill/Bill_pdf.cshtml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@using System.Reflection
|
||||||
|
@using System.IO
|
||||||
|
@using Microsoft.Extensions.WebEncoders
|
||||||
|
@using System.Diagnostics
|
||||||
|
@using System.Text
|
||||||
|
@using Yavsc.Formatters
|
||||||
|
@using Yavsc.Helpers
|
||||||
|
@model Yavsc.ViewModels.Gen.PdfGenerationViewModel
|
||||||
|
|
||||||
|
@{
|
||||||
|
Model.GenerateEstimatePdf();
|
||||||
|
}
|
||||||
|
@if (Model.Generated) {
|
||||||
|
<div>
|
||||||
|
@(Model.BaseFileName).pdf was generated
|
||||||
|
</div>
|
||||||
|
} else {
|
||||||
|
<div class="error">
|
||||||
|
@Model.GenerationErrorMessage
|
||||||
|
<p>Something went wrong ...</p>
|
||||||
|
</div>
|
||||||
|
}
|
216
Yavsc/Views/Shared/Components/Bill/Bill_tex.cshtml
Normal file
216
Yavsc/Views/Shared/Components/Bill/Bill_tex.cshtml
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
@using Yavsc.Helpers
|
||||||
|
@using System.IO
|
||||||
|
@using System.Globalization
|
||||||
|
@model IBillable
|
||||||
|
@{
|
||||||
|
Layout = null;
|
||||||
|
var pro = ViewBag.PerformerProfile;
|
||||||
|
var from = ViewBag.Performer;
|
||||||
|
var to = ViewBag.Client;
|
||||||
|
var PostalAddress = ViewBag.ClientAddress;
|
||||||
|
var proaddr = ViewBag.PerformerOrganizationAddress;
|
||||||
|
var proaddrm = proaddr;
|
||||||
|
var isestimate = !ViewBag.AsBill;
|
||||||
|
var prosign = new FileInfo($"{ViewBag.BillsDir}/sign-{ViewBag.BillingCode}-{Model.Id}.png");
|
||||||
|
var clisign = new FileInfo($"{ViewBag.BillsDir}/sign-{ViewBag.BillingCode}-{Model.Id}.png");
|
||||||
|
var activity = ViewBag.ActivityLabel;
|
||||||
|
var bill = Model.GetBillItems();
|
||||||
|
string validationDate = null ;
|
||||||
|
if (Model.ValidationDate.HasValue) {
|
||||||
|
validationDate = Model.ValidationDate.Value.ToString("dddd dd MMMM yyyy", CultureInfo.CreateSpecificCulture("fr-FR"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\documentclass[french,11pt]{article}
|
||||||
|
\usepackage{eurosym}
|
||||||
|
\usepackage{babel}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[a4paper]{geometry}
|
||||||
|
\usepackage{units}
|
||||||
|
\usepackage{bera}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\usepackage{fancyhdr}
|
||||||
|
\usepackage{fp}
|
||||||
|
|
||||||
|
\def\TVA{20} % Taux de la TVA
|
||||||
|
|
||||||
|
\def\TotalHT{0}
|
||||||
|
\def\TotalTVA{0}
|
||||||
|
|
||||||
|
\newcommand{\AjouterService}[3]{% Arguments : Désignation, quantité, prix
|
||||||
|
\FPround{\prix}{#3}{2}
|
||||||
|
\FPeval{\montant}{#2 * #3}
|
||||||
|
\FPround{\montant}{\montant}{2}
|
||||||
|
\FPadd{\TotalHT}{\TotalHT}{\montant}
|
||||||
|
\eaddto\ListeProduits{#1 & \prix & #2 & \montant \cr}
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\AfficheResultat}{%
|
||||||
|
\ListeProduits
|
||||||
|
\FPeval{\TotalTVA}{\TotalHT * \TVA / 100}
|
||||||
|
\FPadd{\TotalTTC}{\TotalHT}{\TotalTVA}
|
||||||
|
\FPround{\TotalHT}{\TotalHT}{2}
|
||||||
|
\FPround{\TotalTVA}{\TotalTVA}{2}
|
||||||
|
\FPround{\TotalTTC}{\TotalTTC}{2}
|
||||||
|
\global\let\TotalHT\TotalHT
|
||||||
|
\global\let\TotalTVA\TotalTVA
|
||||||
|
\global\let\TotalTTC\TotalTTC
|
||||||
|
\cr
|
||||||
|
\hline
|
||||||
|
\textbf{Total} & & & \TotalHT
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand*\eaddto[2]{% version développée de \addto
|
||||||
|
\edef\tmp{#2}%
|
||||||
|
\expandafter\addto
|
||||||
|
\expandafter#1%
|
||||||
|
\expandafter{\tmp}%
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\ListeProduits}{}
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%% A MODIFIER DANS LA FACTURE %%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
\def\FactureNum {@Model.Id.ToString()} % Numéro de facture
|
||||||
|
\def\FactureAcquittee {@ViewBag.Acquitted?"oui":"non"} % Facture acquittée : oui/non
|
||||||
|
\def\FactureLieu {@proaddrm} % Lieu de l'édition de la facture
|
||||||
|
\def\FactureObjet {@(new HtmlString(isestimate?"Devis":"Facture")) en @TeXHelpers.ToTeX(activity)} % Objet du document
|
||||||
|
% Description de la facture
|
||||||
|
\def\FactureDescr {
|
||||||
|
@TeXHelpers.ToTeX(Model.GetDescription())
|
||||||
|
}
|
||||||
|
|
||||||
|
% Infos Client
|
||||||
|
\def\ClientNom{@TeXHelpers.ToTeX(to.UserName)} % Nom du client
|
||||||
|
|
||||||
|
\def\ClientAdresse{
|
||||||
|
% Adresse du client
|
||||||
|
@PostalAddress
|
||||||
|
@if (PostalAddress!=null) {<text>@PostalAddress</text>}
|
||||||
|
@if (!string.IsNullOrWhiteSpace(to.PhoneNumber)) {<text>@TeXHelpers.ToTeX(to.PhoneNumber)<text>\\</text>
|
||||||
|
</text>}
|
||||||
|
E-mail: @TeXHelpers.ToTeX(to.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
% Liste des produits facturés : Désignation, prix
|
||||||
|
@foreach (var line in bill) {
|
||||||
|
<text>\AjouterService{@TeXHelpers.ToTeX(line.Description)}{@line.Count}{@line.UnitaryCost.ToString("F2",CultureInfo.InvariantCulture)}
|
||||||
|
</text>}
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\geometry{verbose,tmargin=4em,bmargin=8em,lmargin=6em,rmargin=6em}
|
||||||
|
\setlength{\parindent}{0pt}
|
||||||
|
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
|
||||||
|
|
||||||
|
\thispagestyle{fancy}
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\setlength{\parindent}{0pt}
|
||||||
|
|
||||||
|
\renewcommand{\headrulewidth}{0pt}
|
||||||
|
\cfoot{ @TeXHelpers.ToTeX(from.UserName) @if (proaddrm!=null) { <text> - @proaddrm </text> } \newline
|
||||||
|
\small{ E-mail: @TeXHelpers.ToTeX(from.Email) @if (!string.IsNullOrWhiteSpace(from.PhoneNumber)) { <text> - Téléphone fixe: @TeXHelpers.ToTeX(from.PhoneNumber) </text> }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
% Logo de la société
|
||||||
|
@if (from.Avatar != null) {
|
||||||
|
<text>\includegraphics[height=60pt]{@(ViewBag.AvatarsDir)/@(from.UserName).png}
|
||||||
|
</text>
|
||||||
|
} else {
|
||||||
|
<text>%\includegraphics{logo.png}
|
||||||
|
</text>
|
||||||
|
}
|
||||||
|
% Nom et adresse de la société
|
||||||
|
@TeXHelpers.ToTeX(from.UserName) \\
|
||||||
|
@proaddr
|
||||||
|
|
||||||
|
@(isestimate?"Devis":"Facture") n°\FactureNum
|
||||||
|
|
||||||
|
|
||||||
|
{\addtolength{\leftskip}{10.5cm} %in ERT
|
||||||
|
\textbf{\ClientNom} \\
|
||||||
|
\ClientAdresse \\
|
||||||
|
|
||||||
|
} %in ERT
|
||||||
|
|
||||||
|
|
||||||
|
\hspace*{10.5cm}
|
||||||
|
\FactureLieu, le \today
|
||||||
|
|
||||||
|
~\\~\\
|
||||||
|
|
||||||
|
\textbf{Objet : \FactureObjet \\}
|
||||||
|
|
||||||
|
\textnormal{\FactureDescr}
|
||||||
|
|
||||||
|
~\\
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tabular}{lrrr}
|
||||||
|
\textbf{Désignation ~~~~~~} & \textbf{Prix unitaire} & \textbf{Quantité} & \textbf{Montant (\euro)} \\
|
||||||
|
\hline
|
||||||
|
\AfficheResultat{}
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\begin{flushright}
|
||||||
|
\textit{Auto entreprise en franchise de TVA}\\
|
||||||
|
|
||||||
|
\end{flushright}
|
||||||
|
~\\
|
||||||
|
@if (ViewBag.AsBill) {
|
||||||
|
|
||||||
|
} else if (ViewBag.Acquitted) {
|
||||||
|
<text>
|
||||||
|
\ifthenelse{\equal{\FactureAcquittee}{oui}}{
|
||||||
|
Facture acquittée.
|
||||||
|
}
|
||||||
|
</text>
|
||||||
|
} else {
|
||||||
|
var bi = from.BankInfo;
|
||||||
|
if (bi!=null) {
|
||||||
|
<text>À régler par chèque ou par virement bancaire :
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tabular}{|c c c c|}
|
||||||
|
@if (!string.IsNullOrWhiteSpace(bi.BankCode) && !string.IsNullOrWhiteSpace(bi.WicketCode)
|
||||||
|
&& !string.IsNullOrWhiteSpace(bi.AccountNumber) ) {
|
||||||
|
<text>\hline \textbf{Code banque} & \textbf{Code guichet} & \textbf{N° de Compte} & \textbf{Clé RIB} \\
|
||||||
|
@bi.BankCode & @bi.WicketCode & @bi.AccountNumber & @bi.BankedKey \\
|
||||||
|
</text>
|
||||||
|
}
|
||||||
|
@if (!string.IsNullOrWhiteSpace(@bi.IBAN) && !string.IsNullOrWhiteSpace(@bi.BIC)) {
|
||||||
|
<text>
|
||||||
|
\hline \textbf{IBAN N°} & \multicolumn{3}{|l|}{ @bi.IBAN } \\
|
||||||
|
\hline \textbf{Code BIC} & \multicolumn{3}{|l|}{ @bi.BIC }
|
||||||
|
</text>
|
||||||
|
} \\
|
||||||
|
\hline
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}</text>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@if (validationDate!=null) {
|
||||||
|
<text>
|
||||||
|
\begin{flushright}
|
||||||
|
@(new TeXString(isestimate?"Devis demandé le ":"Facture suite à la demande du ")+
|
||||||
|
TeXHelpers.ToTeX(validationDate))
|
||||||
|
\end{flushright}
|
||||||
|
@if (prosign.Exists) {
|
||||||
|
<text>
|
||||||
|
\begin{center}
|
||||||
|
\hspace{263pt}
|
||||||
|
\includegraphics[height=60pt]{@(ViewBag.BillsDir)/estimate-prosign-@(Model.Id).png}
|
||||||
|
\end{center}
|
||||||
|
</text>
|
||||||
|
}
|
||||||
|
</text>
|
||||||
|
}
|
||||||
|
\end{document}
|
13
Yavsc/Views/Shared/Components/Bill/Default.cshtml
Normal file
13
Yavsc/Views/Shared/Components/Bill/Default.cshtml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
@model IBillable
|
||||||
|
<div class="bill">
|
||||||
|
|
||||||
|
<a href="~/api/pdfbill/bill-@(Model.ActivityCode)-@(Model.Id).tex" >Export au format LaTeX</a>
|
||||||
|
|
||||||
|
|
||||||
|
<form action="~/api/pdfbill/gen/@(Model.ActivityCode)-@Model.Id" method="POST">
|
||||||
|
<input type="submit" value="Générer le Pdf"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<a href="~/api/pdfbill/get/@(Model.Id)" >Télécharger le document généré</a>
|
||||||
|
</div>
|
@ -2,12 +2,12 @@
|
|||||||
@model Estimate
|
@model Estimate
|
||||||
<div class="estimate">
|
<div class="estimate">
|
||||||
|
|
||||||
<a href="~/api/pdfestimate/estimate-@(Model.Id).tex" >Export au format LaTeX</a>
|
<a href="~/api/pdfbill/estimate-@(Model.Id).tex" >Export au format LaTeX</a>
|
||||||
|
|
||||||
|
|
||||||
<form action="~/api/pdfestimate/gen/@Model.Id" method="POST">
|
<form action="~/api/pdfbill/gen/@Model.Id" method="POST">
|
||||||
<input type="submit" value="Générer le Pdf"/>
|
<input type="submit" value="Générer le Pdf"/>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<a href="~/api/pdfestimate/get/@(Model.Id)" >Télécharger le document généré</a>
|
<a href="~/api/pdfbill/get/@(Model.Id)" >Télécharger le document généré</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -191,8 +191,7 @@
|
|||||||
@if (!(Model.ProviderValidationDate==null)) {
|
@if (!(Model.ProviderValidationDate==null)) {
|
||||||
<text>
|
<text>
|
||||||
\begin{flushright}
|
\begin{flushright}
|
||||||
@(new HtmlString(isestimate?"Devis validé":"Facture validée")) le @TeXHelpers.ToTeX(Model.ProviderValidationDate.ToString("dddd dd MMMM yyyy",
|
@(new HtmlString(isestimate?"Devis validé":"Facture validée")) le @TeXHelpers.ToTeX(Model.ProviderValidationDate.ToString("dddd dd MMMM yyyy"))
|
||||||
CultureInfo.CreateSpecificCulture("fr-FR")))
|
|
||||||
\end{flushright}
|
\end{flushright}
|
||||||
@if (prosign.Exists) {
|
@if (prosign.Exists) {
|
||||||
<text>
|
<text>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user