Skip to content

Instantly share code, notes, and snippets.

@EvgenyKungurov
Created November 5, 2019 12:57
Show Gist options
  • Save EvgenyKungurov/445d35faa9c893aab9f04d25eb6c285c to your computer and use it in GitHub Desktop.
Save EvgenyKungurov/445d35faa9c893aab9f04d25eb6c285c to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
# класс для начислений по запрплате при создании счета
class Salary::Income::Invoice::Update < Salary::Income::Base
def call
destroy_old_incomes
find_project_contracts
create_incomes
end
private
attr_reader :project_contracts
def destroy_old_incomes
incomes = repository.where(owner: model)
if employees
incomes.where(employee: employees).destroy_all
else
incomes.destroy_all
end
end
def find_project_contracts
@project_contracts = ProjectContract.by_invoice(model)
end
def create_incomes
project_contracts.each do |project_contract|
periods_by_month.each do |period_of_month|
project_contract.team.employees.each do |employee|
next if employees && (employees.exclude? employee)
employee.salary_contracts_by_period(period_of_month).each do |salary_contract|
create_income(
employee: employee,
salary_contract: salary_contract,
period_of_month: period_of_month,
project_contract_period: project_contract.period,
)
end
end
end
end
end
def create_income(employee:, salary_contract:, period_of_month:, project_contract_period:)
return unless salary_contract.invoice_quota.positive?
paid_period = paid_period([salary_contract.period, period_of_month, project_contract_period])
return if paid_period.empty?
date_for = paid_period.last.end_of_month
return if income_exists?(employee: employee, owner: model, date: date_for.beginning_of_month..date_for.end_of_month)
income = repository.create!(
employee: employee,
owner: model,
salary_contract: salary_contract,
amount: amount(salary_contract: salary_contract, period: paid_period),
date: date_for,
)
create_negative_income(income) unless model.invoice_active?
create_negative_refund_income(employee: employee, date: date_for, salary_contract: salary_contract, paid_period: paid_period)
end
def create_negative_income(income)
income.dup.tap { |dup_income| dup_income.tap { |i| i.amount = -income.amount }.save! }
end
def amount(salary_contract:, period:)
Salary::Income::Invoice::TotalPrice.call(model, date_from: period.first, date_to: period.last) * salary_contract.invoice_quota / 100
end
def periods_by_month
model.period
.group_by(&:month)
.map { |group| group.last.first.beginning_of_month..group.last.last }
end
def paid_period(periods)
periods.map do |period|
if period.end
period.to_a
else
(period.begin..Date.today).to_a
end
end.inject { |intersect_period, period| intersect_period & period }
end
def income_exists?(employee:, date:, owner:)
Salary::Income.exists?(employee: employee, owner: owner, date: date)
end
def create_negative_refund_income(employee:, date:, salary_contract:, paid_period:)
refunds = Refund.where(invoice: model)
refunds.each do |refund|
repository.create!(
date: date,
owner: model,
employee: employee,
amount: refund_amount(refund: refund, salary_contract: salary_contract, period: paid_period),
salary_contract: salary_contract,
)
end
end
def refund_amount(refund:, salary_contract:, period:)
-(Salary::Income::Invoice::RefundTotalPrice.call(refund, date_from: period.first, date_to: period.last) * salary_contract.invoice_quota / 100)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment