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 Schedulable
Schedulable::SIMPLE_FORM_OPTIONS
Instance Attribute Summary collapse
- #currency ⇒ Object readonly
- #default_email_sender ⇒ Object readonly
- #name ⇒ Object readonly
- #number ⇒ Object readonly
- #short_name ⇒ Object readonly
Belongs to collapse
- #accounting_business_unit ⇒ BusinessUnit
- #address ⇒ Address
- #administration_business_unit ⇒ BusinessUnit
- #country ⇒ Country
- #default_business_unit ⇒ BusinessUnit
- #parent_company ⇒ Company
- #sales_business_unit ⇒ BusinessUnit
Methods included from Models::Auditable
Has one collapse
- #cc_bank_account ⇒ BankAccount
- #customer ⇒ Customer
- #paypal_bank_account ⇒ BankAccount
- #supplier ⇒ Supplier
Has many collapse
- #activity_type_assignment_queues ⇒ ActiveRecord::Relation<ActivityTypeAssignmentQueue>
- #budgets ⇒ ActiveRecord::Relation<Budget>
- #business_units ⇒ ActiveRecord::Relation<BusinessUnit>
- #catalogs ⇒ ActiveRecord::Relation<Catalog>
- #company_holidays ⇒ ActiveRecord::Relation<CompanyHoliday>
- #email_templates ⇒ ActiveRecord::Relation<EmailTemplate>
- #invoices ⇒ ActiveRecord::Relation<Invoice>
- #ledger_company_accounts ⇒ ActiveRecord::Relation<LedgerCompanyAccount>
- #ledger_transactions ⇒ ActiveRecord::Relation<LedgerTransaction>
- #outgoing_payments ⇒ ActiveRecord::Relation<OutgoingPayment>
- #rmas ⇒ ActiveRecord::Relation<Rma>
- #stores ⇒ ActiveRecord::Relation<Store>
- #tax_rates ⇒ ActiveRecord::Relation<TaxRate>
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
-
#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
-
#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
-
#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
-
#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 Schedulable
Methods included from Models::AfterCommittable
Methods included from Models::EventPublishable
Instance Attribute Details
#currency ⇒ Object (readonly)
83 |
# File 'app/models/company.rb', line 83 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
#default_email_sender ⇒ Object (readonly)
83 |
# File 'app/models/company.rb', line 83 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
#name ⇒ Object (readonly)
83 |
# File 'app/models/company.rb', line 83 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
#number ⇒ Object (readonly)
83 |
# File 'app/models/company.rb', line 83 validates :short_name, :name, :number, :default_email_sender, :currency, presence: true |
#short_name ⇒ Object (readonly)
83 |
# File 'app/models/company.rb', line 83 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
88 |
# File 'app/models/company.rb', line 88 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
87 |
# File 'app/models/company.rb', line 87 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
86 |
# File 'app/models/company.rb', line 86 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.
302 303 304 305 |
# File 'app/models/company.rb', line 302 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.
212 213 214 |
# File 'app/models/company.rb', line 212 def self. Company.order(:id).pluck(:name, :id) end |
.select_options_sales_companies ⇒ Array<Array(String, Integer)>
219 220 221 |
# File 'app/models/company.rb', line 219 def self. Company.sales_companies.pluck(:name, :id) end |
Instance Method Details
#accounting_business_unit ⇒ BusinessUnit
59 |
# File 'app/models/company.rb', line 59 belongs_to :accounting_business_unit, class_name: 'BusinessUnit', optional: true |
#activity_type_assignment_queues ⇒ ActiveRecord::Relation<ActivityTypeAssignmentQueue>
74 |
# File 'app/models/company.rb', line 74 has_many :activity_type_assignment_queues, inverse_of: :company |
#add_business_days(from, business_days) ⇒ Date
Advance +business_days+ working days from +from+, skipping weekends and
this company's holidays. Used for carrier transit-time / arrival-date
estimates.
NOTE: 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.
203 204 205 206 207 |
# File 'app/models/company.rb', line 203 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 |
#administration_business_unit ⇒ BusinessUnit
57 |
# File 'app/models/company.rb', line 57 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.
323 324 325 |
# File 'app/models/company.rb', line 323 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>).
315 316 317 |
# File 'app/models/company.rb', line 315 def assign_next_invoice_number next_year_aware_reference("next_invoice_number_#{id}", "invoice_number_#{id}") end |
#budgets ⇒ ActiveRecord::Relation<Budget>
76 |
# File 'app/models/company.rb', line 76 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.
264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'app/models/company.rb', line 264 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>
78 |
# File 'app/models/company.rb', line 78 has_many :business_units |
#catalogs ⇒ ActiveRecord::Relation<Catalog>
79 |
# File 'app/models/company.rb', line 79 has_many :catalogs, inverse_of: :company |
#cc_bank_account ⇒ BankAccount
64 |
# File 'app/models/company.rb', line 64 has_one :cc_bank_account, class_name: 'BankAccount', foreign_key: 'cc_company_id' |
#company_holidays ⇒ ActiveRecord::Relation<CompanyHoliday>
77 |
# File 'app/models/company.rb', line 77 has_many :company_holidays, dependent: :destroy |
#company_label ⇒ String
"USA πΊπΈ"-style label for the company chooser.
232 233 234 |
# File 'app/models/company.rb', line 232 def company_label "#{country_iso3} #{country_iso3166.emoji_flag}" end |
#country ⇒ Country
60 |
# File 'app/models/company.rb', line 60 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).
226 227 228 |
# File 'app/models/company.rb', line 226 def country_iso3166 ISO3166::Country.find_country_by_alpha3(country_iso3) end |
#currency_symbol ⇒ String
ISO currency symbol for the company's functional currency.
253 254 255 |
# File 'app/models/company.rb', line 253 def currency_symbol Money::Currency.new(currency).symbol end |
#default_business_unit ⇒ BusinessUnit
56 |
# File 'app/models/company.rb', line 56 belongs_to :default_business_unit, class_name: 'BusinessUnit', optional: true |
#email_templates ⇒ ActiveRecord::Relation<EmailTemplate>
75 |
# File 'app/models/company.rb', line 75 has_many :email_templates, as: :resource |
#holiday_dates ⇒ Array<Date>
Get all holiday dates for this company
140 141 142 |
# File 'app/models/company.rb', line 140 def holiday_dates company_holidays.pluck(:holiday_date) end |
#invoices ⇒ ActiveRecord::Relation<Invoice>
71 |
# File 'app/models/company.rb', line 71 has_many :invoices |
#ledger_company_accounts ⇒ ActiveRecord::Relation<LedgerCompanyAccount>
69 |
# File 'app/models/company.rb', line 69 has_many :ledger_company_accounts |
#ledger_transactions ⇒ ActiveRecord::Relation<LedgerTransaction>
70 |
# File 'app/models/company.rb', line 70 has_many :ledger_transactions |
#locale ⇒ Symbol
I18n locale that matches the company entity. Falls back to
en-US for the placeholder IND row.
239 240 241 |
# File 'app/models/company.rb', line 239 def locale { USA => :'en-US', CAN => :'en-CA', NLD => :'nl-NL' }[id] || :'en-US' end |
#netherland? ⇒ Boolean
285 286 287 |
# File 'app/models/company.rb', line 285 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
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'app/models/company.rb', line 165 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
148 149 150 151 152 153 154 155 156 157 158 |
# File 'app/models/company.rb', line 148 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
90 91 92 |
# File 'app/models/company.rb', line 90 def open_on_a_day?(date) company_holidays.where(holiday_date: date).exists? end |
#outgoing_payments ⇒ ActiveRecord::Relation<OutgoingPayment>
73 |
# File 'app/models/company.rb', line 73 has_many :outgoing_payments |
#parent_company ⇒ Company
54 |
# File 'app/models/company.rb', line 54 belongs_to :parent_company, class_name: 'Company', optional: true |
#paypal_bank_account ⇒ BankAccount
65 |
# File 'app/models/company.rb', line 65 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
290 291 292 293 294 295 296 297 |
# File 'app/models/company.rb', line 290 def rma_inspect_email case id when CAN 'rma_inspection_can@warmlyyours.com' else 'rma_inspection_usa@warmlyyours.com' end end |
#sales_business_unit ⇒ BusinessUnit
58 |
# File 'app/models/company.rb', line 58 belongs_to :sales_business_unit, class_name: 'BusinessUnit', optional: true |
#schema_dot_org_aggregate_rating ⇒ Object
Alias for Class#schema_dot_org_aggregate_rating
307 |
# File 'app/models/company.rb', line 307 delegate :schema_dot_org_aggregate_rating, to: :class |
#summary_name ⇒ String Also known as: to_s
"<number> <name>" label used in breadcrumbs and dropdowns.
245 246 247 |
# File 'app/models/company.rb', line 245 def summary_name "#{number} #{name}" end |
#tax_rates ⇒ ActiveRecord::Relation<TaxRate>
68 |
# File 'app/models/company.rb', line 68 has_many :tax_rates |
#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
129 130 131 132 133 134 135 136 |
# File 'app/models/company.rb', line 129 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
185 186 187 188 189 |
# File 'app/models/company.rb', line 185 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
115 116 117 |
# File 'app/models/company.rb', line 115 def working_hours_timezone WORKING_HOURS_TIMEZONES[id] || 'America/Chicago' end |