Class: Pdf::Label::Carton
- Inherits:
-
BaseService
- Object
- BaseService
- Pdf::Label::Carton
- Includes:
- Base
- Defined in:
- app/services/pdf/label/carton.rb
Constant Summary collapse
- LABEL_MARGIN =
Page: 288 × 432 pt (4 × 6 in). 5 pt margin each side → 278 × 422 pt usable.
5- LABEL_AVAIL_H =
422 pt
432 - LABEL_MARGIN * 2
- EXTRA_PADDING =
Extra bottom padding (pt) added to key cells so the rows fill the 422 pt usable height.
The QR code in the BPS row auto-fills available cell width (~108 pt), so bps padding only
needs to cover the remaining gap after the QR + title, not absorb all the slack. { 4 => { address: 32, shipping: 32, po: 26, bps: 22 }, 5 => { address: 2, shipping: 2, po: 2, bps: 1 }, }.freeze
Constants included from Base
Base::FONT, Base::NIMBUS_SANS_PATH, Base::NIMBUS_SANS_PATH_BOLD, Base::WY_LOGO_PATH
Instance Method Summary collapse
- #call ⇒ Object
-
#initialize(shipment, options) ⇒ Carton
constructor
A new instance of Carton.
Constructor Details
#initialize(shipment, options) ⇒ Carton
Returns a new instance of Carton.
16 17 18 19 |
# File 'app/services/pdf/label/carton.rb', line 16 def initialize(shipment, ) @shipment = shipment if shipment @po_number = shipment&.delivery&.po_number end |
Instance Method Details
#call ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 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 |
# File 'app/services/pdf/label/carton.rb', line 21 def call composer = build_composer(page_size: [0, 0, 288, 432], margin: [LABEL_MARGIN, LABEL_MARGIN]) l = composer.document.layout label_table = [] from_address = @shipment.delivery.origin_address.to_array.join("\n") to_address = @shipment.delivery.destination_address.to_array.join("\n") label_table << [ { content: l.formatted_text([{ text: "SHIP FROM:\n", style: { font: "#{FONT} bold", font_size: 9, line_height: 11 } }, { text: from_address.gsub(/^WarmlyYours.*$/, 'WarmlyYours'), style: { font: FONT, font_size: 9, line_height: 11 } }]), col_span: 8 }, { content: l.formatted_text([{ text: "SHIP TO:\n", style: { font: "#{FONT} bold", font_size: 9, line_height: 11 } }, { text: to_address, style: { font: FONT, font_size: 9, line_height: 11 } }]), col_span: 10 } ] shipping_lines = [] shipping_lines << @shipment.delivery&.chosen_shipping_method&.description if @shipment.delivery&.chosen_shipping_method.present? shipping_lines << "BOL: #{@shipment.delivery.carrier_bol}" if @shipment.delivery.carrier_bol.present? shipping_lines << "PRO: #{@shipment.tracking_number}" if @shipment.tracking_number.present? label_table << [ { content: l.text(shipping_lines.join("\n"), style: { font: FONT, font_size: 9, line_height: 11 }), col_span: 18 } ] content_lines = [] content_lines << @shipment.shipment_content_label content_lines << "TOTAL QTY: #{@shipment.shipment_content_quantity}" if @shipment.shipment_content_quantity.positive? if @shipment.shipment_total.positive? label = @shipment.pallet? ? 'PALLET' : 'CARTON' content_lines << "#{label}: #{@shipment.shipment_position} of #{@shipment.shipment_total}" end po_number = @shipment.delivery&.order&.po_number # Sanitise PO to printable ASCII — same logic as the legacy barby generator po_number_clean = po_number.present? ? po_number.to_s.scan(/\S/).join.encode(Encoding::ASCII_8BIT, invalid: :replace, undef: :replace, replace: '') : nil label_table << [ { content: l.text(content_lines.join("\n"), style: { font: FONT, font_size: 9, text_align: :left, line_height: 11 }), col_span: 9 }, { content: [ l.text('PURCHASE ORDER:', style: { font: FONT, font_size: 9, align: :center, text_align: :center, line_height: 11 }), (l.box(:barcode, data: { value: po_number_clean, symbology: :code128 }, width: 120, height: 50) if po_number_clean.present?) ].compact, col_span: 9 } ] bps_string = begin @shipment..presence rescue StandardError nil end skus = @shipment.shipment_content_grouped_content_key sku_lines = skus.first(7).map { |ck, qty| "(#{qty}) #{ck[:sku]}" } sku_lines << "+ #{skus.size - 7} additional skus" if skus.size > 7 label_table << [ { content: [ l.text('Barcode Packing Slip', style: { font: "#{FONT} bold", font_size: 9, align: :center, line_height: 11, padding: [3, 0, 0, 0] }), (l.box(:qrcode, data: bps_string, style: { align: :center, margin: [2, 5, 2, 5] }) if bps_string) ].compact, col_span: 7 }, { content: l.formatted_text([{ text: "#{@shipment.delivery.reference_number_for_label} Contents:\n\n", style: { font: "#{FONT} bold", font_size: 9, line_height: 11 } }, { text: sku_lines.join("\n"), style: { font: FONT, font_size: 8, line_height: 11 } }], style: { padding: [5, 0, 0, 0] }), col_span: 11 } ] if @shipment.container_code.present? # For standard SSCC-18 codes the first two digits are the GS1 Application Identifier "00". # Zint's :gs1_128 symbology expects the AI in brackets: "[00]<18 digits>". # Non-SSCC container codes (e.g. Amazon AMZN-prefixed) are just plain Code 128. , sscc_symbology = if @shipment.sscc_code? ["[#{@shipment.container_code[0..1]}]#{@shipment.container_code[2..]}", :gs1_128] else [@shipment.container_code, :code128] end sscc_code_text = if @shipment.sscc_code? "(#{@shipment.container_code[0..1]}) #{@shipment.container_code[2]} #{@shipment.container_code[3..9]} #{@shipment.container_code[10..18]} #{@shipment.container_code[19]}" else @shipment.container_code end label_table << [ { content: [ l.text('Serial Shipping Container Code (SSCC)', style: { font: "#{FONT} bold", font_size: 9, align: :center, padding: [5, 0, 0, 0], line_height: 11 }), l.box(:barcode, data: { value: , symbology: sscc_symbology }, width: 120, height: 40, style: { align: :center }), l.text(sscc_code_text, style: { font: "#{FONT} bold", font_size: 9, align: :center, padding: [5, 0, 0, 0], line_height: 11 }) ], col_span: 18 } ] end block = lambda do |total_rows| ep = EXTRA_PADDING[total_rows] || EXTRA_PADDING[4] lambda do |cell| if cell.row == 2 && cell.column.zero? cell.style.border = { width: [0.5, 0, 0.5, 0.5] } cell.style.padding = [21, 2, 4 + ep[:po], 7] elsif cell.row == 2 && cell.column >= 8 cell.style.border = { width: [0.5, 0.5, 0.5, 0] } cell.style.padding = [10, 3, 10 + ep[:po], 3] elsif cell.row == 1 cell.style.border = { width: 0.5 } cell.style.padding = [10, 3, 10 + ep[:shipping], 3] elsif cell.row == 3 && cell.column >= 7 cell.style.border = { width: 0.5 } cell.style.padding = [3, 5] elsif cell.row == 3 && cell.column.zero? cell.style.border = { width: 0.5 } cell.style.padding = [5, 0, ep[:bps], 0] elsif cell.row == 0 cell.style.border = { width: 0.5 } cell.style.padding = [3, 3, 3 + ep[:address], 3] else cell.style.border = { width: 0.5 } cell.style.padding = 3 end end end composer.table(label_table, style: { border: { width: 0.5 }, padding: -0.5 }, cell_style: block.call(label_table.size)) buffer = StringIO.new composer.write(buffer, optimize: true) buffer.string end |