Created
October 16, 2014 18:06
-
-
Save khadzhinov/954b28b3937f549b19cd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Organization < VersionableModel | |
belongs_to :user | |
belongs_to :country | |
belongs_to :organization_economic_type | |
has_many :purchases | |
has_many :all_subscriptions, :class_name => "Subscription", :dependent => :destroy | |
has_many :subscriptions, -> { where {(activated_at != nil) & (valid_through >= my{Time.zone.today}) & (valid_from <= my{Time.zone.today})}.order("valid_from ASC") } | |
has_one :organization_responsible_person, :dependent => :destroy , :inverse_of => :organization | |
has_one :organization_custom_requisite, :dependent => :destroy , :inverse_of => :organization | |
has_one :organization_document, :dependent => :destroy , :inverse_of => :organization | |
has_many :organization_bank_accounts, :dependent => :destroy , :inverse_of => :organization | |
has_many :organization_branches, :dependent => :destroy , :inverse_of => :organization | |
has_many :departments, :dependent => :destroy , :inverse_of => :organization | |
has_many :employees, :dependent => :destroy | |
has_many :calendar_days, :dependent => :destroy | |
has_many :reports, :dependent => :destroy | |
has_many :payments, :dependent => :destroy | |
has_many :events, :dependent => :destroy | |
has_many :feeds, :dependent => :nullify | |
has_many :invites, :dependent => :destroy | |
has_many :users_organizations, :dependent => :destroy | |
has_many :users, :through => :users_organizations | |
has_many :consultant_services, :dependent => :destroy, :foreign_key => :consultant_id | |
has_many :outgoing_contracts, :dependent => :destroy, :class_name => 'Contract' | |
has_many :incoming_contracts, :dependent => :destroy, :class_name => 'Contract', :foreign_key => :contractor_id | |
has_many :incoming_partnerships, :dependent => :destroy, :class_name => 'Partnership', :as => :partner | |
has_many :outgoing_partnerships, :dependent => :destroy, :class_name => 'Partnership', :inverse_of => :organization | |
has_many :external_organizations, :dependent => :destroy | |
has_many :organization_addresses, -> { order("address_type DESC") }, :dependent => :destroy | |
has_many :pattern_numbers, :dependent => :destroy | |
has_one :reports_settings, :dependent => :destroy | |
has_many :incoming_documents, :dependent => :destroy | |
# Warehouse module | |
has_many :warehouses, :dependent => :destroy | |
has_many :nomenclatures, :dependent => :destroy | |
has_many :nomenclature_categories, :dependent => :destroy | |
has_many :stocks, :through => :warehouses | |
has_many :measure_types, :dependent => :destroy | |
has_many :incoming_waybills, :dependent => :destroy | |
has_many :outgoing_waybills, :dependent => :destroy | |
has_many :write_off_acts, :dependent => :destroy | |
has_many :inventory_of_materials, :dependent => :destroy | |
has_many :movement_waybills, :dependent => :destroy | |
has_many :account_entries, :dependent => :destroy | |
has_many :closing_account_entries, :dependent => :destroy | |
has_many :account_rests, :dependent => :destroy | |
has_many :balances, :dependent => :destroy | |
has_one :stocktake_settings, :dependent => :destroy | |
# Stocktake > Documents | |
has_many :cash_in_orders, :dependent => :destroy | |
has_many :cash_out_orders, :dependent => :destroy | |
has_many :incoming_payments, :dependent => :destroy | |
has_many :outgoing_payments | |
has_many :outgoing_invoices, :dependent => :destroy | |
has_many :invoices, :dependent => :destroy | |
has_many :service_acts, :dependent => :destroy | |
has_many :power_of_attorneys, :dependent => :destroy | |
has_many :payrolls, :dependent => :destroy | |
has_many :payroll_expenses, :dependent => :destroy | |
has_many :bank_statements, :dependent => :destroy | |
has_many :advance_statements, :dependent => :destroy | |
has_many :reconciliation_acts, :dependent => :destroy | |
has_many :agreements, :dependent => :destroy | |
has_many :agreement_templates, :dependent => :destroy | |
has_many :agreement_comments, :dependent => :destroy | |
# Stocktake > Assets | |
has_many :fixed_assets, :dependent => :destroy | |
has_many :fixed_asset_receipts, :dependent => :destroy | |
has_many :fixed_asset_acceptances, :dependent => :destroy | |
has_many :fixed_asset_transfers, :dependent => :destroy | |
has_many :fixed_asset_movements, :dependent => :destroy | |
has_many :fixed_asset_renewals, :dependent => :destroy | |
has_many :fixed_asset_writeoffs, :dependent => :destroy | |
has_many :intangible_assets, :dependent => :destroy | |
has_many :intangible_asset_receipts, :dependent => :destroy | |
has_many :intangible_asset_acceptances, :dependent => :destroy | |
has_many :intangible_asset_transfers, :dependent => :destroy | |
has_many :intangible_asset_writeoffs, :dependent => :destroy | |
accepts_nested_attributes_for :organization_responsible_person, :organization_custom_requisite, :organization_document, :allow_destroy => true, :update_only => true | |
accepts_nested_attributes_for :organization_bank_accounts, :organization_branches, :departments, :organization_addresses, :consultant_services, :allow_destroy => true | |
enable_paths | |
scope :unverified, -> { where { verification_status != "verified" } } | |
scope :verified, -> { where { verification_status == "verified" } } | |
scope :expired, -> { verified.where("verification_date_to < ?", Time.now) } | |
scope :expires_during_dates, -> (date) { verified.where({:verification_date_to => Time.now..date})} | |
scope :consultants, -> () { where(:is_consultant => true) } | |
ORGANIZATION_TYPES = %w(pe llp) | |
VERIFICATION_STATUSES = %w(unverified pending_verify_sms waiting_sms_code pending_hsm_verification verified) | |
CREATE_USER_QUEUE = "front.#{Rails.env}_create_user" | |
APPROVE_USER_QUEUE = "front.#{Rails.env}_approve_create_user" | |
after_create do | |
Feed.delay.organization_feed(self, User.current_user, { :feed_code => "create_organization" }) | |
Feed.delay.organization_feed(self, User.current_user, { :feed_code => "new_consultant"}) if self.is_consultant | |
create_pattern_numbers | |
add_default_calendar_days | |
create_default_warehouse | |
add_calendar_events | |
calculate_current_indicators | |
update_browser_data | |
end | |
after_update do | |
if @skip_feed | |
@skip_feed = false | |
else | |
Feed.delay.organization_feed(self, User.current_user, {feed_code: "update_organization"}) | |
Feed.delay.organization_feed(self, User.current_user, {feed_code: "new_consultant"}) if self.is_consultant_changed? && self.is_consultant | |
update_browser_data | |
end | |
end | |
before_destroy do | |
Feed.organization_feed(self, User.current_user, {feed_code: "destroy_organization"}) | |
end | |
after_destroy :update_browser_data | |
before_save :check_addresses | |
after_save do | |
ExternalOrganization.react_to_verification_of(self) if verification_status_changed? && is_verified? | |
end | |
attr_accessible :name, | |
:organization_type, | |
:is_consultant, | |
:consultant_aggrement, | |
:tic, | |
:coordinates_latitude, | |
:coordinates_longitude, | |
:phone, | |
:email, | |
:has_branch, | |
:has_accountant, | |
:matches_address, | |
:tax_system, | |
:organization_economic_type_id, | |
:verification_status, | |
:verification_date_from, | |
:verification_date_to, | |
:vat_payer, | |
:organization_responsible_person_attributes, | |
:organization_document_attributes, | |
:organization_custom_requisite_attributes, | |
:user, | |
:user_id, | |
:are_responsible_persons_real, | |
:organization_bank_accounts_attributes, | |
:organization_branches_attributes, | |
:departments_attributes, | |
:tic_scan_link_cache, | |
:remove_tic_scan_link, | |
:organization_addresses_attributes, | |
:consultant_services_attributes | |
validate :check_unverified_organizations_count | |
validates :name, :verification_status, :organization_type, :tax_system, :organization_economic_type_id, :user_id, :presence => true | |
validates :name, :length => { :maximum => 64 } | |
validates :organization_type, :inclusion => { :in => ORGANIZATION_TYPES } | |
validates :tic, :numericality => { :only_integer => true }, :length => { :is => 12 }, :allow_blank => true | |
validates :verification_status, :inclusion => { :in => VERIFICATION_STATUSES } | |
validates :phone, :numericality => { :only_integer => true }, :length => { :minimum => 9 }, :allow_blank => true | |
validates :email, :email => true, :length => { :maximum => 32 }, :allow_blank => true | |
validates :is_consultant, :inclusion => { :in => [true, false] } | |
mount_uploader :tic_scan_link, ScanUploader | |
def partnerships(scopes_list = [:correct], direction = :all) | |
scopes_list = [scopes_list] unless scopes_list.is_a?(Array) | |
records = [] | |
associations = [] | |
associations << :outgoing_partnerships unless direction == :incoming | |
associations << :incoming_partnerships unless direction == :outgoing | |
associations.each do |association| | |
relation = self.send(association) | |
scopes_list.each { |s| | |
s = (association == :outgoing_partnerships ? :verified_for_initiator : :verified_for_partner) if s == :verified | |
relation = relation.send(s) | |
} | |
records += relation | |
end | |
records | |
end | |
def expiry_months | |
expiry_months = {} | |
Purchasable.subscriptions.each do |purchasable| | |
purchase_item = PurchaseItem.last_actual_purchase_item(id, purchasable.id) | |
expiry_months.merge!({purchasable.code_within_category.to_sym => purchase_item ? purchase_item.expiry_at : nil }) | |
end | |
expiry_months | |
end | |
def primary_bank | |
#organization_bank_accounts.first | |
organization_bank_accounts.primary.first | |
end | |
def organization_type_valid? | |
is_pe? || is_llp? | |
end | |
def is_pe? | |
organization_type == "pe" | |
end | |
alias is_pe is_pe? | |
def is_llp? | |
organization_type == "llp" | |
end | |
alias is_llp is_llp? | |
def is_verified? | |
verification_status == "verified" | |
end | |
alias is_verified is_verified? | |
def is_paid? | |
purchases.joins{purchase_items}.where{(purchase_items.expiry_at > Date.today)}.any? | |
end | |
alias is_paid is_paid? | |
def set_as_unverified! | |
update_attributes!({verification_status: "unverified", verification_date_from: nil, verification_date_to: nil}) | |
end | |
def address_string(type) | |
res = [] | |
addr = | |
organization_addresses.select{ |a| a.address_type == type }.first | |
loc = nil | |
if addr | |
res << addr.zip_code if addr.zip_code | |
res << addr.country.name if addr.country | |
loc = addr.region if addr.region | |
loc = addr.location if addr.location | |
loc = addr.city if addr.city | |
loc = addr.locality if addr.locality | |
res << Location.location_full_addr(loc.id) if loc | |
[:street, :house, :building, :apartment].each do |address_part| | |
res << "#{I18n.t("activerecord.attributes.organization_address.#{address_part}")} #{addr[address_part]}" if addr[address_part] | |
end | |
end | |
res.join ", " | |
end | |
def legal_address | |
address_string "legal" | |
end | |
def actual_address | |
address_string "actual" | |
end | |
def responsible_persons_full_name | |
organization_responsible_person.andand.boss_fio | |
end | |
def id_number | |
return nil unless organization_type_valid? | |
if is_pe? | |
iin | |
elsif is_llp? | |
bin | |
end | |
end | |
def iin | |
organization_custom_requisite.andand.iin | |
end | |
def bin | |
organization_custom_requisite.andand.bin | |
end | |
def sending_on_hsm_base_data | |
requisites = is_llp? ? { :bin => bin } : { :iin => iin } | |
{ :org_type => organization_type, :tic => tic, :phone => user.mobile_phone, :fio => user.fio, :org => name }.merge!(requisites) | |
end | |
def send_eds_on_hsm(eds = "") | |
unless is_verified? | |
begin | |
data = self.sending_on_hsm_base_data.merge!({:eds => eds.read, :routing_key => CREATE_USER_QUEUE}) | |
RabbitMQProducer.publish(data.to_json, :routing_key => "hsm.create_user", :persistent => true) | |
update_attributes!({verification_status: "pending_verify_sms"}) | |
rescue | |
set_as_unverified! | |
end | |
end | |
end | |
def self.find_organization_by_hsm_payload(payload) | |
case payload["org_type"] | |
when "llp" | |
self.select("*").joins(:organization_custom_requisite).where({organization_type: payload["org_type"], organization_custom_requisites: {bin: payload["bin"]} }).first | |
when "pe" | |
self.select("*").joins(:organization_custom_requisite).where({organization_type: payload["org_type"], organization_custom_requisites: {iin: payload["iin"]} }).first | |
else | |
false | |
end | |
end | |
def self.on_create_eds(payload) | |
User.current_user = User.system_user | |
organization = self.find_organization_by_hsm_payload(payload) | |
if organization | |
organization.update_attributes!({verification_status: payload["verification_status"]}) | |
FayeClient.publish "/users/#{organization.user_id}/hsm", payload | |
end | |
end | |
def send_verification_code!(smscode = "") | |
begin | |
data = self.sending_on_hsm_base_data.merge!({:smscode => smscode, :routing_key => APPROVE_USER_QUEUE}) | |
RabbitMQProducer.publish(data.to_json, :routing_key => "hsm.approve_create_user", :persistent => true) | |
self.update_attributes!({verification_status: "pending_hsm_verification"}) | |
rescue | |
self.update_attributes!({verification_status: "waiting_sms_code"}) | |
end | |
end | |
def self.on_verify_create_eds(payload) | |
User.current_user = User.system_user | |
organization = self.find_organization_by_hsm_payload(payload) | |
if organization | |
if payload["verification_status"] == "verified" | |
organization.update_attributes!({verification_status: payload["verification_status"], verification_date_from: payload["verification_date_from"].to_date, verification_date_to: payload["verification_date_to"].to_date}) | |
SystemMailer.delay.success_eds_verification_result_message(organization, payload["msg"]) | |
else | |
organization.update_attributes!({verification_status: payload["verification_status"]}) | |
end | |
FayeClient.publish "/users/#{organization.user_id}/hsm", payload | |
end | |
end | |
def add_calendar_events | |
num = events.size | |
add_salary_events | |
add_tax_events | |
add_report_events | |
if num < events.size | |
FayeClient.publish(model_path + "/events", | |
{:action => :fetch}, | |
{:force => true}) | |
end | |
end | |
def add_salary_events | |
return if stocktake_settings.andand.pay_day.blank? | |
pay_time = DateTime.current.change(:day => stocktake_settings.pay_day.to_i).beginning_of_day | |
Event.where({ | |
organization_id: id, | |
start_date: pay_time - 3.day, | |
end_date: pay_time, | |
eventable_type: "Salary", | |
event_type_id: EventType.find_by_code("charge_salary").id | |
}).first_or_create! | |
end | |
def add_tax_events | |
tax_periods = TaxPeriod.all | |
time_now = Time.now.utc | |
tax_periods.each do | period | | |
Event.joins(:event_type).where({ | |
organization_id: self.id, | |
start_date: DateTime.new(time_now.year, time_now.month, period.start_month_day), | |
end_date: DateTime.new(time_now.year, time_now.month, period.end_month_day), | |
eventable_type: "Tax", | |
event_type_id: EventType.find_by_code("pay_#{period.tax_type.code}").id | |
}).first_or_create! | |
end | |
end | |
def add_report_events | |
quarter = (Date.today.month - 1) / 3 + 1 | |
report_periods = ReportPeriod.includes(:report_type).where({quarter: quarter}).to_a | |
time_now = Time.now.utc | |
report_periods.each do | period | | |
unless self.reports.joins(:report_type).where({quarter_number: quarter, quarter_year: time_now.year, report_type: { name: period.report_type.name }}).first | |
Event.joins(:event_type).where({ | |
organization_id: self.id, | |
start_date: period.start_date, | |
end_date: period.end_date, | |
eventable_type: "Report", | |
event_type_id: EventType.find_by_code("create_report_#{period.report_type.name}").id | |
}).first_or_create! | |
end | |
end | |
end | |
def organization_number_name | |
if self.is_llp? | |
on = I18n.t("activerecord.attributes.organization_custom_requisite.bin") | |
elsif self.is_pe? | |
on = I18n.t("activerecord.attributes.organization_custom_requisite.iin") | |
else | |
on = nil | |
end | |
on | |
end | |
def organization_type_name | |
if %w(llp pe).include?(organization_type) | |
I18n.t("activerecord.attributes.organization.organization_types.#{organization_type}") | |
end | |
end | |
def organization_full_name | |
[self.organization_type_name, self.name].reject{|v| v.blank?}.join(" ").strip | |
end | |
def may_be_consulted | |
!is_consultant? && Ability.current.can?(:create, Contract.new(:organization_id => id)) | |
end | |
alias :may_be_consulted? :may_be_consulted | |
def consulting_status | |
return "consultant" if is_consultant | |
contracts = outgoing_contracts.to_a | |
if contracts.detect { |c| c.is_active? } | |
"being_consulted" | |
elsif contracts.detect { |c| c.is_being_negotiated? } | |
"requested_consulting" | |
else | |
"" | |
end | |
end | |
def calculate_current_indicators | |
indicators = { | |
:balance_cash_deck => nil, | |
:balance_bank => nil, | |
:arrears_employees => nil, | |
:arrears_other => nil, | |
:stock_warehouse => indicators_stock_warehouse.to_s, | |
:stock_assortment => indicators_stock_assortment.to_s, | |
:employees_salaries => indicators_employees_salaries.to_s, | |
:employees_active => indicators_employees_active.to_s, | |
:employees_total => indicators_employees_total.to_s | |
} | |
if current_indicators.blank? || current_indicators.symbolize_keys != indicators | |
@skip_feed = true | |
self.current_indicators = indicators | |
save! | |
FayeClient.publish(model_path + "/current_indicators", | |
{:action => :fetch}, | |
{:force => true}) | |
end | |
end | |
protected | |
# Current indicators block | |
def indicators_stock_warehouse | |
warehouses.inject(0) do |sum, warehouse| | |
sum + warehouse.balance | |
end | |
end | |
def indicators_stock_assortment | |
nomenclatures.where(:nomenclature_type_id => (1..2)).size | |
end | |
def indicators_employees_salaries | |
employees.where({ | |
:is_dismissed => false | |
}).inject(0) do |sum, employee| | |
sum + (employee.employee_salary ? employee.employee_salary.rate : 0) | |
end | |
end | |
def indicators_employees_active | |
employees.where({ | |
:is_dismissed => false | |
}).count do |employee| | |
employee.status == "is_on_work" | |
end | |
end | |
def indicators_employees_total | |
employees.where({ | |
:is_dismissed => false | |
}).count | |
end | |
def check_unverified_organizations_count | |
return if user.andand.is_admin | |
if new_record? && user.andand.organizations.andand.unverified.andand.size.to_i >= 3 | |
errors.add(:flash, "activerecord.errors.organization.unverified_limit_reached") | |
end | |
end | |
def check_addresses | |
if self.matches_address | |
attrs = self.organization_addresses.select{ |a| a.address_type == "legal" }.first.attributes.dup | |
attrs.delete "id" | |
attrs.delete "geom" | |
attrs.delete "last_change" | |
attrs.delete "is_deleted" | |
attrs["address_type"] = "actual" | |
if self.organization_addresses.size == 1 | |
self.organization_addresses << OrganizationAddress.new(attrs) | |
else | |
self.organization_addresses.select{ |a| a.address_type == "actual" }.first.update_attributes attrs | |
end | |
end | |
end | |
def create_default_warehouse | |
warehouses.create(name: I18n.t("views.warehouse.default_name")) | |
end | |
def create_pattern_numbers | |
pattern_numbers = AccDocumentType.select('id, default_mask').where('default_mask is not null').to_a | |
PatternNumber.transaction do | |
pattern_numbers.each do |pattern| | |
PatternNumber.create!(organization_id: self.id, acc_document_type_id: pattern.id, counter: 1, mask: pattern.default_mask) | |
end | |
end | |
end | |
def add_default_calendar_days | |
DefaultCalendarDay.all.each { |day| calendar_days.create(day.attributes.slice("date", "mark")) } | |
end | |
def update_browser_data | |
FayeClient.publish(model_root_path, | |
{:action => :fetch}, | |
{:force => true}) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment