1: <?php
2:
3: namespace ShippoClient\Http\Request\Shipments;
4:
5: use ShippoClient\Http\Request\CommonParameter;
6: use TurmericSpice\Container;
7: use TurmericSpice\Container\InvalidAttributeException;
8: use TurmericSpice\ReadWriteAttributes;
9:
10: /**
11: * The heart of the Shippo API, a Shipment is made up of "to" and "from" Address and the Parcel to be shipped.
12: * Once created, a Shipment object can be used to retrieve shipping Rates and purchase a shipping Label.
13: */
14: class CreateObject extends CommonParameter
15: {
16: use ReadWriteAttributes {
17: toArray as public __toArray;
18: }
19:
20: const OBJECT_PURPOSE_QUOTE = 'QUOTE';
21: const OBJECT_PURPOSE_PURCHASE = 'PURCHASE';
22: const SUBMISSION_TYPE_DROPOFF = 'DROPOFF';
23: const SUBMISSION_TYPE_PICKUP = 'PICKUP';
24:
25: /**
26: * Quote Shipment can only be used to obtain quote Rates;
27: * at the same time, they accept any valid or completed Address object.
28: * Purchase Shipment can be used to obtain Rates and purchase Labels,
29: * but only accept purchase Address that have been fully entered.
30: *
31: * Required
32: *
33: * @return string
34: * @throws InvalidAttributeException
35: */
36: public function getObjectPurpose()
37: {
38: $allowed = [static::OBJECT_PURPOSE_QUOTE, static::OBJECT_PURPOSE_PURCHASE];
39:
40: return $this->attributes->mustHave('object_purpose')->asString(function ($value) use ($allowed) {
41: return in_array($value, $allowed, true);
42: });
43: }
44:
45: /**
46: * ID of the Address object that should be used as sender Address.
47: *
48: * Required
49: *
50: * @return string
51: * @throws InvalidAttributeException
52: */
53: public function getAddressFrom()
54: {
55: return $this->attributes->mustHave('address_from')->asString();
56: }
57:
58: /**
59: * ID of the Address object that should be used as recipient Address.
60: *
61: * Required
62: *
63: * @return string
64: * @throws InvalidAttributeException
65: */
66: public function getAddressTo()
67: {
68: return $this->attributes->mustHave('address_to')->asString();
69: }
70:
71: /**
72: * ID of the Parcel object to be shipped.
73: *
74: * Required
75: *
76: * @return string
77: * @throws InvalidAttributeException
78: */
79: public function getParcel()
80: {
81: return $this->attributes->mustHave('parcel')->asString();
82: }
83:
84: /**
85: * Indicates whether the parcel will be dropped off at a carrier location or will be picked up.
86: * Selecting 'PICKUP' does not request a carrier pickup.
87: * A pickup always needs to be requested separately.
88: *
89: * Optional, defaults to DROPOFF
90: *
91: * @return string
92: * @throws InvalidAttributeException
93: */
94: public function getSubmissionType()
95: {
96: $allowed = [static::SUBMISSION_TYPE_DROPOFF, static::SUBMISSION_TYPE_PICKUP];
97:
98: $submission_type = $this->attributes->mayHave('submission_type');
99: if ($submission_type->value() === null) {
100: return static::SUBMISSION_TYPE_DROPOFF;
101: }
102:
103: return $submission_type->asString(function ($value) use ($allowed) {
104: return in_array($value, $allowed, true);
105: });
106: }
107:
108: /**
109: * ID of the Transaction object of the outbound shipment.
110: * This field triggers the creation of a scan-based return shipments.
111: * See the Create a return shipment section for more details.
112: *
113: * Required for return labels
114: *
115: * @return string
116: */
117: public function getReturnOf()
118: {
119: return $this->attributes->mayHave('return_of')->asString();
120: }
121:
122: /**
123: * Desired pickup date. Must be in the format "2014-01-18T00:35:03.463Z" (ISO 8601 date).
124: * Please note that for some carriers, not all pickup dates are available.
125: * The API will return the corresponding error message if not available.
126: * If no pickup_date is given, the value will default to tomorrow's date
127: * (including Saturday or Sunday, which can lead to no carrier availability).
128: *
129: * Required if submission_type is 'PICKUP'. Defaults to current date (UTC) for 'DROPOFF'
130: *
131: * @return string
132: * @throws InvalidAttributeException
133: */
134: public function getSubmissionDate()
135: {
136: $isIOS8601Format = function ($datetime) {
137: // this pattern is not strict but is sufficient
138: return preg_match('/^(\d{4}-\d{2}-\d{2}|\d{8})[t|T]\d{2}:\d{2}:\d{2}([,|\.]\d+[z|Z]|\+\d+)$/', $datetime);
139: };
140:
141: $submission_date = $this->attributes->mayHave('submission_date');
142: if ($submission_date->value() === null) {
143: if ($this->getSubmissionType() !== static::SUBMISSION_TYPE_PICKUP) {
144: return null;
145: }
146:
147: return (new \DateTime('now', new \DateTimeZone('UTC')))->format(\DateTime::ISO8601);
148: }
149:
150: return $submission_date->asString($isIOS8601Format);
151: }
152:
153: /**
154: * ID of the Address object where the shipment will be sent back to if it is not delivered
155: * (Only available for UPS, USPS, and Fedex shipments).
156: * If this field is not set, your shipments will be returned to the address_form.
157: *
158: * Optional
159: *
160: * @return string
161: */
162: public function getAddressReturn()
163: {
164: return $this->attributes->mayHave('address_return')->asString();
165: }
166:
167: /**
168: * ID of the Customs Declarations object for an international shipment.
169: *
170: * Optional
171: *
172: * @return string
173: */
174: public function getCustomsDeclaration()
175: {
176: return $this->attributes->mayHave('customs_declaration')->asString();
177: }
178:
179: /**
180: * Total Parcel value to be insured.
181: * Please note that you need to specify the "insurance_currency" as well as the "insurance_content"
182: * (via the extra field below, if your package content is not general cargo) as well.
183: *
184: * Optional
185: *
186: * @return float
187: */
188: public function getInsuranceAmount()
189: {
190: return $this->attributes->mayHave('insurance_amount')->asFloat();
191: }
192:
193: /**
194: * Currency used for insurance_amount.
195: * The official ISO 4217 currency codes are used, e.g. "USD" or "EUR".
196: *
197: * Required if insurance_amount is set
198: *
199: * @return string
200: * @throws InvalidAttributeException
201: */
202: public function getInsuranceCurrency()
203: {
204: if ($this->attributes->mayHave('insurance_amount')->value() === null) {
205: return $this->attributes->mayHave('insurance_currency')->asString();
206: }
207:
208: return $this->attributes->mustHave('insurance_currency')->asString();
209: }
210:
211: /**
212: * An array of extra services to be requested.
213: * The following services are currently available. We are continuously adding new ones.
214: * - signature_confirmation (string, "standard" for standard signature confirmation, "adult" for adult signature)
215: * - insurance_content (string, specify package content for insurance)
216: * - saturday_delivery (boolean, marks shipment as to be delivered on a Saturday)
217: * - bypass_address_validation (boolean, bypassed address validation, if applicable)
218: * - use_manifests (boolean, shipment to be linked with a manifest (Canada Post only), if applicable)
219: * - saturday_delivery (boolean, marks shipment as to be delivered on a Saturday. Available for UPS and FedEx.)
220: * - bypass_address_validation (boolean, bypassed address validation. Available for USPS, FedEx and UPS.)
221: * - request_retail_rates (boolean, request retail/list rates. Available for FedEx.)
222: * - use_manifests (boolean, shipment to be linked with a manifest (Canada Post only), if applicable)
223: *
224: * Optional
225: *
226: * @return array
227: */
228: public function getExtra()
229: {
230: return $this->attributes->mayHave('extra')->asArray();
231: }
232:
233: /**
234: * Optional text to be printed on the shipping label.
235: *
236: * Optional
237: *
238: * @return string
239: */
240: public function getReference1()
241: {
242: return $this->attributes->mayHave('reference_1')->asString();
243: }
244:
245: /**
246: * Optional text to be printed on the shipping label.
247: *
248: * Optional
249: *
250: * @return string
251: */
252: public function getReference2()
253: {
254: return $this->attributes->mayHave('reference_2')->asString();
255: }
256:
257: /**
258: * An array of object_ids of the carrier account objects to be used for getting shipping rates for this shipment.
259: * If no carrier account object_ids are set in this field,
260: * Shippo will attempt to generate rates using all the carrier accounts that have the 'active' field set.
261: *
262: * @return string
263: */
264: public function getCarrierAccounts()
265: {
266: return $this->attributes->mayHave('carrier_accounts')->asArray();
267: }
268:
269: public function toArray()
270: {
271: return array_filter($this->__toArray());
272: }
273: }
274: