Skip to content

Commit

Permalink
Update - Ajout de vérification supplémentaire pour créer des payouts
Browse files Browse the repository at this point in the history
  • Loading branch information
noelmugnier committed Nov 9, 2020
1 parent 1b9ce53 commit 78ca3d2
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using Sheaft.Core;
using Newtonsoft.Json;

namespace Sheaft.Application.Commands
{
public class EnsureBankAccountValidatedCommand : Command<bool>
{
[JsonConstructor]
public EnsureBankAccountValidatedCommand(RequestUser requestUser) : base(requestUser)
{
}

public Guid ProducerId { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ public UpdateProducerCommand(RequestUser requestUser) : base(requestUser)
public bool OpenForNewBusiness { get; set; }
public FullAddressInput Address { get; set; }
public IEnumerable<Guid> Tags { get; set; }
public bool? NotSubjectToVat { get; set; }
}
}
20 changes: 19 additions & 1 deletion Sheaft.Application.Handlers/Commands/PaymentCommandsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
namespace Sheaft.Application.Handlers
{
public class PaymentCommandsHandler : ResultsHandler,
IRequestHandler<CreateBankAccountCommand, Result<Guid>>
IRequestHandler<CreateBankAccountCommand, Result<Guid>>,
IRequestHandler<EnsureBankAccountValidatedCommand, Result<bool>>
{
private readonly IPspService _pspService;

Expand Down Expand Up @@ -56,5 +57,22 @@ public async Task<Result<Guid>> Handle(CreateBankAccountCommand request, Cancell
}
});
}

public async Task<Result<bool>> Handle(EnsureBankAccountValidatedCommand request, CancellationToken token)
{
return await ExecuteAsync(request, async () =>
{
var user = await _context.GetByIdAsync<User>(request.ProducerId, token);
var bankAccount = await _context.GetSingleAsync<BankAccount>(c => c.User.Id == request.ProducerId && c.IsActive, token);
if (!string.IsNullOrWhiteSpace(bankAccount.Identifier))
return Ok(true);
var result = await _pspService.CreateBankIbanAsync(bankAccount, token);
if (!result.Success)
return Failed<bool>(result.Exception);
return Ok(true);
});
}
}
}
27 changes: 18 additions & 9 deletions Sheaft.Application.Handlers/Commands/PayoutCommandsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.EntityFrameworkCore;
using Sheaft.Options;
using Microsoft.Extensions.Options;
using Sheaft.Exceptions;

