Class: Party
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Party
- Includes:
- ActionView::Helpers::NumberHelper, CrmLinkable, Models::Auditable, Models::LiquidMethods, Models::Notable, PartyAccount, PartyAddresses, PartyCart, PartyContactInfo, PartyIdentity, PartySearch, PgSearch::Model
- Defined in:
- app/models/party.rb
Overview
Single-table inheritance (STI) base for every CRM party row in parties
(customers, contacts, employees, suppliers, buying-group rows, and similar roles).
Shared persistence (addresses, reps, consent JSON, catalog links) lives on this model;
subtype behaviour is composed through subclasses and Party*, Customer*, and Contact*
concerns.
Direct Known Subclasses
Defined Under Namespace
Classes: ExistingAccountError
Constant Summary collapse
- PREFERRED_LANGUAGES =
Preferred languages.
%w[French Spanish].freeze
Constants included from Models::Auditable
Models::Auditable::ALWAYS_IGNORED
Constants included from Schedulable
Schedulable::SIMPLE_FORM_OPTIONS
Instance Attribute Summary collapse
-
#creation_method ⇒ Object
readonly
The pre-Rails-7 normalizr config had
normalize :profile, ...— a typo that targeted no real column (Party hasprofile_idandprofile_info, notprofile) and was a silent no-op.
Belongs to collapse
- #catalog ⇒ Catalog
- #company ⇒ Company
-
#customer ⇒ Customer
WHEN CREATING A NEW ASSOCIATION FOR YOUR PARTY, CUSTOMER OR CONTACT DO NOT FORGET TO HANDLE THEM IN MERGE OPERATIONS IMPLEMENT THIS IN customer_merger.rb or contact_merger.rb.
- #gl_offset_account ⇒ LedgerAccount
- #profile_image ⇒ Image
- #visit ⇒ Visit
Methods included from Models::Auditable
Has one collapse
-
#account ⇒ Account
NOTE: this is a documentation-only association used as a convenience accessor.
- #store ⇒ Store
Has many collapse
- #accounts ⇒ ActiveRecord::Relation<Account>
-
#activities ⇒ ActiveRecord::Relation<Activity>
rubocop:enable Rails/InverseOf.
- #addresses ⇒ ActiveRecord::Relation<Address>
- #agreement_participants ⇒ ActiveRecord::Relation<AgreementParticipant>
- #agreements ⇒ ActiveRecord::Relation<Agreement>
- #assistant_conversations ⇒ ActiveRecord::Relation<AssistantConversation>
- #billing_credit_memos ⇒ ActiveRecord::Relation<CreditMemo>
- #consignment_stores ⇒ ActiveRecord::Relation<Store>
-
#contact_points ⇒ ActiveRecord::Relation<ContactPoint>
-- Contact shares customer_id FK with supplier; see Contact model.
- #contacts ⇒ ActiveRecord::Relation<Contact>
- #course_enrollments ⇒ ActiveRecord::Relation<CourseEnrollment>
-
#credit_memos ⇒ ActiveRecord::Relation<CreditMemo>
owner of the credit memo.
- #destination_call_logs ⇒ ActiveRecord::Relation<CallLog>
- #destination_call_records ⇒ ActiveRecord::Relation<CallRecord>
- #inbound_communications ⇒ ActiveRecord::Relation<Communication>
- #notifications ⇒ ActiveRecord::Relation<Noticed::Notification>
- #opportunity_participants ⇒ ActiveRecord::Relation<OpportunityParticipant>
- #origin_call_logs ⇒ ActiveRecord::Relation<CallLog>
- #origin_call_records ⇒ ActiveRecord::Relation<CallRecord>
- #outbound_communications ⇒ ActiveRecord::Relation<Communication>
- #outgoing_payments ⇒ ActiveRecord::Relation<OutgoingPayment>
- #party_topics ⇒ ActiveRecord::Relation<PartyTopic>
- #purchase_orders ⇒ ActiveRecord::Relation<PurchaseOrder>
- #queue_call_logs ⇒ ActiveRecord::Relation<QueueCallLog>
- #receipts ⇒ ActiveRecord::Relation<Receipt>
- #recipient_sms_messages ⇒ ActiveRecord::Relation<SmsMessage>
- #room_plans ⇒ ActiveRecord::Relation<RoomPlan>
- #sender_sms_messages ⇒ ActiveRecord::Relation<SmsMessage>
- #support_case_participants ⇒ ActiveRecord::Relation<SupportCaseParticipant>
- #support_cases ⇒ ActiveRecord::Relation<SupportCase>
- #survey_enrollments ⇒ ActiveRecord::Relation<SurveyEnrollment>
- #uploads ⇒ ActiveRecord::Relation<Upload>
- #visit_events ⇒ ActiveRecord::Relation<VisitEvent>
- #visits ⇒ ActiveRecord::Relation<Visit>
- #voucher_items ⇒ ActiveRecord::Relation<VoucherItem>
- #vouchers ⇒ ActiveRecord::Relation<Voucher>
Has and belongs to many collapse
- #digital_assets ⇒ ActiveRecord::Relation<DigitalAsset>
- #linked_activities ⇒ ActiveRecord::Relation<Activity>
-
#product_lines ⇒ ActiveRecord::Relation<ProductLine>
-- legacy join tables; migrating to has_many :through is a separate effort.
Delegated Instance Attributes collapse
-
#can? ⇒ Object
Alias for Ability#can?.
-
#cannot? ⇒ Object
Alias for Ability#cannot?.
-
#has_role? ⇒ Object
Alias for Account#has_role?.
-
#is_admin? ⇒ Object
Alias for Account#is_admin?.
-
#is_document_maintainer? ⇒ Object
Alias for Account#is_document_maintainer?.
-
#is_local_sales_rep? ⇒ Object
Alias for Account#is_local_sales_rep?.
-
#is_manager? ⇒ Object
Alias for Account#is_manager?.
-
#is_marketing_manager? ⇒ Object
Alias for Account#is_marketing_manager?.
-
#is_sales_manager? ⇒ Object
Alias for Account#is_sales_manager?.
-
#is_sales_rep? ⇒ Object
Alias for Account#is_sales_rep?.
-
#locale ⇒ Object
Alias for I18n#locale.
-
#main_address ⇒ Object
Alias for Addresses#main_address.
Instance Method Summary collapse
-
#set_full_name ⇒ Object
protected
Before-save callback: rebuild the denormalised
full_namecolumn from the party-type-specific name fields (first/last for people, company name for organizations). -
#set_state_code ⇒ Object
protected
Validation/before-save callback that pins
state_codeto the main address'sstate_code, falling back to whatever Cloudflare visit data was captured at landing time. -
#set_timezone ⇒ Object
protected
Before-save callback: lazily resolve and persist the party's IANA timezone once we have enough info to do so.
Methods included from CrmLinkable
#crm_link, #crm_link_with_host
Methods included from PartyAccount
#ability, #build_account, #create_account, #online_account_invite, #refuse_silent_account_replacement!, search_for_authenticable_linked_party_by_email
Methods included from PartyCart
#all_uploads, #assign_chained_activities?, #cart, #cart=, #cart?, #cart_id, #cart_info, #create_activity, #create_quote_builder_project, #load_cart, #store_original_source
Methods included from PartyIdentity
#active?, #admin?, #aka, #aka=, #all_activities, #blog_admin?, #broadcast_product_interest_changed, #can_be_certified?, #can_list_all_contact_resources?, #clear_individual_names, #clear_names, #contact?, #customer?, #determine_company_id, #direct_commercial?, #direct_pro?, #employee?, #first_name, #first_name=, #guest_individual_name?, #guest_name?, #homeowner?, #id_and_name, #last_name, #last_name=, #manager?, #middle_name, #middle_name=, #name, #name=, #organization?, #person?, #primary_party, #public_facing_full_name, #public_facing_full_name=, #show_name_four, #to_s, #update_product_interests
Methods included from PartyAddresses
#addresses_options_for_select, #can_change_country?, #catalog_country, #catalog_country_iso, #catalog_country_iso3, #city, #country, #country_iso, #country_iso3, #first_address, #flag, #location_name, #most_recent_visit, #new_address, #street1, #street2, #street3, #timezone, #unique_addresses, #visit_data, #visit_location, #zip
Methods included from PartyContactInfo
#all_support_cases, #call_records?, #cell_phone, #cell_phone=, #cell_phone_formatted, #contact_point_options_for_select, #contactable?, #email, #email=, #email_options_for_select, #email_with_name, #emails, #enrichable_via_research?, #fax, #fax=, #fax_formatted, #fax_options_for_select, #first_callable_contact_point, #first_contact_point_by_category, #phone, #phone=, #phone_formatted, #phone_options_for_select, #research_location, #set_email_from_account, #set_primary_contact_point, #sms_enabled_numbers, #sms_messages, #tracking_email_address, #tracking_email_prefix, #website, #website=, #website_options_for_select
Methods included from PartySearch
active, address_search, customer_or_contact, email_search, inactive, lookup, phone_search, ransackable_scopes, searchable, with_main_address
Methods included from Models::Notable
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
#creation_method ⇒ Object (readonly)
The pre-Rails-7 normalizr config had normalize :profile, ... — a typo
that targeted no real column (Party has profile_id and profile_info,
not profile) and was a silent no-op. Under Rails native normalizes
it became harmful: registering on :profile creates a real virtual
attribute that collides with the belongs_to :profile setter and gets
nullified during attributes= mass-assignment, wiping profile_id.
profile_info is a free-text Bio field, not a hash, so the original
[strip, blank, hash_compactor] chain would also corrupt its value.
Drop the normalize entirely.
Validations:
- Inclusion ({ in: creation_methods.keys })
315 |
# File 'app/models/party.rb', line 315 validates :creation_method, inclusion: { in: creation_methods.keys } |
Instance Method Details
#account ⇒ Account
NOTE: this is a documentation-only association used as a convenience
accessor. Use accounts (has_many below) for collection access. We keep
dependent: :destroy so that destroying a party still cleans up its sole
account row; the truly dangerous primitive (auto-destroying an existing
account when assigning a new one) is intercepted by the build_account
override below.
242 |
# File 'app/models/party.rb', line 242 has_one :account, dependent: :destroy |
#accounts ⇒ ActiveRecord::Relation<Account>
250 |
# File 'app/models/party.rb', line 250 has_many :accounts, dependent: :destroy |
#activities ⇒ ActiveRecord::Relation<Activity>
rubocop:enable Rails/InverseOf
254 |
# File 'app/models/party.rb', line 254 has_many :activities, dependent: :destroy |
#addresses ⇒ ActiveRecord::Relation<Address>
243 244 245 246 247 248 249 |
# File 'app/models/party.rb', line 243 has_many :addresses, dependent: :nullify, inverse_of: :party do def main_address find_by(id: [proxy_association.owner.mailing_address_id, proxy_association.owner.billing_address_id, proxy_association.owner.shipping_address_id]) || first end end |
#agreement_participants ⇒ ActiveRecord::Relation<AgreementParticipant>
285 |
# File 'app/models/party.rb', line 285 has_many :agreement_participants, dependent: :destroy |
#agreements ⇒ ActiveRecord::Relation<Agreement>
286 |
# File 'app/models/party.rb', line 286 has_many :agreements, through: :agreement_participants |
#assistant_conversations ⇒ ActiveRecord::Relation<AssistantConversation>
291 |
# File 'app/models/party.rb', line 291 has_many :assistant_conversations, foreign_key: :user_id, dependent: :destroy, inverse_of: :user |
#billing_credit_memos ⇒ ActiveRecord::Relation<CreditMemo>
274 275 |
# File 'app/models/party.rb', line 274 has_many :billing_credit_memos, class_name: 'CreditMemo', foreign_key: 'billing_customer_id', dependent: :nullify, inverse_of: :billing_customer |
#can? ⇒ Object
Alias for Ability#can?
300 |
# File 'app/models/party.rb', line 300 delegate :can?, :cannot?, to: :ability |
#cannot? ⇒ Object
Alias for Ability#cannot?
300 |
# File 'app/models/party.rb', line 300 delegate :can?, :cannot?, to: :ability |
#company ⇒ Company
Validations:
230 |
# File 'app/models/party.rb', line 230 belongs_to :company, optional: true |
#consignment_stores ⇒ ActiveRecord::Relation<Store>
261 |
# File 'app/models/party.rb', line 261 has_many :consignment_stores, class_name: 'Store', foreign_key: :consignee_party_id, dependent: :nullify, inverse_of: :consignee_party |
#contact_points ⇒ ActiveRecord::Relation<ContactPoint>
-- Contact shares customer_id FK with supplier; see Contact model
251 |
# File 'app/models/party.rb', line 251 has_many :contact_points, -> { order(:position) }, dependent: :nullify, inverse_of: :party |
#contacts ⇒ ActiveRecord::Relation<Contact>
Validations (if => #must_have_one_contact ):
252 |
# File 'app/models/party.rb', line 252 has_many :contacts, foreign_key: 'customer_id', dependent: :destroy |
#course_enrollments ⇒ ActiveRecord::Relation<CourseEnrollment>
282 |
# File 'app/models/party.rb', line 282 has_many :course_enrollments, dependent: :destroy, inverse_of: :party |
#credit_memos ⇒ ActiveRecord::Relation<CreditMemo>
owner of the credit memo
273 |
# File 'app/models/party.rb', line 273 has_many :credit_memos, foreign_key: 'customer_id', dependent: :nullify, inverse_of: :customer |
#customer ⇒ Customer
WHEN CREATING A NEW ASSOCIATION FOR YOUR PARTY, CUSTOMER OR CONTACT
DO NOT FORGET TO HANDLE THEM IN MERGE OPERATIONS
IMPLEMENT THIS IN customer_merger.rb or contact_merger.rb
228 |
# File 'app/models/party.rb', line 228 belongs_to :customer, optional: true |
#destination_call_logs ⇒ ActiveRecord::Relation<CallLog>
259 |
# File 'app/models/party.rb', line 259 has_many :destination_call_logs, class_name: 'CallLog', foreign_key: 'to_party_id', dependent: :nullify, inverse_of: :to_party |
#destination_call_records ⇒ ActiveRecord::Relation<CallRecord>
256 257 |
# File 'app/models/party.rb', line 256 has_many :destination_call_records, class_name: 'CallRecord', foreign_key: 'destination_party_id', dependent: :nullify, inverse_of: :destination_party |
#digital_assets ⇒ ActiveRecord::Relation<DigitalAsset>
297 |
# File 'app/models/party.rb', line 297 has_and_belongs_to_many :digital_assets |
#gl_offset_account ⇒ LedgerAccount
232 |
# File 'app/models/party.rb', line 232 belongs_to :gl_offset_account, class_name: 'LedgerAccount', optional: true |
#has_role? ⇒ Object
Alias for Account#has_role?
301 |
# File 'app/models/party.rb', line 301 delegate :has_role?, :is_admin?, :is_manager?, :is_sales_manager?, :is_sales_rep?, :is_local_sales_rep?, :is_marketing_manager?, :is_document_maintainer?, to: :account |
#inbound_communications ⇒ ActiveRecord::Relation<Communication>
265 266 |
# File 'app/models/party.rb', line 265 has_many :inbound_communications, class_name: 'Communication', foreign_key: 'recipient_party_id', dependent: :nullify, inverse_of: :recipient_party |
#is_admin? ⇒ Object
Alias for Account#is_admin?
301 |
# File 'app/models/party.rb', line 301 delegate :has_role?, :is_admin?, :is_manager?, :is_sales_manager?, :is_sales_rep?, :is_local_sales_rep?, :is_marketing_manager?, :is_document_maintainer?, to: :account |
#is_document_maintainer? ⇒ Object
Alias for Account#is_document_maintainer?
301 |
# File 'app/models/party.rb', line 301 delegate :has_role?, :is_admin?, :is_manager?, :is_sales_manager?, :is_sales_rep?, :is_local_sales_rep?, :is_marketing_manager?, :is_document_maintainer?, to: :account |
#is_local_sales_rep? ⇒ Object
Alias for Account#is_local_sales_rep?
301 |
# File 'app/models/party.rb', line 301 delegate :has_role?, :is_admin?, :is_manager?, :is_sales_manager?, :is_sales_rep?, :is_local_sales_rep?, :is_marketing_manager?, :is_document_maintainer?, to: :account |
#is_manager? ⇒ Object
Alias for Account#is_manager?
301 |
# File 'app/models/party.rb', line 301 delegate :has_role?, :is_admin?, :is_manager?, :is_sales_manager?, :is_sales_rep?, :is_local_sales_rep?, :is_marketing_manager?, :is_document_maintainer?, to: :account |
#is_marketing_manager? ⇒ Object
Alias for Account#is_marketing_manager?
301 |
# File 'app/models/party.rb', line 301 delegate :has_role?, :is_admin?, :is_manager?, :is_sales_manager?, :is_sales_rep?, :is_local_sales_rep?, :is_marketing_manager?, :is_document_maintainer?, to: :account |
#is_sales_manager? ⇒ Object
Alias for Account#is_sales_manager?
301 |
# File 'app/models/party.rb', line 301 delegate :has_role?, :is_admin?, :is_manager?, :is_sales_manager?, :is_sales_rep?, :is_local_sales_rep?, :is_marketing_manager?, :is_document_maintainer?, to: :account |
#is_sales_rep? ⇒ Object
Alias for Account#is_sales_rep?
301 |
# File 'app/models/party.rb', line 301 delegate :has_role?, :is_admin?, :is_manager?, :is_sales_manager?, :is_sales_rep?, :is_local_sales_rep?, :is_marketing_manager?, :is_document_maintainer?, to: :account |
#linked_activities ⇒ ActiveRecord::Relation<Activity>
296 |
# File 'app/models/party.rb', line 296 has_and_belongs_to_many :linked_activities, class_name: 'Activity' |
#locale ⇒ Object
Alias for I18n#locale
330 |
# File 'app/models/party.rb', line 330 delegate :locale, to: :I18n |
#main_address ⇒ Object
Alias for Addresses#main_address
302 |
# File 'app/models/party.rb', line 302 delegate :main_address, to: :addresses |
#notifications ⇒ ActiveRecord::Relation<Noticed::Notification>
292 |
# File 'app/models/party.rb', line 292 has_many :notifications, as: :recipient, dependent: :destroy, class_name: 'Noticed::Notification' |
#opportunity_participants ⇒ ActiveRecord::Relation<OpportunityParticipant>
280 |
# File 'app/models/party.rb', line 280 has_many :opportunity_participants, inverse_of: :party, dependent: :destroy |
#origin_call_logs ⇒ ActiveRecord::Relation<CallLog>
258 |
# File 'app/models/party.rb', line 258 has_many :origin_call_logs, class_name: 'CallLog', foreign_key: 'from_party_id', dependent: :nullify, inverse_of: :from_party |
#origin_call_records ⇒ ActiveRecord::Relation<CallRecord>
255 |
# File 'app/models/party.rb', line 255 has_many :origin_call_records, class_name: 'CallRecord', foreign_key: 'origin_party_id', dependent: :nullify, inverse_of: :origin_party |
#outbound_communications ⇒ ActiveRecord::Relation<Communication>
263 264 |
# File 'app/models/party.rb', line 263 has_many :outbound_communications, class_name: 'Communication', foreign_key: 'sender_party_id', dependent: :nullify, inverse_of: :sender_party |
#outgoing_payments ⇒ ActiveRecord::Relation<OutgoingPayment>
269 |
# File 'app/models/party.rb', line 269 has_many :outgoing_payments, foreign_key: 'supplier_id', dependent: :nullify, inverse_of: :supplier |
#party_topics ⇒ ActiveRecord::Relation<PartyTopic>
277 |
# File 'app/models/party.rb', line 277 has_many :party_topics, inverse_of: :party, dependent: :destroy |
#product_lines ⇒ ActiveRecord::Relation<ProductLine>
-- legacy join tables; migrating to has_many :through is a separate effort
295 |
# File 'app/models/party.rb', line 295 has_and_belongs_to_many :product_lines |
#profile_image ⇒ Image
233 |
# File 'app/models/party.rb', line 233 belongs_to :profile_image, class_name: 'Image', dependent: :destroy, optional: true |
#purchase_orders ⇒ ActiveRecord::Relation<PurchaseOrder>
276 |
# File 'app/models/party.rb', line 276 has_many :purchase_orders, foreign_key: :supplier_id, dependent: :nullify, inverse_of: :supplier |
#queue_call_logs ⇒ ActiveRecord::Relation<QueueCallLog>
260 |
# File 'app/models/party.rb', line 260 has_many :queue_call_logs, class_name: 'QueueCallLog', foreign_key: 'caller_party_id', dependent: :nullify, inverse_of: :caller_party |
#receipts ⇒ ActiveRecord::Relation<Receipt>
271 |
# File 'app/models/party.rb', line 271 has_many :receipts, foreign_key: 'customer_id', dependent: :nullify, inverse_of: :customer |
#recipient_sms_messages ⇒ ActiveRecord::Relation<SmsMessage>
289 290 |
# File 'app/models/party.rb', line 289 has_many :recipient_sms_messages, class_name: 'SmsMessage', foreign_key: :recipient_party_id, dependent: :nullify, inverse_of: :recipient_party |
#room_plans ⇒ ActiveRecord::Relation<RoomPlan>
281 |
# File 'app/models/party.rb', line 281 has_many :room_plans, inverse_of: :party, dependent: :destroy |
#sender_sms_messages ⇒ ActiveRecord::Relation<SmsMessage>
287 288 |
# File 'app/models/party.rb', line 287 has_many :sender_sms_messages, class_name: 'SmsMessage', foreign_key: :sender_party_id, dependent: :nullify, inverse_of: :sender_party |
#set_full_name ⇒ Object (protected)
Before-save callback: rebuild the denormalised full_name column
from the party-type-specific name fields (first/last for people,
company name for organizations). Preserves any externally-supplied
value if PartyIdentity#apply_full_name_for_party_type! couldn't compose one.
357 358 359 360 361 |
# File 'app/models/party.rb', line 357 protected def set_full_name existing_full_name = full_name apply_full_name_for_party_type!(existing_full_name) self.full_name ||= existing_full_name end |
#set_state_code ⇒ Object (protected)
Validation/before-save callback that pins state_code to the main
address's state_code, falling back to whatever Cloudflare visit
data was captured at landing time. Letting the column denormalise
state means CRM searches and reports can filter by state without
joining addresses.
337 338 339 340 |
# File 'app/models/party.rb', line 337 protected def set_state_code self.state_code = main_address&.state_code self.state_code ||= visit_data(:state_code) end |
#set_timezone ⇒ Object (protected)
Before-save callback: lazily resolve and persist the party's IANA
timezone once we have enough info to do so. Skipped for guests
(cart-only sessions) and any party that already has a timezone
set, so we don't re-run the geocode lookup on every save.
346 347 348 349 350 351 |
# File 'app/models/party.rb', line 346 protected def set_timezone return if timezone_name.present? return if state == 'guest' # Ignore guests PartyRecordTimezone.new.process(self, save_directly: true) end |
#support_case_participants ⇒ ActiveRecord::Relation<SupportCaseParticipant>
267 |
# File 'app/models/party.rb', line 267 has_many :support_case_participants, dependent: :destroy |
#support_cases ⇒ ActiveRecord::Relation<SupportCase>
268 |
# File 'app/models/party.rb', line 268 has_many :support_cases, through: :support_case_participants |
#survey_enrollments ⇒ ActiveRecord::Relation<SurveyEnrollment>
283 |
# File 'app/models/party.rb', line 283 has_many :survey_enrollments, dependent: :destroy, inverse_of: :party |
#uploads ⇒ ActiveRecord::Relation<Upload>
284 |
# File 'app/models/party.rb', line 284 has_many :uploads, as: :resource, dependent: :destroy |
#visit ⇒ Visit
231 |
# File 'app/models/party.rb', line 231 belongs_to :visit, inverse_of: :party, optional: true |
#visit_events ⇒ ActiveRecord::Relation<VisitEvent>
279 |
# File 'app/models/party.rb', line 279 has_many :visit_events, through: :visits |
#visits ⇒ ActiveRecord::Relation<Visit>
278 |
# File 'app/models/party.rb', line 278 has_many :visits, foreign_key: :user_id, dependent: :nullify, inverse_of: :user |
#voucher_items ⇒ ActiveRecord::Relation<VoucherItem>
272 |
# File 'app/models/party.rb', line 272 has_many :voucher_items, through: :vouchers |
#vouchers ⇒ ActiveRecord::Relation<Voucher>
270 |
# File 'app/models/party.rb', line 270 has_many :vouchers, foreign_key: 'supplier_id', dependent: :nullify, inverse_of: :supplier |