shipping 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,532 @@
1
+ # Author:: Lucas Carlson (mailto:lucas@rufy.com)
2
+ # Copyright:: Copyright (c) 2005 Lucas Carlson
3
+ # License:: LGPL
4
+
5
+ module Shipping
6
+ class FedEx < Base
7
+ # Gets the total price of the shipping
8
+ def price
9
+ get_price
10
+ p = @response.gsub(/.*"#{Tag.index 'net_charge_amount'}(-1)?,"([^"]+)".*99,""/,'\2').to_f
11
+ raise ShippingError, @response.gsub(/.*"3,"([^"]+)".*99,""/,'\1') if p == 0
12
+ return p
13
+ end
14
+
15
+ # Gets the base price of the shipping (with discounts taken into consideration)
16
+ def base_price
17
+ get_price
18
+ p = @response.gsub(/.*"#{Tag.index 'base_rate_amount'}(-1)?,"([^"]+)".*99,""/,'\2').to_f
19
+ raise ShippingError, @response.gsub(/.*"3,"([^"]+)".*99,""/,'\1') if p == 0
20
+ return p
21
+ end
22
+
23
+ private
24
+
25
+ def get_price #:nodoc:
26
+ @required = [:zip, :sender_zip, :weight]
27
+ @required += [:transaction_type, :fedex_account, :fedex_meter, :fedex_url]
28
+
29
+ @transaction_type ||= 'rate_services'
30
+ raise ShippingError, "No such transaction type" unless TransactionTypes.include?(@transaction_type)
31
+ @weight = @weight.to_f.to_s # all weights need to have a dot in them
32
+
33
+ post_data = ["0,\"#{TransactionTypes[@transaction_type][0]}\""] # this is required to be first
34
+
35
+ {
36
+ 'sender_fedex_express_account_number' => @fedex_account,
37
+ 'meter_number' => @fedex_meter,
38
+ 'carrier_code' => TransactionTypes[@transaction_type][1],
39
+ 'sender_postal_code' => @sender_zip,
40
+ 'sender_country_code' => @sender_country || 'US',
41
+ 'recipient_postal_code' => @zip,
42
+ 'recipient_country_code' => @country || 'US',
43
+ 'weight_units' => @weight_units || 'LBS',
44
+ 'package_total' => @package_total || '1', # total number of pieces
45
+ 'total_package_weight' => @weight,
46
+ 'declared_value' => @declared_value,
47
+ 'packaging_type' => @packaging_type || "01", # customer packaging
48
+ 'service_type' => ServiceTypes[@service_type] || ServiceTypes['ground_service']
49
+
50
+ }.each { |i,v| post_data << "#{Tag.index i},\"#{v.to_s.strip}\"" unless v.to_s.strip.empty? }
51
+
52
+ post_data += ['99,""'] # this is the terminating tag
53
+ @data = post_data.join
54
+
55
+ get_response @fedex_url
56
+ end
57
+
58
+ ServiceTypes = {
59
+ "priority" => "01",
60
+ "2day" => "03",
61
+ "standard_overnight" => "05",
62
+ "first_overnight" => "06",
63
+ "express_saver" => "20",
64
+ "1day_freight" => "70",
65
+ "2day_freight" => "80",
66
+ "3day_freight" => "83",
67
+ "international_priority" => "01",
68
+ "international_economy" => "03",
69
+ "international_first" => "06",
70
+ "international_priority_freight" => "70",
71
+ "international_economy_freight" => "86",
72
+ "home_delivery" => "90",
73
+ "ground_service" => "92",
74
+ "international_ground_service" => "92"
75
+ }
76
+
77
+ TransactionTypes = {
78
+ 'rate_ground' => ['022','FDXG'],
79
+ 'rate_express' => ['022','FDXE'],
80
+ 'rate_services' => ['025',''],
81
+ 'ship_ground' => ['021','FDXG'],
82
+ 'ship_express' => ['021','FDXE'],
83
+ 'cancel_express' => ['023','FDXE'],
84
+ 'cancel_ground' => ['023','FDXG'],
85
+ 'close_ground' => ['007','FDXG'],
86
+ 'service_available' => ['019','FDXE'],
87
+ 'fedex_locater' => ['410',''],
88
+ 'subscribe' => ['211',''],
89
+ 'sig_proof_delivery' => ['402',''],
90
+ 'track' => ['405',''],
91
+ 'ref_track' => ['403','']
92
+ }
93
+
94
+ Tag = {
95
+ 0 => 'transaction_code',
96
+ 1 => 'customer_transaction_identifier',
97
+ 2 => 'transaction_error_code',
98
+ 3 => 'transaction_error_message',
99
+ 4 => 'sender_company',
100
+ 5 => 'sender_address_line_1',
101
+ 6 => 'sender_address_line_2',
102
+ 7 => 'sender_city',
103
+ 8 => 'sender_state',
104
+ 9 => 'sender_postal_code',
105
+ 10 => 'sender_fedex_express_account_number',
106
+ 11 => 'recipient_company',
107
+ 12 => 'recipient_contact_name',
108
+ 13 => 'recipient_address_line_1',
109
+ 14 => 'recipient_address_line_2',
110
+ 15 => 'recipient_city',
111
+ 16 => 'recipient_state',
112
+ 17 => 'recipient_postal_code',
113
+ 18 => 'recipient_phone_number',
114
+ 20 => 'payer_account_number',
115
+ 23 => 'pay_type',
116
+ 24 => 'ship_date',
117
+ 25 => 'reference_information',
118
+ 27 => 'cod_flag',
119
+ 28 => 'cod_return_tracking_number',
120
+ 29 => 'tracking_number',
121
+ 30 => 'ursa_code',
122
+ 32 => 'sender_contact_name',
123
+ 33 => 'service_commitment',
124
+ 38 => 'sender_department',
125
+ 40 => 'alcohol_type',
126
+ 41 => 'alcohol_packaging',
127
+ 44 => 'hal_address',
128
+ 46 => 'hal_city',
129
+ 47 => 'hal_state',
130
+ 48 => 'hal_postal_code',
131
+ 49 => 'hal_phone_number',
132
+ 50 => 'recipient_country_code',
133
+ 51 => 'signature_release_ok_flag',
134
+ 52 => 'alcohol_packages',
135
+ 57 => 'dim_height',
136
+ 58 => 'dim_width',
137
+ 59 => 'dim_length',
138
+ 65 => 'astra_barcode',
139
+ 66 => 'broker_name',
140
+ 67 => 'broker_phone_number',
141
+ 68 => 'customs_declared_value_currency_type',
142
+ 70 => 'duties_pay_type',
143
+ 71 => 'duties_payer_account',
144
+ 72 => 'terms_of_sale',
145
+ 73 => 'parties_to_transaction',
146
+ 74 => 'country_of_ultimate_destination',
147
+ 75 => 'weight_units',
148
+ 76 => 'commodity_number_of_pieces',
149
+ 79 => 'description_of_contents',
150
+ 80 => 'country_of_manufacturer',
151
+ 81 => 'harmonized_code',
152
+ 82 => 'unit_quantity',
153
+ 83 => 'export_license_number',
154
+ 84 => 'export_license_expiration_date',
155
+ 99 => 'end_of_record',
156
+ 113 => 'commercial_invoice_flag',
157
+ 116 => 'package_total',
158
+ 117 => 'sender_country_code',
159
+ 118 => 'recipient_irs',
160
+ 120 => 'ci_marks_and_numbers',
161
+ 169 => 'importer_country',
162
+ 170 => 'importer_name',
163
+ 171 => 'importer_company',
164
+ 172 => 'importer_address_line_1',
165
+ 173 => 'importer_address_line_2',
166
+ 174 => 'importer_city',
167
+ 175 => 'importer_state',
168
+ 176 => 'importer_postal_code',
169
+ 177 => 'importer_account_number',
170
+ 178 => 'importer_number_phone',
171
+ 180 => 'importer_id',
172
+ 183 => 'sender_phone_number',
173
+ 186 => 'cod_add_freight_charges_flag',
174
+ 188 => 'label_buffer_data_stream',
175
+ 190 => 'document_pib_shipment_flag',
176
+ 194 => 'delivery_day',
177
+ 195 => 'destination',
178
+ 198 => 'destination_location_id',
179
+ 404 => 'commodity_license_exception',
180
+ 409 => 'delivery_date',
181
+ 411 => 'cod_return_label_buffer_data_stream',
182
+ 413 => 'nafta_flag',
183
+ 414 => 'commodity_unit_of_measure',
184
+ 418 => 'ci_comments',
185
+ 431 => 'dim_weight_used_flag',
186
+ 439 => 'cod_return_contact_name',
187
+ 440 => 'residential_delivery_flag',
188
+ 496 => 'freight_service_commitment',
189
+ 498 => 'meter_number',
190
+ 526 => 'form_id',
191
+ 527 => 'cod_return_form_id',
192
+ 528 => 'commodity_eccn',
193
+ 535 => 'cod_return',
194
+ 536 => 'cod_return_service_commitment',
195
+ 543 => 'cod_return_collect_plus_freight_amount',
196
+ 557 => 'message_type_code',
197
+ 558 => 'message_code',
198
+ 559 => 'message_text',
199
+ 600 => 'forwarding_agent_routed_export_transaction_indicator',
200
+ 602 => 'exporter_ein_ssn_indicator',
201
+ 603 => 'int-con_company_name',
202
+ 604 => 'int-con_contact_name',
203
+ 605 => 'int-con_address_line_1',
204
+ 606 => 'int-con_address_line_2',
205
+ 607 => 'int-con_city',
206
+ 608 => 'int-con_state',
207
+ 609 => 'int-con_zip',
208
+ 610 => 'int-con_phone_number',
209
+ 611 => 'int-con_country',
210
+ 1005 => 'manifest_invoic_e_file_name',
211
+ 1006 => 'domain_name',
212
+ 1007 => 'close_manifest_date',
213
+ 1008 => 'package_ready_time',
214
+ 1009 => 'time_companyclose',
215
+ 1032 => 'duties_payer_country_code',
216
+ 1089 => 'rate_scale',
217
+ 1090 => 'rate_currency_type',
218
+ 1092 => 'rate_zone',
219
+ 1096 => 'origin_location_id',
220
+ 1099 => 'volume_units',
221
+ 1101 => 'payer_credit_card_number',
222
+ 1102 => 'payer_credit_card_type',
223
+ 1103 => 'sender_fax',
224
+ 1104 => 'payer_credit_card_expiration_date',
225
+ 1115 => 'ship_time',
226
+ 1116 => 'dim_units',
227
+ 1117 => 'package_sequence',
228
+ 1118 => 'release_authorization_number',
229
+ 1119 => 'future_day_shipment',
230
+ 1120 => 'inside_pickup_flag',
231
+ 1121 => 'inside_delivery_flag',
232
+ 1123 => 'master_tracking_number',
233
+ 1124 => 'master_form_id',
234
+ 1137 => 'ursa_uned_prefix',
235
+ 1139 => 'sender_irs_ein_number',
236
+ 1145 => 'recipient_department',
237
+ 1159 => 'scan_description',
238
+ 1160 => 'scan_location_city',
239
+ 1161 => 'scan_location_state',
240
+ 1162 => 'scan_date',
241
+ 1163 => 'scan_time',
242
+ 1164 => 'scan_location_country',
243
+ 1167 => 'disp_exception_cd',
244
+ 1168 => 'status_exception_cd',
245
+ 1174 => 'bso_flag',
246
+ 1178 => 'ursa_suffix_code',
247
+ 1179 => 'broker_fdx_account_number',
248
+ 1180 => 'broker_company',
249
+ 1181 => 'broker_line_1_address',
250
+ 1182 => 'broker_line_2_address',
251
+ 1183 => 'broker_city',
252
+ 1184 => 'broker_state',
253
+ 1185 => 'broker_postal_code',
254
+ 1186 => 'broker_country_code',
255
+ 1187 => 'broker_id_number',
256
+ 1193 => 'ship_delete_message',
257
+ 1195 => 'payer_country_code',
258
+ 1200 => 'hold_at_location_hal_flag',
259
+ 1201 => 'sender_email_address',
260
+ 1202 => 'recipient_email_address',
261
+ 1203 => 'optional_ship_alert_message',
262
+ 1204 => 'ship_alert_email_address',
263
+ 1206 => 'ship_alert_notification_flag',
264
+ 1208 => 'no_indirect_delivery_flag_signature_required',
265
+ 1210 => 'purpose_of_shipment',
266
+ 1211 => 'pod_address',
267
+ 1213 => 'proactive_notification_flag',
268
+ 1237 => 'cod_return_phone',
269
+ 1238 => 'cod_return_company',
270
+ 1239 => 'cod_return_department',
271
+ 1240 => 'cod_return_address_1',
272
+ 1241 => 'cod_return_address_2',
273
+ 1242 => 'cod_return_city',
274
+ 1243 => 'cod_return_state',
275
+ 1244 => 'cod_return_postal_code',
276
+ 1253 => 'packaging_list_enclosed_flag',
277
+ 1265 => 'hold_at_location_contact_name',
278
+ 1266 => 'saturday_delivery_flag',
279
+ 1267 => 'saturday_pickup_flag',
280
+ 1268 => 'dry_ice_flag',
281
+ 1271 => 'shippers_load_and_count_slac',
282
+ 1272 => 'booking_number',
283
+ 1273 => 'packaging_type',
284
+ 1274 => 'service_type',
285
+ 1286 => 'exporter_ppi-_contact_name',
286
+ 1287 => 'exporter_ppi-company_name',
287
+ 1288 => 'exporter_ppi-address_line_1',
288
+ 1289 => 'exporter_ppi-address_line_2',
289
+ 1290 => 'exporter_ppi-city',
290
+ 1291 => 'exporter_ppi-state',
291
+ 1292 => 'exporter_ppi-zip',
292
+ 1293 => 'exporter_ppi-country',
293
+ 1294 => 'exporter_ppi-phone_number',
294
+ 1295 => 'exporter_ppi-ein_ssn',
295
+ 1297 => 'customer_invoice_number',
296
+ 1300 => 'purchase_order_number',
297
+ 1331 => 'dangerous',
298
+ 1332 => 'alcohol_flag',
299
+ 1333 => 'drop_off_type',
300
+ 1337 => 'package_content_information',
301
+ 1339 => 'estimated_delivery_date',
302
+ 1340 => 'estimated_delivery_time',
303
+ 1341 => 'sender_pager_number',
304
+ 1342 => 'recipient_pager_number',
305
+ 1343 => 'broker_email_address',
306
+ 1344 => 'broker_fax_number',
307
+ 1346 => 'emerge_shipment_identifier',
308
+ 1347 => 'emerge_merchant_identifier',
309
+ 1349 => 'aes_filing_status',
310
+ 1350 => 'xtn_suffix_number',
311
+ 1352 => 'sender_ein_ssn_identificator',
312
+ 1358 => 'aes_ftsr_exemption_number',
313
+ 1359 => 'sed_legend_number',
314
+ 1366 => 'close_manifest_time',
315
+ 1367 => 'close_manifest_data_buffer',
316
+ 1368 => 'label_type',
317
+ 1369 => 'label_printer_type',
318
+ 1370 => 'label_media_type',
319
+ 1371 => 'manifest_only_request_flag',
320
+ 1372 => 'manifest_total',
321
+ 1376 => 'rate_weight_unit_of_measure',
322
+ 1377 => 'dim_weight_unit_of_measure',
323
+ 1391 => 'client_revision_indicator',
324
+ 1392 => 'inbound_visibility_block_shipment_data_indicator',
325
+ 1394 => 'shipment_content_records_total',
326
+ 1395 => 'part_number',
327
+ 1396 => 'sku_item_upc',
328
+ 1397 => 'receive_quantity',
329
+ 1398 => 'description',
330
+ 1399 => 'aes_entry_number',
331
+ 1400 => 'total_shipment_weight',
332
+ 1401 => 'total_package_weight',
333
+ 1402 => 'billed_weight',
334
+ 1403 => 'dim_weight',
335
+ 1404 => 'total_volume',
336
+ 1405 => 'alcohol_volume',
337
+ 1406 => 'dry_ice_weight',
338
+ 1407 => 'commodity_weight',
339
+ 1408 => 'commodity_unit_value',
340
+ 1409 => 'cod_amount',
341
+ 1410 => 'commodity_customs_value',
342
+ 1411 => 'total_customs_value',
343
+ 1412 => 'freight_charge',
344
+ 1413 => 'insurance_charge',
345
+ 1414 => 'taxes_miscellaneous_charge',
346
+ 1415 => 'declared_value',
347
+ 1416 => 'base_rate_amount',
348
+ 1417 => 'total_surcharge_amount',
349
+ 1418 => 'total_discount_amount',
350
+ 1419 => 'net_charge_amount',
351
+ 1420 => 'total_rebate_amount',
352
+ 1429 => 'list_variable_handling_charge_amount',
353
+ 1431 => 'list_total_customer_charge',
354
+ 1432 => 'cod_customer_amount',
355
+ 1450 => 'more_data_indicator',
356
+ 1451 => 'sequence_number',
357
+ 1452 => 'last_tracking_number',
358
+ 1453 => 'track_reference_type',
359
+ 1454 => 'track_reference',
360
+ 1456 => 'spod_type_request',
361
+ 1458 => 'spod_fax_recipient_name',
362
+ 1459 => 'spod_fax_recipient_number',
363
+ 1460 => 'spod_fax_sender_name',
364
+ 1461 => 'spod_fax_sender_phone_number',
365
+ 1462 => 'language_indicator',
366
+ 1463 => 'spod_fax_recipient_company_name_mail',
367
+ 1464 => 'spod_fax_recipient_address_line_1_mail',
368
+ 1465 => 'spod_fax_recipient_address_line_2_mail',
369
+ 1466 => 'spod_fax_recipient_city_mail',
370
+ 1467 => 'spod_fax_recipient_state_mail',
371
+ 1468 => 'spod_fax_recipient_zip_postal_code_mail',
372
+ 1469 => 'spod_fax_recipient_country_mail',
373
+ 1470 => 'spod_fax_confirmation',
374
+ 1471 => 'spod_letter',
375
+ 1472 => 'spod_ground_recipient_name',
376
+ 1473 => 'spod_ground_recipient_company_name',
377
+ 1474 => 'spod_ground_recipient_address_line_1',
378
+ 1475 => 'spod_ground_recipient_address_line_2',
379
+ 1476 => 'spod_ground_recipient_city',
380
+ 1477 => 'spod_ground_recipient_state_province',
381
+ 1478 => 'spod_ground_recipient_zip_postal_code',
382
+ 1479 => 'spod_ground_recipient_country',
383
+ 1480 => 'more_information',
384
+ 1507 => 'list_total_surcharge_amount',
385
+ 1525 => 'effective_net_discount',
386
+ 1528 => 'list_net_charge_amount',
387
+ 1529 => 'rate_indicator_1_numeric_valid_values',
388
+ 1530 => 'list_base_rate_amount',
389
+ 1531 => 'list_total_discount_amount',
390
+ 1532 => 'list_total_rebate_amount',
391
+ 1534 => 'detail_scan_indicator',
392
+ 1535 => 'paging_token',
393
+ 1536 => 'number_of_relationships',
394
+ 1537 => 'search_relationship_string',
395
+ 1538 => 'search_relationship_type_code',
396
+ 1551 => 'delivery_notification_flag',
397
+ 1552 => 'language_code',
398
+ 1553 => 'shipper_delivery_notification_flag',
399
+ 1554 => 'shipper_ship_alert_flag',
400
+ 1555 => 'shipper_language_code',
401
+ 1556 => 'recipient_delivery_notification_flag',
402
+ 1557 => 'recipient_ship_alert_flag',
403
+ 1558 => 'recipient_language_code',
404
+ 1559 => 'broker_delivery_notification_flag',
405
+ 1560 => 'broker_ship_alert_flag',
406
+ 1561 => 'broker_language_code',
407
+ 1562 => 'fedex_staffed_location_flag',
408
+ 1563 => 'fedex_self_service_location_indicator',
409
+ 1564 => 'fasc',
410
+ 1565 => 'latest_express_dropoff_flag',
411
+ 1566 => 'express_dropoff_after_time',
412
+ 1567 => 'fedex_location_intersection_street_address',
413
+ 1568 => 'distance',
414
+ 1569 => 'hours_of_operation',
415
+ 1570 => 'hours_of_operation_sat',
416
+ 1571 => 'last_express_dropoff',
417
+ 1572 => 'last_express_dropoff_sat',
418
+ 1573 => 'express_service_flag',
419
+ 1574 => 'location_count',
420
+ 1575 => 'fedex_location_business_name',
421
+ 1576 => 'fedex_location_business_type',
422
+ 1577 => 'fedex_location_city',
423
+ 1578 => 'fedex_location_state',
424
+ 1579 => 'fedex_location_postal_code',
425
+ 1580 => 'dangerous_goods_flag',
426
+ 1581 => 'saturday_service_flag',
427
+ 1582 => 'begin_date',
428
+ 1583 => 'end_date',
429
+ 1584 => 'tracking_groups',
430
+ 1606 => 'variable_handling_charge_level',
431
+ 1607 => 'doc_tab_header_1',
432
+ 1608 => 'doc_tab_header_2',
433
+ 1609 => 'doc_tab_header_3',
434
+ 1610 => 'doc_tab_header_4',
435
+ 1611 => 'doc_tab_header_5',
436
+ 1612 => 'doc_tab_header_6',
437
+ 1613 => 'doc_tab_header_7',
438
+ 1614 => 'doc_tab_header_8',
439
+ 1615 => 'doc_tab_header_9',
440
+ 1616 => 'doc_tab_header_10',
441
+ 1617 => 'doc_tab_header_11',
442
+ 1618 => 'doc_tab_header_12',
443
+ 1624 => 'doc_tab_field_1',
444
+ 1625 => 'doc_tab_field_2',
445
+ 1626 => 'doc_tab_field_3',
446
+ 1627 => 'doc_tab_field_4',
447
+ 1628 => 'doc_tab_field_5',
448
+ 1629 => 'doc_tab_field_6',
449
+ 1630 => 'doc_tab_field_7',
450
+ 1631 => 'doc_tab_field_8',
451
+ 1632 => 'doc_tab_field_9',
452
+ 1633 => 'doc_tab_field_10',
453
+ 1634 => 'doc_tab_field_11',
454
+ 1635 => 'doc_tab_field_12',
455
+ 1636 => 'delivery_area_surcharge',
456
+ 1637 => 'list_delivery_area_surcharge',
457
+ 1638 => 'fuel_surcharge',
458
+ 1639 => 'list_fuel_surcharge',
459
+ 1640 => 'fice_surcharge',
460
+ 1642 => 'value_added_tax',
461
+ 1644 => 'offshore_surcharge',
462
+ 1645 => 'list_offshore_surcharge',
463
+ 1649 => 'other_surcharges',
464
+ 1650 => 'list_other_surcharges',
465
+ 1704 => 'service_type_description',
466
+ 1705 => 'deliver_to',
467
+ 1706 => 'signed_for',
468
+ 1707 => 'delivery_time',
469
+ 1711 => 'status_exception',
470
+ 1713 => 'tracking_cod_flag',
471
+ 1715 => 'number_of_track_activities',
472
+ 1716 => 'delivery_reattempt_date',
473
+ 1717 => 'delivery_reattempt_time',
474
+ 1718 => 'package_type_description',
475
+ 1720 => 'delivery_date_numeric',
476
+ 1721 => 'tracking_activity_line_1',
477
+ 1722 => 'tracking_activity_line_2',
478
+ 1723 => 'tracking_activity_line_3',
479
+ 1724 => 'tracking_activity_line_4',
480
+ 1725 => 'tracking_activity_line_5',
481
+ 1726 => 'tracking_activity_line_6',
482
+ 1727 => 'tracking_activity_line_7',
483
+ 1728 => 'tracking_activity_line_8',
484
+ 1729 => 'tracking_activity_line_9',
485
+ 1730 => 'tracking_activity_line_10',
486
+ 1731 => 'tracking_activity_line_11',
487
+ 1732 => 'tracking_activity_line_12',
488
+ 1733 => 'tracking_activity_line_13',
489
+ 1734 => 'tracking_activity_line_14',
490
+ 1735 => 'tracking_activity_line_15',
491
+ 2254 => 'recipient_fax_number',
492
+ 2382 => 'return_shipment_indicator',
493
+ 3000 => 'cod_type_collection',
494
+ 3001 => 'fedex_ground_purchase_order',
495
+ 3002 => 'fedex_ground_invoice',
496
+ 3003 => 'fedex_ground_customer_reference',
497
+ 3008 => 'autopod_flag',
498
+ 3009 => 'aod_flag',
499
+ 3010 => 'oversize_flag',
500
+ 3011 => 'other_oversize_flag',
501
+ 3018 => 'nonstandard_container_flag',
502
+ 3019 => 'fedex_signature_home_delivery_flag',
503
+ 3020 => 'fedex_home_delivery_type',
504
+ 3023 => 'fedex_home_delivery_date',
505
+ 3024 => 'fedex_home_delivery_phone_number',
506
+ 3025 => 'carrier_code',
507
+ 3028 => 'ground_account_number',
508
+ 3035 => 'ship_alert_fax_number',
509
+ 3045 => 'cod_return_reference_indicator',
510
+ 3046 => 'additional_handling_detected',
511
+ 3053 => 'multiweight_net_charge',
512
+ 3090 => 'last_ground_dropoff',
513
+ 3091 => 'last_ground_dropoff_sat',
514
+ 3092 => 'ground_service_flag',
515
+ 3124 => 'oversize_classification',
516
+ 4003 => 'subscriber_contact_name',
517
+ 4004 => 'subscriber_password_reminder',
518
+ 4007 => 'subscriber_company_name',
519
+ 4008 => 'subscriber_address_line_1',
520
+ 4009 => 'subscriber_address_line_2',
521
+ 4011 => 'subscriber_city_name',
522
+ 4012 => 'subscriber_state_code',
523
+ 4013 => 'subscriber_postal_code',
524
+ 4014 => 'subscriber_country_code',
525
+ 4015 => 'subscriber_phone_number',
526
+ 4017 => 'subscriber_pager_number',
527
+ 4018 => 'subscriber_email_address',
528
+ 4021 => 'subscription_service_name',
529
+ 4022 => 'subscriber_fax_number'
530
+ }
531
+ end
532
+ end
@@ -0,0 +1,83 @@
1
+ # Author:: Lucas Carlson (mailto:lucas@rufy.com)
2
+ # Copyright:: Copyright (c) 2005 Lucas Carlson
3
+ # License:: LGPL
4
+
5
+ =begin
6
+ UPS Service transaction_type
7
+ ---------------------------------------------
8
+ Next Day Air Early 1DM
9
+ Next Day Air 1DA
10
+ Next Day Air Intra 1DAPI (Puerto Rico)
11
+ Next Day Air Saver 1DP
12
+ 2nd Day Air A M2DM
13
+ 2nd Day Air 2DA
14
+ 3 Day Select 3DS
15
+ Ground GND
16
+ Canada Standard STD
17
+ Worldwide Express XPR
18
+ Worldwide Express XDM
19
+ Worldwide Expedited XPD
20
+ =end
21
+
22
+ module Shipping
23
+ class UPS < Base
24
+
25
+ API_VERSION = "1.0001"
26
+
27
+ def price
28
+ @required = [:zip, :country, :sender_zip, :weight]
29
+
30
+ @insured_value ||= 0
31
+ @country ||= 'US'
32
+ @sender_country ||= 'US'
33
+ @transaction_type ||= 'GND' # default to UPS ground
34
+
35
+ @data = "AppVersion=1.2&AcceptUPSLicenseAgreement=yes&ResponseType=application/x-ups-rss&ActionCode=3&RateChart=Customer+Counter&DCISInd=0&SNDestinationInd1=0&SNDestinationInd2=0&ResidentialInd=$r&PackagingType=00&ServiceLevelCode=#{@transaction_type}&ShipperPostalCode=#{@sender_zip}&ShipperCountry=#{@sender_country}&ConsigneePostalCode=#{@zip}&ConsigneeCountry=#{@country}&PackageActualWeight=#{@weight}&DeclaredValueInsurance=#{@insured_value}"
36
+
37
+ get_response "http://www.ups.com/using/services/rave/qcost_dss.cgi"
38
+
39
+ price = @response.split("%")
40
+ price = price[price.size-2]
41
+
42
+ return price.to_f
43
+ end
44
+
45
+ def valid_address?( delta = 1.0 )
46
+ @required = [:ups_account, :ups_user, :ups_password]
47
+
48
+ state = STATES.has_value?(@state.downcase) ? STATES.index(@state.downcase) : @state
49
+
50
+ @data = "<?xml version=\"1.0\"?>
51
+ <AccessRequest>
52
+ <AccessLicenseNumber>#{@ups_account}</AccessLicenseNumber>
53
+ <UserId>#{@ups_user}</UserId>
54
+ <Password>#{@ups_password}</Password>
55
+ </AccessRequest>
56
+ <?xml version=\"1.0\"?>
57
+ <AddressValidationRequest xml:lang=\"en-US\">
58
+ <Request>
59
+ <TransactionReference>
60
+ <CustomerContext>#{@city}, #{state} #{@zip}</CustomerContext>
61
+ <XpciVersion>#{API_VERSION}</XpciVersion>
62
+ </TransactionReference>
63
+ <RequestAction>AV</RequestAction>
64
+ </Request>
65
+ <Address>
66
+ <City>#{@city}</City>
67
+ <StateProvinceCode>#{state}</StateProvinceCode>
68
+ <PostalCode>#{@zip}</PostalCode>
69
+ </Address>
70
+ </AddressValidationRequest>"
71
+
72
+ get_response "https://wwwcie.ups.com/ups.app/xml/AV"
73
+
74
+ doc = REXML::Document.new(@response)
75
+
76
+ if doc.root.elements["Response"].elements["ResponseStatusCode"].text == "1" && doc.root.elements["AddressValidationResult"].elements["Quality"].text.to_f >= delta
77
+ return true
78
+ else
79
+ return false
80
+ end
81
+ end
82
+ end
83
+ end
data/lib/shipping.rb ADDED
@@ -0,0 +1,33 @@
1
+ #--
2
+ # Copyright (c) 2005 Lucas Carlson
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ # Author:: Lucas Carlson (mailto:lucas@rufy.com)
24
+ # Copyright:: Copyright (c) 2005 Lucas Carlson
25
+ # License:: LGPL
26
+
27
+ require 'yaml'
28
+ require 'rexml/document'
29
+ require 'net/http'
30
+ require 'net/https'
31
+ require 'shipping/base'
32
+ require 'shipping/fedex'
33
+ require 'shipping/ups'
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ class BaseTest < Test::Unit::TestCase
3
+ def setup
4
+ @ship = Shipping::Base.new :zip => 97202, :state => "OR", :sender_zip => 10001, :sender_state => "New York", :weight => 2
5
+ end
6
+
7
+ def test_ups
8
+ ups = @ship.ups
9
+ assert_instance_of Shipping::UPS, ups
10
+ assert_equal ups.zip, @ship.zip
11
+ end
12
+
13
+ def test_fedex
14
+ fedex = @ship.fedex
15
+ assert_instance_of Shipping::FedEx, fedex
16
+ assert_equal fedex.zip, @ship.zip
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ class FedExTest < Test::Unit::TestCase
3
+ def setup
4
+ @ship = Shipping::FedEx.new :zip => 97202, :state => "OR", :sender_zip => 10001, :sender_state => "New York", :weight => 2
5
+ end
6
+
7
+ def test_price
8
+ assert_equal 5.17, @ship.price
9
+ end
10
+ end