Class: Twinfield::Customer

Inherits:
AbstractModel show all
Extended by:
Helpers::Parsers
Defined in:
lib/twinfield/customer.rb

Defined Under Namespace

Classes: Address, Bank, CollectMandate, CreditManagement, Financials, RemittanceAdvice

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers::Parsers

parse_date, parse_datetime, parse_float

Constructor Details

#initialize(office: nil, code: nil, uid: nil, name: nil, shortname: nil, inuse: nil, behaviour: nil, modified: nil, touched: nil, beginperiod: nil, beginyear: nil, endperiod: nil, endyear: nil, website: nil, cocnumber: nil, vatnumber: nil, financials: nil, creditmanagement: nil, remittanceadvice: nil, addresses: nil, banks: nil, status: :active) ⇒ Customer

Returns a new instance of Customer.



426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
# File 'lib/twinfield/customer.rb', line 426

def initialize(office: nil, code: nil, uid: nil, name: nil, shortname: nil, inuse: nil, behaviour: nil, modified: nil, touched: nil, beginperiod: nil, beginyear: nil, endperiod: nil, endyear: nil, website: nil, cocnumber: nil, vatnumber: nil, financials: nil, creditmanagement: nil, remittanceadvice: nil, addresses: nil, banks: nil, status: :active)
  @office = office || Twinfield.configuration.company
  @status = status
  @code = code
  @uid = uid
  @name = name
  @shortname = shortname
  @inuse = inuse
  @behaviour = behaviour
  @modified = modified
  @touched = touched
  @beginperiod = beginperiod
  @beginyear = beginyear
  @endperiod = endperiod
  @endyear = endyear
  @website = website
  @cocnumber = cocnumber
  @vatnumber = vatnumber
  @financials = financials.is_a?(Hash) ? Financials.new(**financials) : financials
  @creditmanagement = creditmanagement.is_a?(Hash) ? CreditManagement.new(**creditmanagement) : creditmanagement
  @remittanceadvice = remittanceadvice.is_a?(Hash) ? RemittanceAdvice.new(**remittanceadvice) : remittanceadvice
  @addresses = (addresses || []).map { |a| a.is_a?(Hash) ? Address.new(**a) : a }
  @banks = (banks || []).map { |a| a.is_a?(Hash) ? Bank.new(**a) : a }
end

Instance Attribute Details

#addressesObject

Returns the value of attribute addresses.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def addresses
  @addresses
end

#banksObject

Returns the value of attribute banks.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def banks
  @banks
end

#beginperiodObject

Returns the value of attribute beginperiod.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def beginperiod
  @beginperiod
end

#beginyearObject

Returns the value of attribute beginyear.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def beginyear
  @beginyear
end

#behaviourObject

Returns the value of attribute behaviour.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def behaviour
  @behaviour
end

#cocnumberObject

Returns the value of attribute cocnumber.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def cocnumber
  @cocnumber
end

#codeObject

Returns the value of attribute code.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def code
  @code
end

#creditmanagementObject

Returns the value of attribute creditmanagement.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def creditmanagement
  @creditmanagement
end

#endperiodObject

Returns the value of attribute endperiod.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def endperiod
  @endperiod
end

#endyearObject

Returns the value of attribute endyear.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def endyear
  @endyear
end

#financialsObject

Returns the value of attribute financials.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def financials
  @financials
end

#inuseObject

Returns the value of attribute inuse.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def inuse
  @inuse
end

#modifiedObject

Returns the value of attribute modified.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def modified
  @modified
end

#nameObject

Returns the value of attribute name.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def name
  @name
end

#officeObject

Returns the value of attribute office.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def office
  @office
end

#remittanceadviceObject

Returns the value of attribute remittanceadvice.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def remittanceadvice
  @remittanceadvice
end

#shortnameObject

Returns the value of attribute shortname.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def shortname
  @shortname
end

#statusObject

Returns the value of attribute status.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def status
  @status
end

#touchedObject

Returns the value of attribute touched.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def touched
  @touched
end

#uidObject

Returns the value of attribute uid.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def uid
  @uid
end

#vatnumberObject

Returns the value of attribute vatnumber.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def vatnumber
  @vatnumber
end

#websiteObject

Returns the value of attribute website.



424
425
426
# File 'lib/twinfield/customer.rb', line 424

def website
  @website
end

Class Method Details

.allObject



539
540
541
# File 'lib/twinfield/customer.rb', line 539

def all
  search
end

.find(customercode) ⇒ Object



574
575
576
577
578
# File 'lib/twinfield/customer.rb', line 574

def find(customercode)
  options = {office: Twinfield.configuration.company, code: customercode, dimtype: "DEB"}
  customer_xml = Twinfield::Api::Process.read(:dimensions, options)
  from_xml(customer_xml)
end

.from_xml(nokogiri_or_string) ⇒ Object



580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
# File 'lib/twinfield/customer.rb', line 580

