Class: Company
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Company
- Includes:
- Models::Auditable
- Defined in:
- app/models/company.rb
Overview
== Schema Information
Table name: companies
Database name: primary
id :integer not null, primary key
consolidated_currency :string(3)
country_iso3 :string(255)
currency :string(255)
default_email_sender :string(50)
legal_name :string(255)
market_zone :string
name :string(100)
number :integer
short_name :string(255)
tax_info :string(255)
accounting_business_unit_id :integer
address_id :integer
administration_business_unit_id :integer
default_business_unit_id :integer
ledger_project_id :integer
parent_company_id :integer
sales_business_unit_id :integer
Indexes
companies_address_id_idx (address_id)
companies_parent_company_id_idx (parent_company_id)
companies_sales_business_unit_id_idx (sales_business_unit_id)
idx_company_number (number)
index_companies_on_ledger_project_id (ledger_project_id)
index_companies_on_market_zone (market_zone)
Foreign Keys
companies_address_id_fk (address_id => addresses.id) ON DELETE => nullify
companies_parent_company_id_fk (parent_company_id => companies.id) ON DELETE => nullify
companies_sales_business_unit_id_fk (sales_business_unit_id => business_units.id) ON DELETE => nullify
Constant Summary collapse
- USA =
Usa.
1- CAN =
Can.
2- IND =
Ind.
3- NLD =
Nld.
4- WORKING_HOURS_CONFIG =
Working hours configuration for this company
Default is Mon-Fri 8:30am-5:30pm { mon: { '08:30' => '17:30' }, tue: { '08:30' => '17:30' }, wed: { '08:30' => '17:30' }, thu: { '08:30' => '17:30' }, fri: { '08:30' => '17:30' } }.freeze
- WORKING_HOURS_TIMEZONES =
Timezone for working hours by company
Future: Could be moved to Store model when we have multiple warehouses per country { USA => 'America/Chicago', CAN => 'America/Toronto', IND => 'Asia/Kolkata', NLD => 'Europe/Amsterdam' }.freeze
Constants included from Models::Auditable
Models::Auditable::ALWAYS_IGNORED
Constants included from Models::Schedulable
Models::Schedulable::SIMPLE_FORM_OPTIONS
Instance Attribute Summary collapse
-
#currency ⇒ Object
readonly
Validates short name, name, number, default email sender, currency.
-
#default_email_sender ⇒ Object
readonly
Validates short name, name, number, default email sender, currency.
-
#name ⇒ Object
readonly
Validates short name, name, number, default email sender, currency.
-
#number ⇒ Object
readonly
Validates short name, name, number, default email sender, currency.
-
#short_name ⇒ Object
readonly
Validates short name, name, number, default email sender, currency.
Belongs to collapse
-
#accounting_business_unit ⇒ BusinessUnit?
The accounting business unit this record belongs to.
-
#address ⇒ Address?
The address this record belongs to.
-
#administration_business_unit ⇒ BusinessUnit?
The administration business unit this record belongs to.
-
#country ⇒ Country?
The country this record belongs to.
-
#default_business_unit ⇒ BusinessUnit?
The default business unit this record belongs to.
-
#parent_company ⇒ Company?
The parent company this record belongs to.
-
#sales_business_unit ⇒ BusinessUnit?
The sales business unit this record belongs to.
Methods included from Models::Auditable
Has one collapse
-
#cc_bank_account ⇒ BankAccount?
The associated cc bank account.
-
#customer ⇒ Customer?
The associated customer.
-
#paypal_bank_account ⇒ BankAccount?
The associated paypal bank account.
-
#supplier ⇒ Supplier?
The associated supplier.
Has many collapse
-
#activity_type_assignment_queues ⇒ ActiveRecord::Relation<ActivityTypeAssignmentQueue>
The associated activity type assignment queues.
-
#budgets ⇒ ActiveRecord::Relation<Budget>
The associated budgets.
-
#business_units ⇒ ActiveRecord::Relation<BusinessUnit>
The associated business units.
-
#catalogs ⇒ ActiveRecord::Relation<Catalog>
The associated catalogs.
-
#company_holidays ⇒ ActiveRecord::Relation<CompanyHoliday>
The associated company holidays.
-
#email_templates ⇒ ActiveRecord::Relation<EmailTemplate>
The associated email templates.
-
#invoices ⇒ ActiveRecord::Relation<Invoice>
The associated invoices.
-
#ledger_company_accounts ⇒ ActiveRecord::Relation<LedgerCompanyAccount>
The associated ledger company accounts.
-
#ledger_transactions ⇒ ActiveRecord::Relation<LedgerTransaction>
The associated ledger transactions.
-
#outgoing_payments ⇒ ActiveRecord::Relation<OutgoingPayment>
The associated outgoing payments.
-
#rmas ⇒ ActiveRecord::Relation<Rma>
The associated rmas.
-
#stores ⇒ ActiveRecord::Relation<Store>
The associated stores.
-
#tax_rates ⇒ ActiveRecord::Relation<TaxRate>
The associated tax rates.
Delegated Instance Attributes collapse
-
#schema_dot_org_aggregate_rating ⇒ Object
Alias for Class#schema_dot_org_aggregate_rating.
Class Method Summary collapse
-
.market_zone_eu ⇒ ActiveRecord::Relation<Company>
A relation of Companies that are market zone eu.
-
.market_zone_na ⇒ ActiveRecord::Relation<Company>
A relation of Companies that are market zone na.
-
.sales_companies ⇒ ActiveRecord::Relation<Company>
A relation of Companies that are sales companies.
-
.schema_dot_org_aggregate_rating ⇒ nil
deprecated
Deprecated.
reviews moved to Reviews.io; the rating is fetched
client-side via their API. Kept so old templates don't 500. -
.select_options ⇒ Array<Array(String, Integer)>
[name, id]pairs for every Company (including IND placeholder), used in admin filter dropdowns. - .select_options_sales_companies ⇒ Array<Array(String, Integer)>
Instance Method Summary collapse
-
#add_business_days(from, business_days) ⇒ Date
Advance +business_days+ working days from +from+, skipping weekends and this company's holidays.
-
#assign_next_credit_memo_number ⇒ String
Same scheme as #assign_next_invoice_number but pulls from the per-company
next_credit_memo_number_<id>sequence. -
#assign_next_invoice_number ⇒ String
Allocate the next invoice number for this company.
-
#business_unit_for(dept) ⇒ BusinessUnit?
Look up one of the four canonical BusinessUnits by department tag β
default/sales/administration/accounting. -
#canada? ⇒ Boolean
Whether the record canada.
-
#company_label ⇒ String
"USA πΊπΈ"-style label for the company chooser. -
#country_iso3166 ⇒ ISO3166::Country?
Resolve
country_iso3to an ISO3166::Country instance (used downstream for emoji flag, name, demonym). -
#currency_symbol ⇒ String
ISO currency symbol for the company's functional currency.
-
#holiday_dates ⇒ Array<Date>
Get all holiday dates for this company.
-
#locale ⇒ Symbol
I18n locale that matches the company entity.
-
#netherland? ⇒ Boolean
Whether the record netherland.
-
#next_business_day(date) ⇒ Date
Find the next business day on or after the given date Skips weekends and company holidays.
-
#next_valid_ship_date ⇒ Date
Calculate the next valid ship date for this company Accounts for weekends and company holidays.
-
#open_on_a_day?(date) ⇒ Boolean
Whether the record open on a day.
-
#rma_inspect_email ⇒ Object
at some point these can be database editable fields.
-
#summary_name ⇒ String
(also: #to_s)
"<number> <name>"label used in breadcrumbs and dropdowns. -
#usa? ⇒ Boolean
Whether the record usa.
-
#with_working_hours_config { ... } ⇒ Object
Execute a block with working hours configured for this company's holidays and timezone This is the preferred way to do business day calculations.
-
#working_day?(date) ⇒ Boolean
Check if a given date is a working day for this company.
-
#working_hours_timezone ⇒ String
Get the timezone for this company's warehouse operations.
Methods included from Models::Auditable
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
Methods inherited from ApplicationRecord
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
Methods included from Models::Schedulable
Methods included from Models::AfterCommittable
Methods included from Models::EventPublishable
Instance Attribute Details
#currency ⇒ Object (readonly)
Validates short name, name, number, default email sender, currency.
Validations:
108 |
# File 'app/models/company.rb', line 108 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
#default_email_sender ⇒ Object (readonly)
Validates short name, name, number, default email sender, currency.
Validations:
108 |
# File 'app/models/company.rb', line 108 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
#name ⇒ Object (readonly)
Validates short name, name, number, default email sender, currency.
Validations:
108 |
# File 'app/models/company.rb', line 108 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
#number ⇒ Object (readonly)
Validates short name, name, number, default email sender, currency.
Validations:
108 |
# File 'app/models/company.rb', line 108 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
#short_name ⇒ Object (readonly)
Validates short name, name, number, default email sender, currency.
Validations:
108 |
# File 'app/models/company.rb', line 108 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
Class Method Details
.market_zone_eu ⇒ ActiveRecord::Relation<Company>
A relation of Companies that are market zone eu. Active Record Scope
113 |
# File 'app/models/company.rb', line 113 scope :market_zone_eu, -> { where(market_zone: 'EU').order(:id) } |
.market_zone_na ⇒ ActiveRecord::Relation<Company>
A relation of Companies that are market zone na. Active Record Scope
112 |
# File 'app/models/company.rb', line 112 scope :market_zone_na, -> { where(market_zone: 'NA').order(:id) } |
.sales_companies ⇒ ActiveRecord::Relation<Company>
A relation of Companies that are sales companies. Active Record Scope
111 |
# File 'app/models/company.rb', line 111 scope :sales_companies, -> { where(id: [USA, CAN, NLD]).order(:id) } |
.schema_dot_org_aggregate_rating ⇒ nil
reviews moved to Reviews.io; the rating is fetched
client-side via their API. Kept so old templates don't 500.
332 333 334 335 |
# File 'app/models/company.rb', line 332 def self. # Reviews migrated to Reviews.io - aggregate rating now fetched from Reviews.io API nil end |
.select_options ⇒ Array<Array(String, Integer)>
[name, id] pairs for every Company (including IND
placeholder), used in admin filter dropdowns.
239 240 241 |
# File 'app/models/company.rb', line 239 def self. Company.order(:id).pluck(:name, :id) end |
.select_options_sales_companies ⇒ Array<Array(String, Integer)>
246 247 248 |
# File 'app/models/company.rb', line 246 def self. Company.sales_companies.pluck(:name, :id) end |
Instance Method Details
#accounting_business_unit ⇒ BusinessUnit?
Returns the accounting business unit this record belongs to.
65 |
# File 'app/models/company.rb', line 65 belongs_to :accounting_business_unit, class_name: 'BusinessUnit', optional: true |
#activity_type_assignment_queues ⇒ ActiveRecord::Relation<ActivityTypeAssignmentQueue>
Returns the associated activity type assignment queues.
93 |
# File 'app/models/company.rb', line 93 has_many :activity_type_assignment_queues, inverse_of: :company |
#add_business_days(from, business_days) ⇒ Date
this uses our shipping holidays. Carrier-specific holiday
calendars (a carrier may observe days we don't, or vice versa) are a
future enhancement β for now the company's standard holiday set is a
good-enough proxy for both.
Advance +business_days+ working days from +from+, skipping weekends and
this company's holidays. Used for carrier transit-time / arrival-date
estimates.
230 231 232 233 234 |
# File 'app/models/company.rb', line 230 def add_business_days(from, business_days) with_working_hours_config do WorkingHours.add_days(from.to_date, business_days.to_i).to_date end end |
#address ⇒ Address?
Returns the address this record belongs to.
57 |
# File 'app/models/company.rb', line 57 belongs_to :address, optional: true |
#administration_business_unit ⇒ BusinessUnit?
Returns the administration business unit this record belongs to.
61 |
# File 'app/models/company.rb', line 61 belongs_to :administration_business_unit, class_name: 'BusinessUnit', optional: true |
#assign_next_credit_memo_number ⇒ String
Same scheme as #assign_next_invoice_number but pulls from
the per-company next_credit_memo_number_<id> sequence.
353 354 355 |
# File 'app/models/company.rb', line 353 def assign_next_credit_memo_number next_year_aware_reference("next_credit_memo_number_#{id}", "credit_memo_number_#{id}") end |
#assign_next_invoice_number ⇒ String
Allocate the next invoice number for this company. Format is
<company_id><YY><5-digit serial> zero-padded to 9 chars,
rolled at calendar-year change. Pulls from a per-company
Postgres sequence (next_invoice_number_<id>).
345 346 347 |
# File 'app/models/company.rb', line 345 def assign_next_invoice_number next_year_aware_reference("next_invoice_number_#{id}", "invoice_number_#{id}") end |
#budgets ⇒ ActiveRecord::Relation<Budget>
Returns the associated budgets.
97 |
# File 'app/models/company.rb', line 97 has_many :budgets |
#business_unit_for(dept) ⇒ BusinessUnit?
Look up one of the four canonical BusinessUnits by department
tag β default / sales / administration / accounting.
GL-posting code uses this so per-row business-unit assignment
comes from the Company rather than being hard-coded.
291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'app/models/company.rb', line 291 def business_unit_for(dept) case dept when 'default' default_business_unit when 'sales' sales_business_unit when 'administration' administration_business_unit when 'accounting' accounting_business_unit end end |
#business_units ⇒ ActiveRecord::Relation<BusinessUnit>
Returns the associated business units.
101 |
# File 'app/models/company.rb', line 101 has_many :business_units |
#canada? ⇒ Boolean
Returns whether the record canada.
310 311 312 |
# File 'app/models/company.rb', line 310 def canada? id == CAN end |
#catalogs ⇒ ActiveRecord::Relation<Catalog>
Returns the associated catalogs.
103 |
# File 'app/models/company.rb', line 103 has_many :catalogs, inverse_of: :company |
#cc_bank_account ⇒ BankAccount?
Returns the associated cc bank account.
74 |
# File 'app/models/company.rb', line 74 has_one :cc_bank_account, class_name: 'BankAccount', foreign_key: 'cc_company_id' |
#company_holidays ⇒ ActiveRecord::Relation<CompanyHoliday>
Returns the associated company holidays.
99 |
# File 'app/models/company.rb', line 99 has_many :company_holidays, dependent: :destroy |
#company_label ⇒ String
"USA πΊπΈ"-style label for the company chooser.
259 260 261 |
# File 'app/models/company.rb', line 259 def company_label "#{country_iso3} #{country_iso3166.emoji_flag}" end |
#country ⇒ Country?
Returns the country this record belongs to.
67 |
# File 'app/models/company.rb', line 67 belongs_to :country, foreign_key: 'country_iso3', primary_key: 'iso3', optional: true |
#country_iso3166 ⇒ ISO3166::Country?
Resolve country_iso3 to an ISO3166::Country instance
(used downstream for emoji flag, name, demonym).
253 254 255 |
# File 'app/models/company.rb', line 253 def country_iso3166 ISO3166::Country.find_country_by_alpha3(country_iso3) end |
#currency_symbol ⇒ String
ISO currency symbol for the company's functional currency.
280 281 282 |
# File 'app/models/company.rb', line 280 def currency_symbol Money::Currency.new(currency).symbol end |
#customer ⇒ Customer?
Returns the associated customer.
70 |
# File 'app/models/company.rb', line 70 has_one :customer |
#default_business_unit ⇒ BusinessUnit?
Returns the default business unit this record belongs to.
59 |
# File 'app/models/company.rb', line 59 belongs_to :default_business_unit, class_name: 'BusinessUnit', optional: true |
#email_templates ⇒ ActiveRecord::Relation<EmailTemplate>
Returns the associated email templates.
95 |
# File 'app/models/company.rb', line 95 has_many :email_templates, as: :resource, dependent: :destroy |
#holiday_dates ⇒ Array<Date>
Get all holiday dates for this company
167 168 169 |
# File 'app/models/company.rb', line 167 def holiday_dates company_holidays.pluck(:holiday_date) end |
#invoices ⇒ ActiveRecord::Relation<Invoice>
Returns the associated invoices.
87 |
# File 'app/models/company.rb', line 87 has_many :invoices |
#ledger_company_accounts ⇒ ActiveRecord::Relation<LedgerCompanyAccount>
Returns the associated ledger company accounts.
83 |
# File 'app/models/company.rb', line 83 has_many :ledger_company_accounts |
#ledger_transactions ⇒ ActiveRecord::Relation<LedgerTransaction>
Returns the associated ledger transactions.
85 |
# File 'app/models/company.rb', line 85 has_many :ledger_transactions |
#locale ⇒ Symbol
I18n locale that matches the company entity. Falls back to
en-US for the placeholder IND row.
266 267 268 |
# File 'app/models/company.rb', line 266 def locale { USA => :'en-US', CAN => :'en-CA', NLD => :'nl-NL' }[id] || :'en-US' end |
#netherland? ⇒ Boolean
Returns whether the record netherland.
315 316 317 |
# File 'app/models/company.rb', line 315 def netherland? id == NLD end |
#next_business_day(date) ⇒ Date
Find the next business day on or after the given date
Skips weekends and company holidays
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'app/models/company.rb', line 192 def next_business_day(date) # Build the midnight Time in the warehouse zone, not the system # zone. `Date#to_time` uses the process's local TZ, so on a UTC # server it shifts the input back a day before # `WorkingHours.advance_to_working_time` can act on it. time = Time.find_zone!(working_hours_timezone).local(date.year, date.month, date.day) with_working_hours_config do if WorkingHours.working_day?(date) date else WorkingHours.advance_to_working_time(time).to_date end end end |
#next_valid_ship_date ⇒ Date
Calculate the next valid ship date for this company
Accounts for weekends and company holidays
175 176 177 178 179 180 181 182 183 184 185 |
# File 'app/models/company.rb', line 175 def next_valid_ship_date now = Time.current.in_time_zone(working_hours_timezone) with_working_hours_config do if now.in_working_hours? now.to_date else WorkingHours.advance_to_working_time(now).to_date end end end |
#open_on_a_day?(date) ⇒ Boolean
Returns whether the record open on a day.
117 118 119 |
# File 'app/models/company.rb', line 117 def open_on_a_day?(date) company_holidays.where(holiday_date: date).exists? end |
#outgoing_payments ⇒ ActiveRecord::Relation<OutgoingPayment>
Returns the associated outgoing payments.
91 |
# File 'app/models/company.rb', line 91 has_many :outgoing_payments |
#parent_company ⇒ Company?
Returns the parent company this record belongs to.
55 |
# File 'app/models/company.rb', line 55 belongs_to :parent_company, class_name: 'Company', optional: true |
#paypal_bank_account ⇒ BankAccount?
Returns the associated paypal bank account.
76 |
# File 'app/models/company.rb', line 76 has_one :paypal_bank_account, class_name: 'BankAccount', foreign_key: 'paypal_company_id' |
#rma_inspect_email ⇒ Object
at some point these can be database editable fields
320 321 322 323 324 325 326 327 |
# File 'app/models/company.rb', line 320 def rma_inspect_email case id when CAN 'rma_inspection_can@warmlyyours.com' else 'rma_inspection_usa@warmlyyours.com' end end |
#rmas ⇒ ActiveRecord::Relation<Rma>
Returns the associated rmas.
89 |
# File 'app/models/company.rb', line 89 has_many :rmas |
#sales_business_unit ⇒ BusinessUnit?
Returns the sales business unit this record belongs to.
63 |
# File 'app/models/company.rb', line 63 belongs_to :sales_business_unit, class_name: 'BusinessUnit', optional: true |
#schema_dot_org_aggregate_rating ⇒ Object
Alias for Class#schema_dot_org_aggregate_rating
337 |
# File 'app/models/company.rb', line 337 delegate :schema_dot_org_aggregate_rating, to: :class |
#stores ⇒ ActiveRecord::Relation<Store>
Returns the associated stores.
79 |
# File 'app/models/company.rb', line 79 has_many :stores |
#summary_name ⇒ String Also known as: to_s
"<number> <name>" label used in breadcrumbs and dropdowns.
272 273 274 |
# File 'app/models/company.rb', line 272 def summary_name "#{number} #{name}" end |
#supplier ⇒ Supplier?
Returns the associated supplier.
72 |
# File 'app/models/company.rb', line 72 has_one :supplier |
#tax_rates ⇒ ActiveRecord::Relation<TaxRate>
Returns the associated tax rates.
81 |
# File 'app/models/company.rb', line 81 has_many :tax_rates |
#usa? ⇒ Boolean
Returns whether the record usa.
305 306 307 |
# File 'app/models/company.rb', line 305 def usa? id == USA end |
#with_working_hours_config { ... } ⇒ Object
Execute a block with working hours configured for this company's holidays and timezone
This is the preferred way to do business day calculations
156 157 158 159 160 161 162 163 |
# File 'app/models/company.rb', line 156 def with_working_hours_config(&) WorkingHours::Config.with_config( working_hours: WORKING_HOURS_CONFIG, holidays: holiday_dates, time_zone: working_hours_timezone, & ) end |
#working_day?(date) ⇒ Boolean
Check if a given date is a working day for this company
212 213 214 215 216 |
# File 'app/models/company.rb', line 212 def working_day?(date) with_working_hours_config do WorkingHours.working_day?(date) end end |
#working_hours_timezone ⇒ String
Get the timezone for this company's warehouse operations
142 143 144 |
# File 'app/models/company.rb', line 142 def working_hours_timezone WORKING_HOURS_TIMEZONES[id] || 'America/Chicago' end |