namespace Sheaft.Application.Handlers
{
Expand Down Expand Up @@ -163,22 +164,30 @@ public async Task<Result<Guid>> Handle(CreatePayoutCommand request, Cancellation
var wallet = await _context.GetSingleAsync<Wallet>(c => c.User.Id == request.ProducerId, token);
var bankAccount = await _context.GetSingleAsync<BankAccount>(c => c.User.Id == request.ProducerId && c.IsActive, token);
var bankConfigurationResult = await _mediatr.Process(new EnsureBankAccountValidatedCommand(request.RequestUser) { ProducerId = request.ProducerId }, token);
if (!bankConfigurationResult.Success)
return Failed<Guid>(bankConfigurationResult.Exception);
var transfers = await _context.GetAsync<Transfer>(
t => request.TransferIds.Contains(t.Id)
&& t.PurchaseOrder.Status == PurchaseOrderStatus.Delivered
&& (t.Payout == null || t.Payout.Status == TransactionStatus.Failed),
token);
var hasAlreadyPaidComission = await _context.AnyAsync<Payout>(
p => p.Fees > 0
&& p.DebitedWallet.User.Id == request.ProducerId
&& p.Status != TransactionStatus.Failed,
token);
var amount = transfers.Sum(t => t.Credited);
var fees = hasAlreadyPaidComission || amount < _pspOptions.ProducerFees ? 0m : _pspOptions.ProducerFees;
if (!hasAlreadyPaidComission && fees == 0m)
return Failed<Guid>(new InvalidCastException());
var fees = 0m;
if (producerLegals.DeclarationRequired)
{
var hasAlreadyPaidComission = await _context.AnyAsync<Payout>(
p => p.Fees > 0
&& p.DebitedWallet.User.Id == request.ProducerId
&& p.Status != TransactionStatus.Failed,
token);
fees = hasAlreadyPaidComission || amount < _pspOptions.ProducerFees ? 0m : _pspOptions.ProducerFees;
if (!hasAlreadyPaidComission && fees == 0m)
return Failed<Guid>(new Exception("Invalid fees for payout without paid commission."));
}
using (var transaction = await _context.BeginTransactionAsync(token))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public async Task<Result<Guid>> Handle(RegisterProducerCommand request, Cancella
Email = request.Legals.Email,
Siret = request.Legals.Siret,
Kind = request.Legals.Kind,
VatIdentifier = request.Legals.VatIdentifier,
VatIdentifier = request.NotSubjectToVat ? null : request.Legals.VatIdentifier,
UserId = producer.Id,
Owner = request.Legals.Owner
}, token);
Expand Down Expand Up @@ -139,6 +139,11 @@ public async Task<Result<bool>> Handle(UpdateProducerCommand request, Cancellati
producer.SetDescription(request.Description);
producer.SetOpenForNewBusiness(request.OpenForNewBusiness);
if (request.NotSubjectToVat.HasValue)
{
producer.SetNotSubjectToVat(request.NotSubjectToVat.Value);
}
var departmentCode = UserAddress.GetDepartmentCode(request.Address.Zipcode);
var department = await _context.Departments.SingleOrDefaultAsync(d => d.Code == departmentCode, token);
Expand Down
2 changes: 1 addition & 1 deletion Sheaft.Application.Models/Inputs/BusinessInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class BusinessInput
public string Picture { get; set; }
public FullAddressInput Address { get; set; }
public bool OpenForNewBusiness { get; set; }
public bool NotSubjectToVat { get; set; }
public bool? NotSubjectToVat { get; set; }
public IEnumerable<Guid> Tags { get; set; }
}
}
1 change: 1 addition & 0 deletions Sheaft.Application.Models/ViewModels/BusinessViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ public class ProducerViewModel
public bool OpenForNewBusiness { get; set; }
public AddressViewModel Address { get; set; }
public IEnumerable<Guid> Tags { get; set; }
public bool NotSubjectToVat { get; set; }
}
}
4 changes: 3 additions & 1 deletion Sheaft.GraphQL.Types/Inputs/RegisterProducerInputType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ public class RegisterProducerInputType : SheaftInputType<RegisterProducerInput>
protected override void Configure(IInputObjectTypeDescriptor<RegisterProducerInput> descriptor)
{
descriptor.Field(c => c.OpenForNewBusiness);
descriptor.Field(c => c.NotSubjectToVat);
descriptor.Field(c => c.Description);
descriptor.Field(c => c.Phone);
descriptor.Field(c => c.Picture);
descriptor.Field(c => c.SponsoringCode);

descriptor.Field(c => c.NotSubjectToVat)
.Type<NonNullType<BooleanType>>();

descriptor.Field(c => c.Address)
.Type<NonNullType<FullAddressInputType>>();

Expand Down
11 changes: 11 additions & 0 deletions Sheaft.Web.Api/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,17 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IConfigu
wallet.SetIdentifier(configuration.GetValue<string>("Psp:WalletId"));
context.Add(wallet);

var bankAccount = new BankAccount(Guid.NewGuid(), "Dons", "Sheaft", configuration.GetValue<string>("Psp:Bank:Iban"), configuration.GetValue<string>("Psp:Bank:Bic"),
new BankAddress(
configuration.GetValue<string>("Psp:Bank:Address:Line1"),
configuration.GetValue<string>("Psp:Bank:Address:Line2"),
configuration.GetValue<string>("Psp:Bank:Address:Zipcode"),
configuration.GetValue<string>("Psp:Bank:Address:City"),
configuration.GetValue<CountryIsoCode>("Psp:Bank:Address:Country")), admin);

bankAccount.SetIdentifier(configuration.GetValue<string>("Psp:Bank:Id"));
context.Add(bankAccount);

context.SaveChanges();
}

Expand Down
14 changes: 13 additions & 1 deletion Sheaft.Web.Api/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,19 @@
"FixedAmount": 0.18,
"Percent": 0.018,
"UserId": "##REPLACE##",
"WalletId": "##REPLACE##"
"WalletId": "##REPLACE##",
"Bank": {
"Id": "##REPLACE##",
"Iban": "##REPLACE##",
"Bic": "##REPLACE##",
"Address": {
"Line1": "##REPLACE##",
"Line2": "##REPLACE##",
"Zipcode": "##REPLACE##",
"City": "##REPLACE##",
"Country": "##REPLACE##"
}
}
},
"Routines": {
"CheckOrderExpiredFromMinutes": 1440,
Expand Down
14 changes: 13 additions & 1 deletion Sheaft.Web.Jobs/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,19 @@
"FixedAmount": 0.18,
"Percent": 0.018,
"UserId": "##REPLACE##",
"WalletId": "##REPLACE##"
"WalletId": "##REPLACE##",
"Bank": {
"Id": "##REPLACE##",
"Iban": "##REPLACE##",
"Bic": "##REPLACE##",
"Address": {
"Line1": "##REPLACE##",
"Line2": "##REPLACE##",
"Zipcode": "##REPLACE##",
"City": "##REPLACE##",
"Country": "##REPLACE##"
}
}
},
"Routines": {
"CheckOrderExpiredFromMinutes": 1440,
Expand Down
11 changes: 7 additions & 4 deletions Sheaft.Web.Manage/Controllers/ProducersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ public async Task<IActionResult> Edit(ProducerViewModel model, IFormFile picture
Kind = model.Kind,
Phone = model.Phone,
Tags = model.Tags,
Picture = model.Picture
Picture = model.Picture,
NotSubjectToVat = model.NotSubjectToVat
}, token);

