universal-parcel-scraper 0.784.1-main.4205 → 0.784.2-main.4207

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -208,14 +208,17 @@ export function parseRoyalMailTrackingResponse(payload, trackingNumber) {
208
208
  // Royal Mail also sorts the history; upstream order is not guaranteed.
209
209
  // A partial comparator can move resolved scans across unresolved overseas
210
210
  // clocks. Preserve provider order unless every scan denotes an instant.
211
+ let receiptAccepted = false;
211
212
  if (events.every(event => event.time)) {
212
213
  events.sort((a, b) => Date.parse(b.time) - Date.parse(a.time));
213
214
  // Mail a sender hands in at a parcel hub or a mail centre, or a collection
214
215
  // one of them receives first, has no acceptance scan before that receipt,
215
216
  // which the summary then calls "We've got it".
216
217
  const first = [...events].reverse().find(event => event.stage !== 'registered' && event.stage !== 'pending');
217
- if (first?.stage === 'in_transit' && FIRST_RECEIPTS.has(first.provider_code ?? ''))
218
+ if (first?.stage === 'in_transit' && FIRST_RECEIPTS.has(first.provider_code ?? '')) {
218
219
  first.stage = 'accepted';
220
+ receiptAccepted = true;
221
+ }
219
222
  }
220
223
  const trimmed = events.slice(0, MAX_EVENTS_TO_RETURN);
221
224
  const summaryCategory = cleanScalar(summary.statusCategory);
@@ -227,11 +230,12 @@ export function parseRoyalMailTrackingResponse(payload, trackingNumber) {
227
230
  const lastClock = abroad.get(lastText);
228
231
  const lastTime = lastClock ? ('time' in lastClock ? lastClock.time : null) : eventTime(lastText);
229
232
  // A summary category groups several scans: "Ready for Delivery" covers the delivery office's
230
- // receipt and the day's round. When it repeats the newest scan, a round or customs scan's code
231
- // places the parcel further along. Receipts stay under "We've got it", the acceptance.
233
+ // receipt and the day's round, "We've got it" the acceptance and the mail centre's receipt after
234
+ // a drop-off. When it repeats the newest scan, a round, customs or receipt scan's code places the
235
+ // parcel further along. Receipts after a first receipt, the acceptance itself, stay under it.
232
236
  const summaryStage = royalMailSummaryStage(summaryCategory, statusText) ?? undefined;
233
237
  const newest = trimmed[0];
234
- const repeated = newest?.stage_source === 'carrier_map' && newest.stage !== 'in_transit'
238
+ const repeated = newest?.stage_source === 'carrier_map' && !(receiptAccepted && newest.stage === 'in_transit')
235
239
  && (Boolean(lastTime) && lastTime === newest.time
236
240
  || events.every(event => event.time) && cleanScalar(summary.lastEventCode, 64) === newest.provider_code);
237
241
  const stage = repeated && furtherAlong(summaryStage, newest.stage) ? newest.stage : summaryStage;
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Universal Parcel Scraper",
5
- "version": "0.784.1-main.4205"
5
+ "version": "0.784.2-main.4207"
6
6
  },
7
7
  "paths": {
8
8
  "/health": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-parcel-scraper",
3
- "version": "0.784.1-main.4205",
3
+ "version": "0.784.2-main.4207",
4
4
  "description": "Self-hosted parcel tracking: carrier detection, dedicated scrapers and optional universal providers.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",