1package Net::UPS::Service;
2$Net::UPS::Service::VERSION = '0.16';
3{
4  $Net::UPS::Service::DIST = 'Net-UPS';
5}
6use strict;
7use warnings;
8use Carp ( 'croak' );
9use Class::Struct 0.58;
10
11struct(
12    code            => '$',
13    label           => '$',
14    total_charges   => '$',
15    rates           => '@',
16    rated_packages  => '@',
17    guaranteed_days => '$',
18);
19
20sub SERVICE_CODES () {
21    return {
22        NEXT_DAY_AIR            => '01',
23        '2ND_DAY_AIR'           => '02',
24        GROUND                  => '03',
25        WORLDWIDE_EXPRESS       => '07',
26        WORLDWIDE_EXPEDITED     => '08',
27        STANDARD                => '11',
28        '3_DAY_SELECT'          => '12',
29        '3DAY_SELECT'           => '12',
30        NEXT_DAY_AIR_SAVER      => '13',
31        NEXT_DAY_AIR_EARLY_AM   => '14',
32        WORLDWIDE_EXPRESS_PLUS  => '54',
33        WORLDWIDE_EXPRESS_FREIGHT => '96',
34        '2ND_DAY_AIR_AM'        => '59',
35        SAVER                   => '65',
36        TODAY_EXPRESS_SAVER     => '86',
37        TODAY_EXPRESS           => '85',
38        TODAY_DEDICATED_COURIER => '83',
39        TODAY_STANDARD          => '82',
40    };
41}
42
43sub SERVICE_CODES_REVERSE () {
44    return {
45        map { SERVICE_CODES->{$_}, $_ } keys %{SERVICE_CODES()}
46    };
47}
48
49
50sub new_from_code {
51    my $class = shift;
52    my $code  = shift;
53
54    unless ( defined $code ) {
55        croak "new_from_code(): usage error";
56    }
57
58    $code = sprintf("%02d", $code);
59
60    my $label = SERVICE_CODES_REVERSE->{$code};
61    unless ( defined $label ) {
62        croak "new_from_code(): no such service code '$code'";
63    }
64    return $class->new(code=>$code, label=>$label);
65}
66
67
68sub new_from_label {
69    my $class = shift;
70    my $label = shift;
71
72    unless ( defined $label ) {
73        croak "new_from_label(): usage error";
74    }
75    my $code = SERVICE_CODES->{$label};
76    unless ( defined $code ) {
77        croak "new_from_label(): no such service '$label'";
78    }
79    return $class->new(code=>$code, label=>$label);
80}
81
82
83sub name {
84    my $self = shift;
85    unless ( $self->label ) {
86        return "UNKNOWN";
87    }
88    my $name = $self->label();
89    $name =~ s/_/ /g;
90    return $name;
91}
92
93
94sub cache_id { $_[0]->code }
95
961;
97
98__END__;
99
100=head1 NAME
101
102Net::UPS::Service - Class representing a UPS service
103
104=head1 SYNOPSIS
105
106    $services = $ups->shop_for_rates($from, $to, $package);
107    unless ( defined $services ) {
108        die $ups->errstr;
109    }
110    unless ( @$services ) {
111        die "There are no services available for your address";
112    }
113    print "Following services are available for your address to ship that package:\n";
114    while (my $service = shift @$services ) {
115        printf("%s => \$.2f\n", $service->label, $service->total_charges);
116    }
117
118=head1 DESCRIPTION
119
120Net::UPS::Service represents a single UPS shipping service. In typical programming environment, the only time you will interact with this object is when it's returned from C<shop_for_rates()> method of Net::UPS.
121
122=head1 ATTRIBUTES
123
124Following attributes are available in all Services
125
126=over 4
127
128=item code()
129
130Two digit service code as used by UPS Online Tools. It is not something useful for an average programmer.
131
132=item label()
133
134Label assigned by Net::UPS to each service code, to rid programmer of having to have service codes table in front of him the whole time he's coding.
135
136=item total_charges()
137
138Monetary value of total cost of shipping package(s). If you had multiple packages passed to C<shop_for_rates()> method, then total_charges() is the total of all the rates' C<total_charges()>. Don't get confused!
139
140=item rates()
141
142An array reference to a list of rates quoted by this service. Amount of rates always equals amount of packages being rated, so there is always only one rate per package. If there was only one package rated, than C<rates()> returns an arrayref with a single Net::UPS::Rate object.
143
144=item rated_packages()
145
146Reference to a list of packages rated using this service. If there was only one package rated, rated_packages() returns an arrayref containing a single element. Each package represented by Net::UPS::Package instance.
147
148=item guaranteed_days()
149
150Guaranteed days in transit. You can use this option to calculate the exact date the customer can expect the package delivered. This attributes seems to be undef for GROUND service.
151
152=back
153
154=head1 METHODS
155
156Net::UPS::Service is a Class::Struct. In addition, following methods are provided:
157
158=over 4
159
160=item new_from_code($code)
161
162Creates a Net::UPS::Service instance using the service code. Example:
163
164    $service = Net::UPS::Service->new_from_code('03');
165    printf("Service is: %s\n", $service->label);
166
167    # outputs:
168    Service is: GROUND
169
170=item new_from_label($label)
171
172Create Net::UPS::Service instance using the service label. Example:
173
174    $service = Net::UPS::Service->new_from_label('2ND_DAY_AIR');
175    printf("Service code is: %s\n", $service->code);
176
177    # Outputs:
178    Service code is: 02
179
180=item name()
181
182Similar to label(), except underscores will be removed before output. For example:
183
184    $service = Net::UPS::Service->new_from_code('07');
185    printf("Service label is: %s\n", $service->label);
186    printf("Service name  is: %s\n", $service->name);
187
188    # Outputs:
189    Service label is: WORLDWIDE_EXPRESS
190    Service name  is: WORLDWIDE EXPRESS
191
192=back
193
194=head1 AUTHOR AND LICENSING
195
196For support and licensing information refer to L<Net::UPS|Net::UPS/"AUTHOR">
197
198=cut
199