Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/apps/frenet/src/frenet-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import handleApiEvent from './functions-lib/events-to-frenet';
const { httpsFunctionOptions: { region } } = config.get();

export const frenet = {
cronTrackingCodes: functions.region(region).pubsub
cronTrackingCodes: functions.region(region)
.runWith({ timeoutSeconds: 540 })
.pubsub
.schedule(process.env.CRONTAB_FRENET_TRACKING_CODES || '19 * * * *')
.onRun(() => {
return handleTrackingCodes();
Expand Down
138 changes: 58 additions & 80 deletions packages/apps/frenet/src/functions-lib/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ const save = (
serviceCode,
createdAt: new Date(),
}).then(() => resolve(true))
.catch(logger.error);
.catch((err) => {
logger.error(err);
resolve(false);
});
}
});

Expand Down Expand Up @@ -47,98 +50,73 @@ const get = async (
});
});

const clear = async () => new Promise((resolve) => {
const maxAgeDays = 60;

const getDeadline = () => {
const deadline = new Date();
deadline.setMonth(deadline.getMonth() - 2);
deadline.setDate(deadline.getDate() - maxAgeDays);
return deadline;
};

getFirestore().collection(firestoreColl)
.where('createdAt', '<=', deadline)
.get()
.then((docsRef) => {
docsRef.docs.forEach((doc) => {
doc.ref.delete();
});
resolve(true);
});
});
const clear = async () => {
const docsRef = await getFirestore().collection(firestoreColl)
.where('createdAt', '<=', getDeadline())
.get();
const bulkWriter = getFirestore().bulkWriter();
docsRef.docs.forEach((doc) => {
bulkWriter.delete(doc.ref);
});
await bulkWriter.close();
};

const remove = async (
trackingCode: string,
serviceCode: string,
) => new Promise((resolve) => {
getFirestore().doc(`${firestoreColl}/${trackingCode}`)
.get()
.then(async (documentSnapshot) => {
if (documentSnapshot && documentSnapshot.exists) {
const data = documentSnapshot.data();
if (data && data.serviceCode === serviceCode) {
await documentSnapshot.ref.delete();
resolve(true);
}
}
resolve(false);
});
});
) => {
const documentSnapshot = await getFirestore().doc(`${firestoreColl}/${trackingCode}`).get();
if (documentSnapshot.exists && documentSnapshot.data()?.serviceCode === serviceCode) {
await documentSnapshot.ref.delete();
return true;
}
return false;
};

const update = async (
trackingStatus: string,
trackingStatus: string | number,
trackingCode: string,
) => new Promise((resolve) => {
const documentRef = getFirestore().doc(`${firestoreColl}/${trackingCode}`);
if (documentRef) {
documentRef.set({
trackingStatus,
updateAt: new Date().toISOString(),
}, { merge: true })
.then(() => resolve(true));
) => {
await getFirestore().doc(`${firestoreColl}/${trackingCode}`).set({
trackingStatus: String(trackingStatus),
updateAt: new Date().toISOString(),
}, { merge: true });
return true;
};

const listByStatus = async (
operator: 'in' | 'not-in',
) => {
const docsRef = await getFirestore().collection(firestoreColl)
.where('trackingStatus', operator, ['9', 9])
.get();
if (!docsRef.size) {
const err = new Error('Tracking code not found for any store :)');
err.name = 'NoTrackingCodesForUpdate';
throw err;
}
});
const list: { [x: string]: any }[] = [];
docsRef.forEach((documentSnapshot) => {
const data = documentSnapshot.data();
list.push({ ...data, createdAt: data.createdAt?.toDate?.() });
});
return list;
};

const getAll = () => new Promise((resolve, reject) => {
getFirestore().collection(firestoreColl)
.where('trackingStatus', '!=', '9')
.get()
.then((docsRef) => {
if (docsRef.size > 0) {
const list: { [x: string]: any }[] = [];
docsRef.forEach((documentSnapshot) => {
if (documentSnapshot && documentSnapshot.exists) {
const data = documentSnapshot.data();
list.push({ ...data, createAt: data.toDate() });
}
});
resolve(list);
} else {
const err = new Error('Tracking code not found for any store :)');
err.name = 'NoTrackingCodesForUpdate';
reject(err);
}
});
});
const getAll = () => listByStatus('not-in');

const getAllDelivered = () => new Promise((resolve, reject) => {
getFirestore().collection(firestoreColl)
.where('trackingStatus', '==', '9')
.get()
.then((docsRef) => {
if (docsRef.size > 0) {
const list: { [x: string]: any }[] = [];
docsRef.forEach((documentSnapshot) => {
if (documentSnapshot && documentSnapshot.exists) {
const data = documentSnapshot.data();
list.push({ ...data, createAt: data.toDate() });
}
});
resolve(list);
} else {
const err = new Error('Tracking code not found for any store :)');
err.name = 'NoTrackingCodesForUpdate';
reject(err);
}
});
});
const getAllDelivered = () => listByStatus('in');

