Class: Bisac::POA

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/bisac/poa.rb

Overview

Represents a single BISAC purchase order acknowledgement

Generating

It’s currently not possible to generate a POA with this class. All it needs is a to_s method though, much like Bisac::PO. Patches welcome.

Reading

Each POA file can contain multiple POA’s, so use pasrse_file() to iterate over them all.

Bisac::POA.parse_file("filename.bsc") do |msg|
  puts msg.source_san
  puts msg.source_name
  puts msg.items.size
  ...
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePOA

creates a new Bisac::POA object



39
40
41
# File 'lib/bisac/poa.rb', line 39

def initialize
  @items = []
end

Instance Attribute Details

#ack_typeObject

Returns the value of attribute ack_type.



28
29
30
# File 'lib/bisac/poa.rb', line 28

def ack_type
  @ack_type
end

#currencyObject

Returns the value of attribute currency.



34
35
36
# File 'lib/bisac/poa.rb', line 34

def currency
  @currency
end

#customer_sanObject

Returns the value of attribute customer_san.



32
33
34
# File 'lib/bisac/poa.rb', line 32

def customer_san
  @customer_san
end

#customer_suffixObject

Returns the value of attribute customer_suffix.



32
33
34
# File 'lib/bisac/poa.rb', line 32

def customer_suffix
  @customer_suffix
end

#dateObject

Returns the value of attribute date.



26
27
28
# File 'lib/bisac/poa.rb', line 26

def date
  @date
end

#destination_sanObject

Returns the value of attribute destination_san.



27
28
29
# File 'lib/bisac/poa.rb', line 27

def destination_san
  @destination_san
end

#destination_suffixObject

Returns the value of attribute destination_suffix.



27
28
29
# File 'lib/bisac/poa.rb', line 27

def destination_suffix
  @destination_suffix
end

#filenameObject

Returns the value of attribute filename.



26
27
28
# File 'lib/bisac/poa.rb', line 26

def filename
  @filename
end

#format_versionObject

Returns the value of attribute format_version.



26
27
28
# File 'lib/bisac/poa.rb', line 26

def format_version
  @format_version
end

#itemsObject

Returns the value of attribute items.



36
37
38
# File 'lib/bisac/poa.rb', line 36

def items
  @items
end

#po_cancel_dateObject

Returns the value of attribute po_cancel_date.



35
36
37
# File 'lib/bisac/poa.rb', line 35

def po_cancel_date
  @po_cancel_date
end

#po_dateObject

Returns the value of attribute po_date.



34
35
36
# File 'lib/bisac/poa.rb', line 34

def po_date
  @po_date
end

#po_numberObject

poa header attributes



31
32
33
# File 'lib/bisac/poa.rb', line 31

def po_number
  @po_number
end

#po_typeObject

Returns the value of attribute po_type.



35
36
37
# File 'lib/bisac/poa.rb', line 35

def po_type
  @po_type
end

#poa_dateObject

Returns the value of attribute poa_date.



34
35
36
# File 'lib/bisac/poa.rb', line 34

def poa_date
  @poa_date
end

#source_nameObject

file header attributes



25
26
27
# File 'lib/bisac/poa.rb', line 25

def source_name
  @source_name
end

#source_sanObject

file header attributes



25
26
27
# File 'lib/bisac/poa.rb', line 25

def source_san
  @source_san
end

#source_suffixObject

file header attributes



25
26
27
# File 'lib/bisac/poa.rb', line 25

def source_suffix
  @source_suffix
end

#supplier_poa_numberObject

poa header attributes



31
32
33
# File 'lib/bisac/poa.rb', line 31

def supplier_poa_number
  @supplier_poa_number
end

#supplier_sanObject

Returns the value of attribute supplier_san.



33
34
35
# File 'lib/bisac/poa.rb', line 33

def supplier_san
  @supplier_san
end

#supplier_suffixObject

Returns the value of attribute supplier_suffix.



33
34
35
# File 'lib/bisac/poa.rb', line 33

def supplier_suffix
  @supplier_suffix
end

Class Method Details

.parse_file(input, &block) ⇒ Object

return all POAs from a BISAC file

Raises:

  • (ArgumentError)


44
45
46
47
48
49
50
# File 'lib/bisac/poa.rb', line 44

def self.parse_file(input, &block)
  raise ArgumentError, 'no file provided' if input.nil?
  raise ArgumentError, 'Invalid file' unless File.file?(input)
  self.parse_string(File.read(input)) do |msg|
    yield msg
  end
end

.parse_string(input, &block) ⇒ Object

return all POAs from a BISAC string

Raises:

  • (ArgumentError)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/bisac/poa.rb', line 53

def self.parse_string(input, &block)
  raise ArgumentError, 'no data provided' if input.nil?
  data = []
  input.split("\n").each do |l|
    data << l

    # yield each message found in the string. A line starting with
    # 91 is the footer to a POA
    if data.last[0,2] == "91"
      msg = Bisac::POA.new
      msg.build_message(data)
      yield msg
      data = []
    end
  end

  # if we've got to the end of the file, and haven't hit a footer line yet, the file
  # is probably malformed. Call build_message anyway, and let it detect any errors
  if data.size > 0
    msg = Bisac::POA.new
    msg.build_message(data)
    yield msg
  end
end

Instance Method Details

#build_message(data) ⇒ Object

Populate the current object with the message contained in data

An array of lines making a complete, single POA message



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/bisac/poa.rb', line 167

