<commit_before>﻿using System;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using JoinRpg.Data.Write.Interfaces;
using JoinRpg.DataModel;
using JoinRpg.Domain;
using JoinRpg.Services.Interfaces;

namespace JoinRpg.Services.Impl
{
  [UsedImplicitly]
  public class FinanceOperationsImpl : ClaimImplBase, IFinanceService
  {
    public FinanceOperationsImpl(IUnitOfWork unitOfWork, IEmailService emailService) : base(unitOfWork, emailService)
    {
    }

    public async Task FeeAcceptedOperation(int projectId, int claimId, int currentUserId, string contents, DateTime operationDate,
  int feeChange, int money, int paymentTypeId)
    {
      var claim = await LoadClaim(projectId, claimId, currentUserId);
      var now = DateTime.UtcNow;
      var paymentType = claim.Project.PaymentTypes.Single(pt => pt.PaymentTypeId == paymentTypeId);

      paymentType.EnsureActive();

      if (operationDate > now.AddDays(1))//TODO[UTC]: if everyone properly uses UTC, we don't have to do +1
      {
        throw new CannotPerformOperationInFuture();
      }

      if (feeChange != 0 || money < 0)
      {
        claim.RequestMasterAccess(currentUserId, acl => acl.CanManageMoney);
      }
      var state = FinanceOperationState.Approved;

      if (paymentType.UserId != currentUserId)
      {
        if (claim.PlayerUserId == currentUserId)
        {
          //Player mark that he pay fee. Put this to moderation
          state = FinanceOperationState.Proposed;
        }
        else
        {
          claim.RequestMasterAccess(currentUserId, acl => acl.CanManageMoney);
        }
      }

      var comment = claim.AddCommentImpl(currentUserId, null, contents, now, isVisibleToPlayer:true, extraAction: null);

      var financeOperation = new FinanceOperation()
      {
        Created = now,
        FeeChange = feeChange,
        MoneyAmount = money,
        Changed = now,
        Claim = claim,
        Comment = comment,
        PaymentType = paymentType,
        State = state,
        ProjectId = projectId,
        OperationDate = operationDate
      };

      comment.Finance = financeOperation;

      claim.FinanceOperations.Add(financeOperation);

      if (claim.Project.ProjectFeeSettings.Any()    //If project has fee 
          && claim.CurrentFee == null  //and fee not already fixed for claim
          && claim.ClaimBalance() > claim.ClaimTotalFee(operationDate) //and current fee is payed in full
          )
      {
        claim.CurrentFee = claim.Project.CurrentFee(operationDate); //fix fee for claim
      }

      await UnitOfWork.SaveChangesAsync();
      var email = CreateClaimEmail<FinanceOperationEmail>(claim, currentUserId, contents, s => s.MoneyOperation,
        isVisibleToPlayer: true, commentExtraAction: null);

      await EmailService.Email(await email);

    }
  }
}<commit_msg>Add target master to recepients of finance operation<commit_after>﻿using System;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using JoinRpg.Data.Write.Interfaces;
using JoinRpg.DataModel;
using JoinRpg.Domain;
using JoinRpg.Services.Interfaces;

namespace JoinRpg.Services.Impl
{
  [UsedImplicitly]
  public class FinanceOperationsImpl : ClaimImplBase, IFinanceService
  {
    public FinanceOperationsImpl(IUnitOfWork unitOfWork, IEmailService emailService) : base(unitOfWork, emailService)
    {
    }

    public async Task FeeAcceptedOperation(int projectId, int claimId, int currentUserId, string contents, DateTime operationDate,
  int feeChange, int money, int paymentTypeId)
    {
      var claim = await LoadClaim(projectId, claimId, currentUserId);
      var now = DateTime.UtcNow;
      var paymentType = claim.Project.PaymentTypes.Single(pt => pt.PaymentTypeId == paymentTypeId);

      paymentType.EnsureActive();

      if (operationDate > now.AddDays(1))//TODO[UTC]: if everyone properly uses UTC, we don't have to do +1
      {
        throw new CannotPerformOperationInFuture();
      }

      if (feeChange != 0 || money < 0)
      {
        claim.RequestMasterAccess(currentUserId, acl => acl.CanManageMoney);
      }
      var state = FinanceOperationState.Approved;

      if (paymentType.UserId != currentUserId)
      {
        if (claim.PlayerUserId == currentUserId)
        {
          //Player mark that he pay fee. Put this to moderation
          state = FinanceOperationState.Proposed;
        }
        else
        {
          claim.RequestMasterAccess(currentUserId, acl => acl.CanManageMoney);
        }
      }

      var comment = claim.AddCommentImpl(currentUserId, null, contents, now, isVisibleToPlayer:true, extraAction: null);

      var financeOperation = new FinanceOperation()
      {
        Created = now,
        FeeChange = feeChange,
        MoneyAmount = money,
        Changed = now,
        Claim = claim,
        Comment = comment,
        PaymentType = paymentType,
        State = state,
        ProjectId = projectId,
        OperationDate = operationDate
      };

      comment.Finance = financeOperation;

      claim.FinanceOperations.Add(financeOperation);

      if (claim.Project.ProjectFeeSettings.Any()    //If project has fee 
          && claim.CurrentFee == null  //and fee not already fixed for claim
          && claim.ClaimBalance() > claim.ClaimTotalFee(operationDate) //and current fee is payed in full
          )
      {
        claim.CurrentFee = claim.Project.CurrentFee(operationDate); //fix fee for claim
      }

      await UnitOfWork.SaveChangesAsync();
      var email = CreateClaimEmail<FinanceOperationEmail>(claim, currentUserId, contents, s => s.MoneyOperation,
        isVisibleToPlayer: true, commentExtraAction: null, extraRecepients: new [] { paymentType.User});

      await EmailService.Email(await email);

    }
  }
}
{'fraction_non_alphanumeric': 0.08873190902825638, 'fraction_numerical': 0.0013783597518952446, 'mean_word_length': 2.875166889185581, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6605026', 'n_tokens_mistral': 1625, 'n_tokens_neox': 1611, 'n_words': 404}