Class: Bisac::PO

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

Overview

Represents a single BISAC purchase order.

Generating

po = Bisac::PO.new
po.source_san = "1111111"
po.source_name = "James"
...
item = Bisac::POLineItem.new
item.isbn = "0385519869"
item.qty = 2
po.items << item
puts po.to_s

Reading

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

Bisac::PO.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

#initializePO

creates a new Bisac::PO object



41
42
43
44
45
46
47
48
# File 'lib/bisac/po.rb', line 41

def initialize
  @items = []

  # default values
  @cancellation_date = "000000"
  @do_not_ship_before = "000000"
  @backorder = true
end

Instance Attribute Details

#backorderObject

Returns the value of attribute backorder.



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

def backorder
  @backorder
end

#cancellation_dateObject

Returns the value of attribute cancellation_date.



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

def cancellation_date
  @cancellation_date
end

#dateObject

Returns the value of attribute date.



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

def date
  @date
end

#destination_sanObject

Returns the value of attribute destination_san.



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

def destination_san
  @destination_san
end

#destination_suffixObject

Returns the value of attribute destination_suffix.



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

def destination_suffix
  @destination_suffix
end

#do_not_exceed_actionObject

Returns the value of attribute do_not_exceed_action.



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

def do_not_exceed_action
  @do_not_exceed_action
end

#do_not_exceed_amountObject

Returns the value of attribute do_not_exceed_amount.



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

def do_not_exceed_amount
  @do_not_exceed_amount
end

#do_not_ship_beforeObject

Returns the value of attribute do_not_ship_before.



37
38
39
# File 'lib/bisac/po.rb', line 37

def do_not_ship_before
  @do_not_ship_before
end

#filenameObject

Returns the value of attribute filename.



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

def filename
  @filename
end

#format_versionObject

Returns the value of attribute format_version.



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

def format_version
  @format_version
end

#invoice_copiesObject

Returns the value of attribute invoice_copies.



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

def invoice_copies
  @invoice_copies
end

#itemsObject

Returns the value of attribute items.



38
39
40
# File 'lib/bisac/po.rb', line 38

def items
  @items
end

#po_numberObject

Returns the value of attribute po_number.



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

def po_number
  @po_number
end

#source_nameObject

Returns the value of attribute source_name.



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

def source_name
  @source_name
end

#source_sanObject

Returns the value of attribute source_san.



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

def source_san
  @source_san
end

#source_suffixObject

Returns the value of attribute source_suffix.



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

def source_suffix
  @source_suffix
end

#special_instructionsObject

Returns the value of attribute special_instructions.



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

def special_instructions
  @special_instructions
end

Class Method Details

.load_from_file(input) ⇒ Object

reads a bisac text file into memory. input should be a string that specifies the file path



52
53
54
55
56
# File 'lib/bisac/po.rb', line 52

def self.load_from_file(input)
  $stderr.puts "WARNING: Bisac::PO.load_from_file is deprecated. It only returns the first PO in the file. use parse_file instead."
  self.parse_file(input) { |msg| return msg }
  return nil
end

.load_from_string(input) ⇒ Object

creates a Bisac::PO object from a string. Input should be a complete bisac file as a string



103
104
105
106
107
# File 'lib/bisac/po.rb', line 103

def self.load_from_string(input)
  $stderr.puts "WARNING: Bisac::PO.load_from_string is deprecated. It only returns the first PO in the string. use parse_string instead."
  data = input.split("\n")
  return self.build_message(data)
end

.parse_file(input) {|self.build_message(data)| ... } ⇒ Object

return all POs from a BISAC file

Yields:

  • (self.build_message(data))

Raises:

  • (ArgumentError)


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/bisac/po.rb', line 59

def self.parse_file(input, &block)
  raise ArgumentError, 'no file provided' if input.nil?
  raise ArgumentError, 'Invalid file' unless File.file?(input)
  data = []
  File.open(input, "r") do |f|
    f.each_line do |l|
      data << l

      # yield each message found in the file. A line starting with
      # 90 is the footer to a PO
      if data.last[0,2] == "90"
        yield self.build_message(data)
        data = []
      end
    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
  yield self.build_message(data) if data.size > 0
end

.parse_string(input) {|self.build_message(data)| ... } ⇒ Object

return all POs from a BISAC string

Yields:

  • (self.build_message(data))

Raises:

  • (ArgumentError)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/bisac/po.rb', line 82

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
    # 90 is the footer to a PO
    if data.last[0,2] == "90"
      yield self.build_message(data)
      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
  yield self.build_message(data) if data.size > 0
end

Instance Method Details

#to_sObject



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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/bisac/po.rb', line 113

def to_s
  lines = []

  # file header
  line = " " * 80
  line[0,2]   = "00" # 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)
  lines << line

  # po header
  lines << ""
  lines.last << "10"
  lines.last << "00002"  # line counter
  lines.last << " "
  lines.last << @po_number.to_s.ljust(11, " ")
  lines.last << " " # TODO
  lines.last << pad_trunc(@source_san, 7)
  lines.last << pad_trunc("",5) # TODO
  lines.last << pad_trunc(@destination_san, 7)
  lines.last << pad_trunc("",5) # TODO
  lines.last << pad_trunc(@date, 6)
  lines.last << pad_trunc(@cancellation_date,6)
  lines.last << yes_no(@backorder)
  lines.last << pad_trunc(@do_not_exceed_action,1)
  lines.last << pad_trunc(@do_not_exceed_amount,7)
  lines.last << pad_trunc(@invoice_copies,2)
  lines.last << yes_no(@special_instructions)
  lines.last << pad_trunc("",5) # TODO
  lines.last << pad_trunc(@do_not_ship_before,6)

  sequence = 3
  @items.each_with_index do |item, idx|
    item.line_item_number = idx + 1
    item.sequence_number  = sequence
    new_lines = item.to_s.split("\n")
    lines     += new_lines
    sequence  += new_lines.size
  end

  # PO control
  line = " " * 80
  line[0,2]   = "50"
  line[2,5]   = (lines.size + 1).to_s.rjust(5,"0")  # line counter
  line[8,12]  = @po_number.to_s.ljust(13, " ")
  line[20,5]  = "00001" # number of POs in file
  line[25,10] = @items.size.to_s.rjust(10,"0")
  line[35,10] = total_qty.to_s.rjust(10,"0")
  lines << line

  # file trailer
  line = " " * 80
  line[0,2]   = "90"
  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 '10' (PO) records
  line[25,10] = total_qty.to_s.rjust(10,"0")
  line[35,5]  = lines.select { |l| l[0,1] == "0"}.size.to_s.rjust(5,"0") # number of '00'-'09' records
  line[40,5]  = lines.select { |l| l[0,1] == "0"}.size.to_s.rjust(5,"0") # number of '10'-'19' records
  line[55,5]  = lines.select { |l| l[0,1] == "4"}.size.to_s.rjust(5,"0") # number of '40'-'49' records
  line[60,5]  = lines.select { |l| l[0,1] == "5"}.size.to_s.rjust(5,"0") # number of '50'-'59' records
  line[65,5]  = lines.select { |l| l[0,1] == "6"}.size.to_s.rjust(5,"0") # number of '60'-'69' records
  lines << line

  lines.join("\n")
end

#total_qtyObject



109
110
111
# File 'lib/bisac/po.rb', line 109

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