def build_message(data)
  raise Bisac::InvalidFileError, 'File appears to be too short' unless data.size >= 3
  raise Bisac::InvalidFileError, 'Missing header information' unless data[0][0,2].eql?("02")
  raise Bisac::InvalidFileError, 'Missing footer information' unless data[-1][0,2].eql?("91")

  data.each do |line|
    # ensure each line is at least 80 chars long
    line = line.ljust(80)

    case line[0,2]
    when "02" # file header
      self.source_san = line[7,7].strip
      self.source_suffix = line[14,5].strip
      self.source_name = line[19,13].strip
      self.date = line[32,6].strip
      self.filename = line[38,22].strip
      self.format_version = line[60,3].strip
      self.destination_san = line[63,7].strip
      self.destination_suffix = line[70,5].strip
      self.ack_type = line[75,1].strip
    when "11" # poa header
      self.supplier_poa_number = line[7,13].strip
      self.po_number = line[20,13].strip
      self.customer_san = line[33,7].strip
      self.customer_suffix = line[40,5].strip
      self.supplier_san = line[45,7].strip
      self.supplier_suffix = line[52,5].strip
      self.poa_date = line[57,6].strip
      self.currency = line[63,3].strip
      self.po_date  = line[66,6].strip
      self.po_cancel_date = line[72,6].strip
      self.po_type = line[78,2].strip
    when "40" # line item
      item = Bisac::POALineItem.load_from_string(line)
      self.items << item
    when "41"
    when "42"
    when "59" # poa footer
      # check the built objects match the file
    when "91" # file footer
      # check the built objects match the file
    end

  end

  self
end

#to_sObject

convert this POA into a standards compliant string, ready for sending to customers.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/bisac/poa.rb', line 93

def to_s
  lines = []

  # file header
  line = " " * 80
  line[0,2]   = "02" # line type
  line[2,5]   = "00001"  # line counter
  line[7,7]   = pad_trunc(@source_san, 7)
  line[14,5]  = pad_trunc(@source_suffix, 5)
  line[19,13] = pad_trunc(@source_name, 13)
  line[32,6]  = pad_trunc(@date, 6)
  line[38,22] = pad_trunc(@filename, 22)
  line[60,3]  = pad_trunc(@format_version, 3)
  line[63,7]  = pad_trunc(@destination_san, 7)
  line[70,5]  = pad_trunc(@destination_suffix, 5)
  line[75,1]  = pad_trunc(@ack_type, 1)
  lines << line

  # po header
  line = " " * 80
  line[0,2]    = "11" # line type
  line[2,5]    = "00002"  # line counter
  line[7,13]   = pad_trunc(@supplier_poa_number, 13)
  line[20,13]  = pad_trunc(@po_number, 13)
  line[33,7]   = pad_trunc(@customer_san, 7)
  line[40,5]   = pad_trunc(@customer_suffice, 5)
  line[45,7]   = pad_trunc(@supplier_san, 7)
  line[52,5]   = pad_trunc(@supplier_suffice, 5)
  line[57,6]   = pad_trunc(@poa_date, 6)
  line[63,3]   = pad_trunc(@currency, 3)
  line[66,6]   = pad_trunc(@po_date, 6)
  line[72,6]   = pad_trunc(@po_cancel_date, 6)
  line[78,2]   = pad_trunc(@po_type, 2)
  lines << line

  @items.each_with_index do |item, idx|
    item.line_item_number = idx + 1
    item.sequence_number  = lines.size + 1
    lines << item.to_s
  end

  # POA control
  line = " " * 80
  line[0,2]   = "59"
  line[2,5]   = (lines.size + 1).to_s.rjust(5,"0")  # line counter
  line[7,13]  = pad_trunc(@supplier_poa_number, 13)
  line[20,5]  = (lines.size).to_s.rjust(5,"0") # number of lines to this point
  line[25,10] = (lines.size - 2).to_s.rjust(10,"0") # number of line items in file
  line[35,10] = total_shippable_qty.to_s.rjust(10,"0")
  lines << line

  # file trailer
  line = " " * 80
  line[0,2]   = "91"
  line[2,5]   = (lines.size+1).to_s.rjust(5,"0")  # line counter
  line[7,20]  = @items.size.to_s.rjust(13,"0")
  line[20,5]  = "00001" # total '11' (POA) records
  line[25,10] = total_shippable_qty.to_s.rjust(10,"0")
  line[35,5]  = "00001" # number of '00'-'09' records
  line[40,5]  = "00001" # number of '10'-'19' records
  line[45,5]  = "00000" # number of '20'-'29' records
  line[50,5]  = "00000" # number of '30'-'39' records
  line[55,5]  = (@items.size).to_s.rjust(5,"0") # number of '40'-'49' records
  line[60,5]  = "00001" # number of '50'-'59' records
  line[65,5]  = "00001" # number of '60'-'99' records
  lines << line

  lines.join("\n")
end

#total_order_qtyObject

total number of units ordered by the customer



80
81
82
# File 'lib/bisac/poa.rb', line 80

def total_order_qty
  @items.collect { |i| i.order_qty }.inject { |sum, x| sum ? sum+x : x}
end

#total_shippable_qtyObject

total number of units to ship



86
87
88
# File 'lib/bisac/poa.rb', line 86

def total_shippable_qty
  @items.collect { |i| i.shippable_qty }.inject { |sum, x| sum ? sum+x : x}
end