diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2026-05-12 15:35:06 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2026-05-12 15:37:29 -0400 |
| commit | 9010ebe8a581fb9db7bc6e97d40ff062fb18495f (patch) | |
| tree | 4301a455762a59d4951507c8a8781e99c6f91c6d /print.go | |
| parent | 329257be8d9fb05d3dcea49823acea0f878ed52c (diff) | |
| download | lulu-9010ebe8a581fb9db7bc6e97d40ff062fb18495f.zip | |
unmarshal GET /print-jobs response
Diffstat (limited to 'print.go')
| -rw-r--r-- | print.go | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/print.go b/print.go new file mode 100644 index 0000000..4302e6e --- /dev/null +++ b/print.go @@ -0,0 +1,193 @@ +package lulu + +import ( + "encoding/json" + "fmt" + "time" +) + +const ( + MinProductionDelay = 60 * time.Minute + MaxProductionDelay = 48 * time.Hour +) + +type getPrintJobsResp struct { + Count uint `json:"count"` + Next string `json:"next"` + Prev string `json:"previous"` + Results []PrintJob `json:"results"` +} + +type PrintJob struct { + // An email address for questions regarding the print + // job—normally, you want to use the email address of a + // developer or shop owner, not the end customer. + Contact EmailAddress `json:"contact_email"` + + Cost PrintJobCost `json:"costs"` + + Created time.Time `json:"date_created"` + Modified time.Time `json:"date_modified"` + + EstimatedShippingDates EstimatedShippingDates `json:"estimated_shipping_dates"` + + // Arbitrary string to identify and connect a print job to your + // systems. Set it to an order number, a purchase order or + // whatever else works for your particular use case. + ExternalId string `json:"external_id"` + + Id uint64 `json:"id"` + + LineItems []LineItem `json:"line_items"` + + OrderId string `json:"order_id"` + + // Delay before a newly created Print-Job is sent to production. + // Minimum is 60 minutes, maximum is 2880 minutes (=48 hours). As + // most cancellation requests occur right after an order has been + // placed, it makes sense to wait for some time before sending an + // order to production. Once production has started, orders + // cannot be canceled anymore. + ProductionDelay time.Duration + + // Target timestamp of when this job will move into production. + ProductionDue time.Time `json:"production_due_time"` + + AddressValidation ShippingAddressValidation `json:"shipping_address"` + + // The shipping level that this Print-Job is shipped with. + ShipOpt ShippingLevel `json:"shipping_level"` + + // ISO 3166-1 alpha-2 country code of the tax country determined for this job + TaxCountry string `json:"tax_country"` +} + +func (pj *PrintJob) UnmarshalJSON(data []byte) error { + type alias PrintJob // prevent infinite recursion + if err := json.Unmarshal(data, (*alias)(pj)); err != nil { + return err + } + var extra struct { + ProductionDelay uint `json:"production_delay"` + } + if err := json.Unmarshal(data, &extra); err != nil { + return fmt.Errorf("error unmarshaling %T.ProductionDelay: %w", *pj, err) + } + pj.ProductionDelay = time.Minute * time.Duration(extra.ProductionDelay) + return nil +} + +type EstimatedShippingDates struct { + ArrivalMax Date `json:"arrival_max"` + ArrivalMin Date `json:"arrival_min"` + DispatchMax Date `json:"dispatch_max"` + DispatchMin Date `json:"dispatch_min"` +} + +type LineItem struct { + // Arbitrary string to identify and connect a print job to your + // systems. Set it to an order number, a purchase order or + // whatever else works for your particular use case. + ExternalId string `json:"external_id"` + + Id uint64 `json:"id"` + + NPages uint `json:"page_count"` + + // Manufacturing options. + Mfg PkgId `json:"pod_package_id"` + + // Id of the printable. It can be used instead of PrintableNormalization. + PrintableId string `json:"printable_id"` + + // Normalization process of the cover and interior source files. + PrintableNormalization PrintableNormalization `json:"printable_normalization"` + + // Quantity of printed books. + Quantity uint `json:"quantity"` + + Status LineItemStatus `json:"status"` + + // Title of the line item. Should be on the cover. + Title string `json:"title"` + + // Tracking id for this line item's shipment. + TrackingId string `json:"tracking_id"` + + // A list of tracking urls for this line item's shipment. + TrackingUrls []string `json:"tracking_urls"` + + // Name of the carrier handling the shipment. + Carrier string `json:"carrier_name"` +} + +// PrintableNormalization represents the normalization processes of the +// interior and cover source files. +type PrintableNormalization struct { + Cover NormalizationJob `json:"cover"` + Interior NormalizationJob `json:"interior"` +} + +// NormalizationJob represents the normalization process of an interior +// or cover source file. +type NormalizationJob struct { + JobId uint `json:"job_id"` + NormalizedFile NormalizedFile `json:"normalized_file"` + SrcMd5Sum string `json:"source_md5_sum"` // md5 hash of the source file. + SrcUrl string `json:"source_url"` // URL of the source file. +} + +// NormalizedFile represents a file on the server that was created by +// normalizing a cover or interior source file. +type NormalizedFile struct { + Id uint64 `json:"file_id"` + Name string `json:"filename"` +} + +type LineItemStatus struct { + Messages LineItemStatusMessages `json:"messages"` + Status OrderStatus `json:"name"` +} + +type LineItemStatusMessages struct { + Delay time.Duration // Expected delay due to the error, if present. + Error string `json:"error"` + Info string `json:"info"` + PrintableNormalization PrintableNormalization `json:"printable_normalization"` + Timestamp time.Time `json:"timestamp"` // Timestamp of the last status change. + TrackingUrls []string + TrackingId string `json:"tracking_id"` // Tracking ID for this line item's shipment. + Carrier string `json:"carrier_name"` // Name of the carrier handling the shipment. +} + +func (msgs *LineItemStatusMessages) UnmarshalJSON(data []byte) error { + type alias LineItemStatusMessages // prevent infinite recursion + if err := json.Unmarshal(data, (*alias)(msgs)); err != nil { + return err + } + + var extra struct { + Delay string `json:"delay"` + TrackingUrls json.RawMessage `json:"tracking_urls"` + } + if err := json.Unmarshal(data, &extra); err != nil { + return err + } + + var err error + if len(extra.Delay) > 0 { + msgs.Delay, err = time.ParseDuration(fmt.Sprintf("%sh", extra.Delay)) + if err != nil { + return fmt.Errorf("error unmarshaling %T.Delay: %w", *msgs, err) + } + } + + if len(extra.TrackingUrls) > 0 { + msgs.TrackingUrls, err = unmarshalSliceOrVal[string](extra.TrackingUrls) + if err != nil { + return fmt.Errorf("error unmarshaling %T.TrackingUrls: %w", *msgs, err) + } + } + + return nil +} |