if (!result.Success)
Expand All @@ -137,7 +138,6 @@ public async Task<IActionResult> CreateLegal(Guid userId, CancellationToken toke
var entity = await _context.Users.OfType<Business>()
.AsNoTracking()
.Where(c => c.Id == userId)
.ProjectTo<ProducerViewModel>(_configurationProvider)
.SingleOrDefaultAsync(token);

if (entity == null)
Expand All @@ -159,6 +159,8 @@ public async Task<IActionResult> CreateLegal(Guid userId, CancellationToken toke
public async Task<IActionResult> CreateLegal(BusinessLegalViewModel model, CancellationToken token)
{
var requestUser = await GetRequestUser(token);
var user = await _context.FindByIdAsync<Producer>(model.Owner.Id, token);

var result = await _mediatr.Process(new CreateBusinessLegalCommand(requestUser)
{
UserId = model.Owner.Id,
Expand All @@ -167,7 +169,7 @@ public async Task<IActionResult> CreateLegal(BusinessLegalViewModel model, Cance
Kind = model.Kind,
Owner = _mapper.Map<OwnerInput>(model.Owner),
Siret = model.Siret,
VatIdentifier = model.VatIdentifier
VatIdentifier = user != null && user.NotSubjectToVat ? null : model.VatIdentifier
}, token);

if (!result.Success)
Expand Down Expand Up @@ -203,6 +205,7 @@ public async Task<IActionResult> UpdateLegal(Guid userId, CancellationToken toke
public async Task<IActionResult> UpdateLegal(BusinessLegalViewModel model, CancellationToken token)
{
var requestUser = await GetRequestUser(token);
var user = await _context.FindByIdAsync<Producer>(model.Owner.Id, token);
var result = await _mediatr.Process(new UpdateBusinessLegalCommand(requestUser)
{
Id = model.Id,
Expand All @@ -211,7 +214,7 @@ public async Task<IActionResult> UpdateLegal(BusinessLegalViewModel model, Cance
Kind = model.Kind,
Owner = _mapper.Map<OwnerInput>(model.Owner),
Siret = model.Siret,
VatIdentifier = model.VatIdentifier
VatIdentifier = user != null && user.NotSubjectToVat ? null : model.VatIdentifier
}, token);

if (!result.Success)
Expand Down
14 changes: 13 additions & 1 deletion Sheaft.Web.Manage/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,19 @@
"FixedAmount": 0.18,
"Percent": 0.018,
"UserId": "##REPLACE##",
"WalletId": "##REPLACE##"
"WalletId": "##REPLACE##",
"Bank": {
"Id": "##REPLACE##",
"Iban": "##REPLACE##",
"Bic": "##REPLACE##",
"Address": {
"Line1": "##REPLACE##",
"Line2": "##REPLACE##",
"Zipcode": "##REPLACE##",
"City": "##REPLACE##",
"Country": "##REPLACE##"
}
}
},
"Routines": {
"CheckOrderExpiredFromMinutes": 1440,
Expand Down
14 changes: 13 additions & 1 deletion Sheaft.Web.Payment/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,19 @@
"FixedAmount": 0.18,
"Percent": 0.018,
"UserId": "##REPLACE##",
"WalletId": "##REPLACE##"
"WalletId": "##REPLACE##",
"Bank": {
"Id": "##REPLACE##",
"Iban": "##REPLACE##",
"Bic": "##REPLACE##",
"Address": {
"Line1": "##REPLACE##",
"Line2": "##REPLACE##",
"Zipcode": "##REPLACE##",
"City": "##REPLACE##",
"Country": "##REPLACE##"
}
}
},
"Routines": {
"CheckOrderExpiredFromMinutes": 1440,
Expand Down

0 comments on commit 78ca3d2

Please sign in to comment.