module C80Estate
class Pstat < ActiveRecord::Base
belongs_to :property
belongs_to :atype
belongs_to :sevent
# nil, если это запись с общими данными, а не astatus related запись
# (добавлена только для того, чтобы можно было :dependend => :destroy)
belongs_to :parent, :class_name => 'C80Estate::Pstat'
has_many :pstats, :foreign_key => 'parent_id', :dependent => :destroy
# рассчитаем коэф-ты занятости
before_create :calc_busy_coefs
# сгенерим atype related записи
after_create :generate_atype_pstats
def self.busy_coef(prop_id: nil, atype_id: nil, start_date: nil, end_date: nil)
# start_date: строка вида 2015-12-12
result = {}
# если ничего не подано - просто выберем все занятые площади и поделим на все известные площади
if prop_id.nil? && atype_id.nil? && start_date.nil? && end_date.nil?
all_areas_count = Area.all.count
free_areas_count = Area.free_areas.count
busy_areas_count = Area.busy_areas.count
ddd = '-'
if self.count > 0
ddd = Time.at(self.first.created_at).strftime('%Y/%m/%d')
end
result[:busy_coef] = sprintf "%.2f%", busy_areas_count*1.0/all_areas_count*100.0
result[:comment] = "C #{ddd} по #{Time.now.year}/#{sprintf "%02d", Time.now.month}/#{sprintf "%02d", Time.now.day}"
result[:abbr] = 'Показана занятость для всех площадей всех объектов недвижимости за весь период'
result[:title] = 'Статистика - Все объекты недвижимости'
result[:props] = [
{tag: 'all_areas_count', val: "Площадей всего: #{all_areas_count}"},
{tag: 'free_areas_count', val: "Площадей свободно: #{free_areas_count}"},
{tag: 'busy_areas_count', val: "Площадей занято: #{busy_areas_count}"}
]
Rails.logger.debug " busy_areas_count = #{ busy_areas_count }"
Rails.logger.debug " all_areas_count = #{ all_areas_count }"
Rails.logger.debug " result[:busy_coef] = #{ result[:busy_coef] }"
# если фильтруем по property
elsif prop_id.present?
# фиксируем property
property = Property.find(prop_id)
# работаем с ней, если только есть площади
if property.areas.count > 0
# обозначим диапазон фильтрации
area_created_at = Time.at(property.areas.first.created_at)
time_now = Time.now
# Rails.logger.debug("area_created_at = #{area_created_at}")
# Rails.logger.debug("time_now = #{time_now}")
# если подана нижняя граница диапазона и она позже, чем время создания самой первой площади объекта,
# выравниваем период рассчета коэф-та по этой нижней границе диапазона
if start_date.present?
start_date_tt = Time.parse(start_date)
if start_date_tt > area_created_at
used_start_date = start_date_tt
# Rails.logger.debug("start_date: используем аргумент: #{start_date_tt}")
else
used_start_date = area_created_at
# Rails.logger.debug("start_date: используем время рождения Площади: #{area_created_at}")
end
else
used_start_date = area_created_at
# Rails.logger.debug("start_date: используем время рождения Площади: #{area_created_at}")
end
used_start_date_str = used_start_date.strftime('%Y/%m/%d')
if end_date.present?
end_date_tt = Time.parse(end_date)
if end_date < time_now
used_end_date = end_date_tt
Rails.logger.debug("end_date: используем аргумент: #{end_date_tt}")
else
used_end_date = time_now
Rails.logger.debug("end_date: используем текущее время")
end
else
used_end_date = time_now
Rails.logger.debug("end_date: используем текущее время")
end
used_end_date_str = used_end_date.strftime('%Y/%m/%d')
# Rails.logger.debug("start_date = #{start_date}; end_date = #{end_date}; used_start_date = #{used_start_date}; used_end_date = #{used_end_date}")
# sevents = self.where(:area_id => area_id).where(:created_at => used_start_date..used_end_date)
pstats = self.where(:property_id => prop_id)
.where("created_at BETWEEN ? AND ?", used_start_date, used_end_date)
if atype_id.present?
pstats = pstats.where(:atype_id => atype_id)
end
# если в этот промежуток небыло событий - значит промежуток целиком попал в какое-то событие
# найдем его
# заодно поднимем вспомогательный флаг, который обработаем во view
mark_whole = false
if pstats.count == 0
pstats = [self.where(:property_id => prop_id).where("created_at < ?", used_start_date).last]
mark_whole = true
# sevents.each do |se|
# Rails.logger.debug "\t\t\t #{used_start_date - se.created_at}"
# end
end
# если сортируем по типу, то берём последнюю запись,
# иначе - берём последнюю запись с общими данными
if atype_id.nil?
free_areas_atnow = pstats.where(:atype_id => nil).last.free_areas
busy_areas_atnow = pstats.where(:atype_id => nil).last.busy_areas
else
free_areas_atnow = pstats.last.free_areas
busy_areas_atnow = pstats.last.busy_areas
end
Rails.logger.debug("\t\t atype_id = #{atype_id}")
Rails.logger.debug("\t\t free_areas_atnow = #{free_areas_atnow}")
Rails.logger.debug("\t\t busy_areas_atnow = #{busy_areas_atnow}")
# защищаемся от деления на ноль
if free_areas_atnow + busy_areas_atnow == 0
bcoef = 0.0
else
bcoef = busy_areas_atnow*1.0 / (free_areas_atnow + busy_areas_atnow) * 100.0
end
result[:busy_coef] = sprintf "%.2f%", bcoef
result[:comment] = "C #{used_start_date_str} по #{used_end_date_str}"
result[:abbr] = 'Занятость объекта за указанный период'
result[:title] = "Статистика - Объект - #{property.title}"
result[:graph] = _parse_for_js_radial_graph(free_areas_atnow,busy_areas_atnow)
result[:graph_dynamic] = _parse_for_js_dynamic_graph(pstats)
# if atype_id.present?
# result[:title] += " (#{Atype.find(atype_id).title})"
# end
dc_str = property.areas.first.created_at.in_time_zone('Moscow').strftime('%Y/%m/%d')
dc_abbr = 'За дату создания объекта недвижимости при рассчетах берётся дата создания первой площади объекта'
result[:props] = [
{tag: 'title', val: "#{property.title}"},
{tag: 'born_date', val: "Дата создания: #{dc_str}"},
{tag: 'all_areas_count', val: "Площадей всего: #{ free_areas_atnow + busy_areas_atnow }"},
{tag: 'free_areas_count', val: "Свободных площадей: #{ free_areas_atnow }"},
{tag: 'busy_areas_count', val: "Занятых площадей: #{ busy_areas_atnow }"}
]
if atype_id.present?
result[:props] << {tag: 'atype_filter', val: "Фильтр по типу площади: #{ Atype.find(atype_id).title }"}
end
else
result[:props] = [
{tag: 'title', val: "#{property.title} не имеет площадей"}
]
end
end
result
end
def atype_title
res = "-"
if atype.present?
res = atype.title
end
res
end
def property_title
res = "-"
if property.present?
res = property.title
end
res
end
private
# Когда создаётся запись, посчитаем коэф-ты
def calc_busy_coefs
if self.property.areas.count > 0
# здесь считаем коэф-ты только для `записей с общими данными`
if self.atype.nil?
self.free_areas = self.property.areas.free_areas.count
self.busy_areas = self.property.areas.busy_areas.count
self.coef_busy = self.busy_areas / (self.free_areas + self.busy_areas) * 100
self.free_areas_sq = self.property.areas.free_areas_sq
self.busy_areas_sq = self.property.areas.busy_areas_sq
self.coef_busy_sq = self.busy_areas_sq / (self.free_areas_sq + self.busy_areas_sq) * 100
# здесь считаем коэф-ты для 'atype related записей'
else
self.free_areas = self.property.areas.where(:atype_id => self.atype.id).free_areas.count
self.busy_areas = self.property.areas.where(:atype_id => self.atype.id).busy_areas.count
self.coef_busy = (self.free_areas + self.busy_areas == 0) ? 0:self.busy_areas / (self.free_areas + self.busy_areas) * 100
self.free_areas_sq = self.property.areas.where(:atype_id => self.atype.id).free_areas_sq
self.busy_areas_sq = self.property.areas.where(:atype_id => self.atype.id).busy_areas_sq
self.coef_busy_sq = (self.free_areas_sq + self.busy_areas_sq == 0) ? 0:self.busy_areas_sq / (self.free_areas_sq + self.busy_areas_sq) * 100
end
end
end
# Когда создаётся `запись с общими данными` в таблице 'pstats', автоматически
# создаются `atype related записи` в кол-ве N шт с данными по каждому типу площади
# с такой же датой created_at
def generate_atype_pstats
# генерим только для `записей с общими данными`
if self.atype.nil?
# перебираем все типы
atypes = Atype.all
atypes.each do |atype|
# генерим atype related pstats, связываем их с Родителем
Pstat.create!({
atype_id: atype.id,
property_id: self.property.id,
sevent_id: self.sevent.id,
created_at: self.created_at,
parent_id: self.id
})
end
end
end
def self._parse_for_js_radial_graph(free_areas_atnow, busy_areas_atnow)
# res = [
# ['Year', 'Sales', 'Expenses'],
# ['2013', 1000, 400],
# ['2014', 1170, 460],
# ['2015', 660, 1120],
# ['2016/12/12', 1030, 540]
#
# ]
# [
# ['', ''],
# ['Свободно', 11],
# ['Занято', 2]
# ]
res = [['','']]
res << ['Свободно', free_areas_atnow]
res << ['Занято', busy_areas_atnow]
Rails.logger.debug "<_parse_for_js_radial_graph> res: #{res}"
res
end
def self._parse_for_js_dynamic_graph(pstats)
# res = [
# ['Year', 'Sales', 'Expenses'],
# ['2013', 1000, 400],
# ['2014', 1170, 460],
# ['2015', 660, 1120],
# ['2016/12/12', 1030, 540]
# ]
res = []
pstats.each do |pstat|
res << [ pstat.created_at.strftime('%Y/%m/%d'), pstat.coef_busy ]
end
res
end
end
end