我有一个写的会计系统,该系统遵循标准的双项会计惯例。
双重记账功能有一个称为“试用余额”的功能,您可以在其中验证整个系统的正确性,因为在运行该系统时,它始终等于0.00
我已经编写了测试,并且在系统“停止”时总是运行我的试用余额,但是在播种大量记录的过程中,由于数据库写负载繁重,我发现我的试用余额在10次尝试中大约有1次是错误的。 >
静止(无插入)时,它始终正确0.00
。
当我插入交易时,它们总是在交易中,就像这样:
2000.times do |i|
ActiveRecord::Base.transaction do
puts "#{i} ==================================================================="
entry = JournalEntry.create!(description: 'Purchase mower on credit', user: user)
entry.line_items.create!(amount: Money.from_amount(1551.75).cents, account: property.accounts.find_by(name: 'Equipment'), side: :debit)
entry.line_items.create!(amount: Money.from_amount(1551.75).cents, account: property.accounts.find_by(name: 'Accounts Payable'), side: :credit)
end
end
它在负载下破裂的事实使我觉得我对Rails事务的工作方式不是很重要……
可能是什么原因造成的?
首先,我的试用余额功能(GeneralLedger.new(property).trial_balance
)执行以下pseodo-SQL(在交易中否):
SELECT sum(...) WHERE account = 'asset'
SELECT sum(...) WHERE account = 'liability'
SELECT sum(...) WHERE account = 'equity'
SELECT sum(...) WHERE account = 'income'
SELECT sum(...) WHERE account = 'expense'
然后我根据会计公式将它们加在一起,得出0.00:
def trial_balance
balance_category(:asset) - (balance_category(:liability) + balance_category(:equity) + balance_category(:income) - balance_category(:expense))
end
balance_category
函数可触发每个SELECT总共5次,每个类别一次。
因为它返回0,这意味着它以某种方式选择何时插入其中途...........我不知道这是怎么回事?
我可以理解,日记帐分录/行项目的创建是否不在事务中,而它是在选择插入行的中途进行选择,但是它应该仅在事务结束后从整个组中进行选择?
答案 0 :(得分:1)
如果要避免重复的语句,请将其折叠为以下形式:
SELECT account, SUM(...) AS amount FROM ...
WHERE account IN ('asset', 'liability', ...)
GROUP BY account
您可以这样获取这些信息:
where(account: ACCOUNT_TYPES).group(:account).pluck('account, SUM(...)')
ACCOUNT_TYPES
是您需要提取的帐户类型的数组。
您始终可以采用这种pluck
格式,并使用.to_h
转换为快速查找哈希,然后像这样使用它:
balance_category = ...where(...)...pluck(...).to_h
balance_category[:asset]
如果需要默认值,请考虑:
balance_category = Hash.new(0).merge(...where(...)...pluck(...).to_h)
默认值可以是整数(0
)或浮点数(0.0
)或任何其他值。