const db = {
getDeadline,
save,
get,
clear,
Expand All @@ -155,6 +133,6 @@ export type TrackingDoc = {
trackingStatus: string,
trackingCode: string,
serviceCode: string,
createdAt: string,
createdAt: Date,
updateAt?: string
}
15 changes: 8 additions & 7 deletions packages/apps/frenet/src/functions-lib/fetch-tracking-code.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import axios from 'axios';

export default (
export default async (
trackingCode: string,
serviceCode: string,
token: string,
) => new Promise((resolve) => {
axios({
) => {
const { data } = await axios({
method: 'post',
url: 'http://api.frenet.com.br/tracking/trackinginfo',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'Accept': 'application/json',
token,
},
data: {
ShippingServiceCode: serviceCode,
TrackingNumber: trackingCode,
},
})
.then(({ data }) => resolve(data));
});
timeout: 10000,
});
return data;
};
12 changes: 8 additions & 4 deletions packages/apps/frenet/src/functions-lib/remove-delivered.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,22 @@ const removeDeliveredToFirestore = async () => {
try {
const codes: TrackingDoc[] = await db.getAllDelivered() as TrackingDoc[];
if (codes.length > 0) {
codes.forEach(async (code) => {
await Promise.all(codes.map(async (code) => {
try {
await db.remove(code.trackingCode, code.serviceCode);
logger.info('> (App Frenet) Code removed, delivered status', code);
} catch (err) {
logger.error(err);
}
});
}));
}
resolve(null);
} catch (err: any) {
if (err.name === 'NoTrackingCodesForUpdate') {
resolve(null);
} else {
reject(err);
}
} catch (err) {
reject(err);
}
});

Expand Down
36 changes: 25 additions & 11 deletions packages/apps/frenet/src/functions-lib/tracking-codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const getConfig = async () => {
};

const diffInDays = (
createdAt: string,
createdAt: Date,
) => {
const today = new Date();
const created = new Date(createdAt);
Expand All @@ -47,13 +47,21 @@ const handleTrackingCodes = async () => {
resolve(null);
}

if (codes) {
// Don't notify customers of old orders
const deadline = db.getDeadline().getTime();
const total = codes.length;
codes = codes.filter(({ createdAt }) => createdAt && createdAt.getTime() > deadline);
if (codes.length < total) {
logger.info(`> (App Frenet) Skipping ${total - codes.length} tracking codes older than deadline`);
}
}

if (!appConfig || !appConfig.frenet_access_token || !codes) {
// no config for store bye
resolve(null);
} else {
// Wait for every code before finishing, the function may be stopped
// right after resolving
await Promise.allSettled(codes.map(async (code) => {
const handleCode = async (code: TrackingDoc) => {
const serviceCode = String(code.serviceCode).startsWith('FR')
? String(code.serviceCode.replace(/^FR/, '')).trim()
: code.serviceCode;
Expand Down Expand Up @@ -119,11 +127,14 @@ const handleTrackingCodes = async () => {

if (trackingEvent && parseInt(code.trackingStatus, 10) !== trackingEvent.status) {
try {
// Don't email customers about events from long ago
const isOldEvent = diffInDays(trackingEvent.date) > 7;
await updateOrderfulfilllment(
code.orderId,
code.trackingCode,
trackingEvent.status,
trackingEvent.date,
isOldEvent,
);

await db.update(trackingEvent.status, code.trackingCode);
Expand All @@ -146,25 +157,28 @@ const handleTrackingCodes = async () => {
}
}
}
}));
};
// Limit concurrent requests to Frenet and Store API
for (let i = 0; i < codes.length; i += 10) {
// eslint-disable-next-line no-await-in-loop
await Promise.allSettled(codes.slice(i, i + 10).map(handleCode));
}
resolve(null);
}
});

if (appConfig && appConfig.frenet_access_token) {
await db.clear().catch((err) => {
logger.error('> (App Frenet) Error removing old tracking codes => ', err);
});

await checkTrackingCodes.catch((err) => {
logger.error('> (App Frenet) Error => ', err);
});

await removeDeliveredToFirestore().catch((err) => {
logger.error('> (App Frenet) Error removing Delivered to Firestore => ', err);
});

if (new Date().getHours() === 23) {
await db.clear().catch((err) => {
logger.error('> (App Frenet) Error removing old tracking codes => ', err);
});
}
}
};

Expand Down
4 changes: 4 additions & 0 deletions packages/apps/frenet/src/functions-lib/update-fulfillments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const updateFulfillments = async (
trackingCode: string,
eventType: number,
eventDate: Date,
skipNotification?: boolean,
) => {
let notes;
const status = parseStatus(eventType);
Expand All @@ -33,6 +34,9 @@ const updateFulfillments = async (
'app-frenet',
],
} as any; // TODO: incompatible type=> amount;
if (skipNotification) {
bodyFulfillments.customer_notified = true;
}

if (eventType === 2) {
notes = 'Entrega está atrasada.';
Expand Down
Loading