def from_xml(nokogiri_or_string)
  nokogiri = nokogiri_or_string.is_a?(Nokogiri::XML::Document) ? nokogiri_or_string : Nokogiri::XML(nokogiri_or_string)
  dimension = nokogiri.css("dimension")[0]

  if dimension.attributes["result"]&.text == "0"
    return nil
  end

  obj = new(shortname: nokogiri.css("dimension > shortname").text, name: nokogiri.css("dimension > name").text, code: nokogiri.css("dimension > code").text)
  obj.status = dimension.attributes["status"].text
  obj.office = nokogiri.css("dimension > office").text
  obj.uid = nokogiri.css("dimension > uid").text
  obj.inuse = nokogiri.css("dimension > inuse").text
  obj.behaviour = nokogiri.css("dimension > behaviour").text
  obj.modified = parse_datetime(nokogiri.css("dimension > modified").text)
  obj.touched = nokogiri.css("dimension > touched").text
  obj.beginperiod = nokogiri.css("dimension > beginperiod").text
  obj.beginyear = nokogiri.css("dimension > beginyear").text
  obj.endperiod = nokogiri.css("dimension > endperiod").text
  obj.endyear = nokogiri.css("dimension > endyear").text
  obj.website = nokogiri.css("dimension > website").text
  obj.cocnumber = nokogiri.css("dimension > cocnumber").text
  obj.vatnumber = nokogiri.css("dimension > vatnumber").text
  obj.financials = Financials.from_xml(nokogiri.css("dimension > financials")[0])
  obj.creditmanagement = CreditManagement.from_xml(nokogiri.css("dimension > creditmanagement")[0]) if nokogiri.css("dimension > creditmanagement")[0]
  obj.remittanceadvice = RemittanceAdvice.from_xml(nokogiri.css("dimension > remittanceadvice")[0]) if nokogiri.css("dimension > remittanceadvice")[0]
  obj.addresses = nokogiri.css("dimension > addresses > address").map { |xml_fragment| Address.from_xml(xml_fragment) }
  obj.banks = nokogiri.css("dimension > banks > bank").map { |xml_fragment| Bank.from_xml(xml_fragment) }
  obj
end

.next_unused_twinfield_customer_code(range = nil) ⇒ Object

helper method that calculates the next unused code

Returns:

  • String



545
546
547
548
549
550
551
552
# File 'lib/twinfield/customer.rb', line 545

def next_unused_twinfield_customer_code range = nil
  current_codes = Twinfield::Customer.all.map(&:code).map(&:to_i).sort
  current_codes_in_range = current_codes & range.to_a if range
  latest = (current_codes_in_range || current_codes).last
  latest = latest ? latest + 1 : range.to_a.first
  raise "invalid new customer code" if latest == 1
  latest.to_s
end

.search(text = "*") ⇒ Object



554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
# File 'lib/twinfield/customer.rb', line 554

def search text = "*"
  text = "*#{text}*" unless text.match?(/[?*]/)
  options = {
    dimtype: "DEB",
    office: Twinfield.configuration.company,
    pattern: text,
    max_rows: 10000
  }
  response = Twinfield::Api::Finder.request("DIM", options)
  if response.body[:search_response][:data][:total_rows].to_i == 1
    resp = response.body[:search_response][:data][:items][:array_of_string][:string]
    [Customer.new(name: resp[1], code: resp[0])]
  elsif response.body[:search_response][:data][:total_rows].to_i > 1
    response.body[:search_response][:data][:items][:array_of_string]
      .map { |item| Customer.new(name: item[:string][1], code: item[:string][0]) }
  else
    []
  end
end

Instance Method Details

#destroyObject Also known as: delete



523
524
525
526
# File 'lib/twinfield/customer.rb', line 523

def destroy
  self.status = :deleted
  save
end

#loadObject



533
534
535
# File 'lib/twinfield/customer.rb', line 533

def load
  Customer.find(code)
end

#saveObject



511
512
513
514
515
516
517
518
519
520
521
# File 'lib/twinfield/customer.rb', line 511

def save
  response = Twinfield::Api::Process.request { to_xml }

  xml = Nokogiri::XML(response.body[:process_xml_string_response][:process_xml_string_result])

  if xml.at_css("dimension").attributes["result"].value == "1"
    self.class.from_xml(xml)
  else
    raise Twinfield::Create::Error.new(xml.css("[msg]").map { |x| x.attributes["msg"].value }.join(" "), object: self)
  end
end

#to_hObject Also known as: to_hash



451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
# File 'lib/twinfield/customer.rb', line 451

def to_h
  {
    office: office,
    code: code,
    uid: uid,
    name: name,
    shortname: shortname,
    inuse: inuse,
    behaviour: behaviour,
    modified: modified,
    touched: touched,
    beginperiod: beginperiod,
    beginyear: beginyear,
    endperiod: endperiod,
    endyear: endyear,
    website: website,
    cocnumber: cocnumber,
    vatnumber: vatnumber,
    financials: financials.to_h,
    creditmanagement: creditmanagement.to_h,
    remittanceadvice: remittanceadvice.to_h,
    addresses: addresses.map(&:to_h),
    banks: banks.map(&:to_h),
    status: status
  }
end

#to_xmlObject



479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
# File 'lib/twinfield/customer.rb', line 479

def to_xml
  Nokogiri::XML::Builder.new do |xml|
    xml.dimension(status: status) do
      xml.office office
      xml.type "DEB"
      xml.code code
      xml.uid uid if uid
      xml.name name
      xml.shortname shortname
      # xml.behaviour behaviour #temporarily disable
      xml.beginperiod beginperiod if beginperiod
      xml.beginyear beginyear if beginyear
      xml.endperiod endperiod if endperiod
      xml.endyear endyear if endyear
      xml.website website
      xml << financials&.to_xml
      xml << creditmanagement&.to_xml if creditmanagement&.present?
      xml << remittanceadvice&.to_xml
      xml.addresses do
        addresses.each do |line|
          xml << line.to_xml
        end
      end
      xml.banks do
        banks.each do |line|
          xml << line.to_xml
        end
      end
    end
  end.doc.root.to_xml
end

#transactions(filter_hash = {}) ⇒ Object



529
530
531
# File 'lib/twinfield/customer.rb', line 529

def transactions(filter_hash = {})
  Twinfield::Browse::Transaction::Customer.where(customer_code: code, **filter_hash)
end