Refactoring file names and structure, adding retries and proper closure to API calls, updating README, adding footer to Discord notifications
This commit is contained in:
parent
9b86936a49
commit
5dd3a06864
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
logs/*
|
@ -1,8 +1,8 @@
|
|||||||
# ShipmentNotifier
|
# ShipmentNotifier
|
||||||
|
|
||||||
Script that polls the Amazon SP-API for most recent shipments, if a shipment is found that has been created in the last 6 hours, sends a Discord notification to a provided webhook.
|
Script that polls the Amazon SP-API for most recent shipments, if a shipment is found that has been created in the last 14 days, sends a Discord notification to a provided webhook.
|
||||||
|
|
||||||
- Acceptable time delta: < 6 hours - accounts for SP-API delays and time for the shipment to transition to 'Shipped'
|
- Acceptable time delta: < 14 days - accounts for SP-API delays and time for the shipment to transition to 'Shipped'
|
||||||
- Number of shipments to look for: 10
|
- Number of shipments to look for: 10
|
||||||
- Stores UID of shipments that a notification has previously been sent for to avoid sending duplicate notifications
|
- Stores UID of shipments that a notification has previously been sent for to avoid sending duplicate notifications
|
||||||
- Recommended to run every 10 minutes via cron
|
- Runs every 10 minutes via cron
|
@ -1,8 +1,16 @@
|
|||||||
from log import log, cleanLogs
|
from ShipmentNotifierLogger import log, cleanLogs
|
||||||
from timeOperations import isInboundShipmentPlanWithinSpecifiedDelta
|
from ShipmentNotifierAmazonAPI import (
|
||||||
from amazonAPI import getAccessToken, getInboundShipmentData, getInboundShipmentPlans, getInboundShipmentPlan, getProductName
|
getInboundShipmentData,
|
||||||
from sentNotifications import isInboundShipmentPlanIDInSentNotifications, updateSentNotifications
|
getInboundShipmentPlans,
|
||||||
from discordNotifications import sendDiscordNotification
|
getInboundShipmentPlan,
|
||||||
|
getProductName
|
||||||
|
)
|
||||||
|
from ShipmentNotifierHelpers import (
|
||||||
|
isInboundShipmentPlanIDInSentNotifications,
|
||||||
|
updateSentNotifications,
|
||||||
|
sendDiscordNotification,
|
||||||
|
isInboundShipmentPlanWithinSpecifiedDelta
|
||||||
|
)
|
||||||
|
|
||||||
def parseInboundShipmentPlans():
|
def parseInboundShipmentPlans():
|
||||||
log('\U0001F504 Getting inbound shipment plans...', 'info')
|
log('\U0001F504 Getting inbound shipment plans...', 'info')
|
||||||
|
119
ShipmentNotifierAmazonAPI.py
Normal file
119
ShipmentNotifierAmazonAPI.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import requests
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from ShipmentNotifierLogger import log
|
||||||
|
|
||||||
|
SETTINGS = yaml.safe_load(open('../ShipmentNotifierSettings.yaml'))
|
||||||
|
|
||||||
|
def getAccessToken(settings=SETTINGS):
|
||||||
|
with requests.post(
|
||||||
|
'https://api.amazon.com/auth/o2/token',
|
||||||
|
{
|
||||||
|
'grant_type': 'refresh_token',
|
||||||
|
'refresh_token': settings['REFRESH_TOKEN'],
|
||||||
|
'client_id': settings['CLIENT_ID'],
|
||||||
|
'client_secret': settings['CLIENT_SECRET'],
|
||||||
|
}
|
||||||
|
) as accessToken:
|
||||||
|
if accessToken.status_code == 200:
|
||||||
|
accessTokenJSON = accessToken.json()
|
||||||
|
|
||||||
|
return accessTokenJSON['access_token']
|
||||||
|
|
||||||
|
def getProductName(MSKU, maxRetries=50, settings=SETTINGS):
|
||||||
|
for attempt in range(maxRetries):
|
||||||
|
with requests.get(
|
||||||
|
settings['SPAPI_ENDPOINT'] + '/listings/2021-08-01/items/' + settings['SELLER_ID'] + f'/{MSKU}',
|
||||||
|
headers = {
|
||||||
|
'x-amz-access-token': getAccessToken(),
|
||||||
|
},
|
||||||
|
params = {
|
||||||
|
'marketplaceIds': settings['MARKETPLACE_ID']
|
||||||
|
},
|
||||||
|
) as productNameResponse:
|
||||||
|
if productNameResponse.status_code == 200:
|
||||||
|
productName = productNameResponse.json()['summaries'][0]['itemName']
|
||||||
|
if attempt + 1 > 1:
|
||||||
|
log(f"SP-API call for product name completed on attempt {attempt + 1}", 'info')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
log(f"SP-API call for product name failed, status code: {productNameResponse.status_code} JSON response: {productNameResponse.json()}", 'error')
|
||||||
|
log(f'Headers: {productNameResponse.headers}', 'debug')
|
||||||
|
|
||||||
|
return productName
|
||||||
|
|
||||||
|
def getInboundShipmentPlans(maxRetries=50, settings=SETTINGS):
|
||||||
|
for attempt in range(maxRetries):
|
||||||
|
with requests.get(
|
||||||
|
settings['SPAPI_ENDPOINT'] + '/inbound/fba/2024-03-20/inboundPlans?pageSize=10&sortBy=CREATION_TIME&sortOrder=DESC&status=SHIPPED',
|
||||||
|
headers = {
|
||||||
|
'x-amz-access-token': getAccessToken(),
|
||||||
|
}
|
||||||
|
) as inboundShipmentPlansResponse:
|
||||||
|
if inboundShipmentPlansResponse.status_code == 200:
|
||||||
|
inboundShipmentPlans = inboundShipmentPlansResponse.json()['inboundPlans']
|
||||||
|
if attempt + 1 > 1:
|
||||||
|
log(f"SP-API call for inbound shipment plans completed on attempt {attempt + 1}", 'info')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
log(f"SP-API call for inbound shipment plans failed, status code: {inboundShipmentPlansResponse.status_code} JSON response: {inboundShipmentPlansResponse.json()}", 'error')
|
||||||
|
log(f'Headers: {inboundShipmentPlansResponse.headers}', 'debug')
|
||||||
|
|
||||||
|
return inboundShipmentPlans
|
||||||
|
|
||||||
|
def getInboundShipmentPlan(inboundShipmentPlanID, maxRetries=50, settings=SETTINGS):
|
||||||
|
for attempt in range(maxRetries):
|
||||||
|
with requests.get(
|
||||||
|
settings['SPAPI_ENDPOINT'] + f'/inbound/fba/2024-03-20/inboundPlans/{inboundShipmentPlanID}/items',
|
||||||
|
headers = {
|
||||||
|
'x-amz-access-token': getAccessToken(),
|
||||||
|
}
|
||||||
|
) as inboundShipmentPlanResponse:
|
||||||
|
if inboundShipmentPlanResponse.status_code == 200:
|
||||||
|
inboundShipmentPlan = inboundShipmentPlanResponse.json()
|
||||||
|
if attempt + 1 > 1:
|
||||||
|
log(f"SP-API call for inbound shipment plan completed on attempt {attempt + 1}", 'info')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
log(f"SP-API call for inbound shipment plan failed, status code: {inboundShipmentPlanResponse.status_code} JSON response: {inboundShipmentPlanResponse.json()}", 'error')
|
||||||
|
log(f'Headers: {inboundShipmentPlanResponse.headers}', 'debug')
|
||||||
|
|
||||||
|
return inboundShipmentPlan
|
||||||
|
|
||||||
|
def getInboundShipmentData(inboundPlanId, maxRetries=50, settings=SETTINGS):
|
||||||
|
inboundShipmentData = {inboundPlanId: {'destinations': [], 'shipmentIDs': []}}
|
||||||
|
|
||||||
|
for attempt in range(maxRetries):
|
||||||
|
with requests.get(
|
||||||
|
settings['SPAPI_ENDPOINT'] + f'/inbound/fba/2024-03-20/inboundPlans/{inboundPlanId}/placementOptions',
|
||||||
|
headers = {
|
||||||
|
'x-amz-access-token': getAccessToken(),
|
||||||
|
}
|
||||||
|
) as inboundPlanShipmentDataResponse:
|
||||||
|
if inboundPlanShipmentDataResponse.status_code == 200:
|
||||||
|
if attempt + 1 > 1:
|
||||||
|
log(f"SP-API call for inbound shipment data completed on attempt {attempt + 1}", 'info')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
log(f"SP-API call for inbound shipment data failed, status code: {inboundPlanShipmentDataResponse.status_code} JSON response: {inboundPlanShipmentDataResponse.json()}", 'error')
|
||||||
|
log(f'Headers: {inboundPlanShipmentDataResponse.headers}', 'debug')
|
||||||
|
|
||||||
|
for shipmentID in inboundPlanShipmentDataResponse.json()['placementOptions'][0]['shipmentIds']:
|
||||||
|
for attempt in range(maxRetries):
|
||||||
|
with requests.get(
|
||||||
|
settings['SPAPI_ENDPOINT'] + f'/inbound/fba/2024-03-20/inboundPlans/{inboundPlanId}/shipments/{shipmentID}',
|
||||||
|
headers = {
|
||||||
|
'x-amz-access-token': getAccessToken(),
|
||||||
|
}
|
||||||
|
) as individualShipmentDataResponse:
|
||||||
|
if inboundPlanShipmentDataResponse.status_code == 200:
|
||||||
|
inboundShipmentData[inboundPlanId]['shipmentIDs'].append(individualShipmentDataResponse.json()['shipmentConfirmationId'])
|
||||||
|
inboundShipmentData[inboundPlanId]['destinations'].append(individualShipmentDataResponse.json()['destination']['warehouseId'])
|
||||||
|
if attempt + 1 > 1:
|
||||||
|
log(f"SP-API call for individual shipment data completed on attempt {attempt + 1}", 'info')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
log(f"SP-API call for individual shipment data failed, status code: {individualShipmentDataResponse.status_code} JSON response: {individualShipmentDataResponse.json()}", 'error')
|
||||||
|
log(f'Headers: {individualShipmentDataResponse.headers}', 'debug')
|
||||||
|
|
||||||
|
return inboundShipmentData
|
75
ShipmentNotifierHelpers.py
Normal file
75
ShipmentNotifierHelpers.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import json
|
||||||
|
import yaml
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from datetime import (
|
||||||
|
datetime,
|
||||||
|
timedelta
|
||||||
|
)
|
||||||
|
from ShipmentNotifierLogger import log
|
||||||
|
|
||||||
|
SETTINGS = yaml.safe_load(open('../ShipmentNotifierSettings.yaml'))
|
||||||
|
|
||||||
|
def sendDiscordNotification(*args, settings=SETTINGS):
|
||||||
|
newLine = '\n'
|
||||||
|
shipmentNotification = requests.post(
|
||||||
|
SETTINGS['DISCORD_WEBHOOK'],
|
||||||
|
json = {
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
"title": ":package: New Inbound Shipment Detected :package:",
|
||||||
|
"url": f"https://sellercentral.amazon.co.uk/fba/sendtoamazon?wf={args[0]}",
|
||||||
|
"color": 4886754,
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Shipment Information",
|
||||||
|
"value": f'''
|
||||||
|
> Inbound Shipment Plan ID: {args[0]}
|
||||||
|
> Creation Date: {args[1]['creationDate']}
|
||||||
|
> Destination Fulfilment Centres: {', '.join(destination for destination in args[1]['destinations'])}
|
||||||
|
> Shipments: {', '.join(f'[{shipmentID}](https://sellercentral.amazon.co.uk/fba/inbound-shipment/summary/{shipmentID}/contents)' for shipmentID in args[1]['shipmentIDs'])}
|
||||||
|
'''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shipment Contents",
|
||||||
|
"value": f'''
|
||||||
|
{newLine.join(f"> {MSKU}: {Count}" for MSKU, Count in args[1]['contents'].items())}
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
def updateSentNotifications(inboundPlanId):
|
||||||
|
with open('../ShipmentNotifierSentNotifications.json') as sentNotificationsJSON:
|
||||||
|
sentNotifications = json.load(sentNotificationsJSON)
|
||||||
|
|
||||||
|
sentNotifications['sentNotifications'].append(inboundPlanId)
|
||||||
|
|
||||||
|
with open('../ShipmentNotifierSentNotifications.json', mode='w') as outputSentNotifications:
|
||||||
|
outputSentNotifications.write(json.dumps(sentNotifications, indent=4))
|
||||||
|
|
||||||
|
def isInboundShipmentPlanIDInSentNotifications(inboundShipmentPlanId):
|
||||||
|
with open('../ShipmentNotifierSentNotifications.json') as sentNotificationsJSON:
|
||||||
|
sentNotifications = json.load(sentNotificationsJSON)
|
||||||
|
|
||||||
|
if inboundShipmentPlanId in sentNotifications['sentNotifications']:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def isInboundShipmentPlanWithinSpecifiedDelta(inboundShipmentPlanCreationTime, delta=20160):
|
||||||
|
currentTime = datetime.now()
|
||||||
|
inboundShipmentPlanTime = datetime.strptime(inboundShipmentPlanCreationTime, '%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
timeDelta = currentTime - inboundShipmentPlanTime
|
||||||
|
|
||||||
|
log(f'Current time: {currentTime}', 'info')
|
||||||
|
log(f'Inbound shipment plan creation time: {inboundShipmentPlanTime}', 'info')
|
||||||
|
log(f'Time delta: {timeDelta}', 'info')
|
||||||
|
|
||||||
|
if timeDelta < timedelta(minutes=delta):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
77
amazonAPI.py
77
amazonAPI.py
@ -1,77 +0,0 @@
|
|||||||
import requests
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
from log import log
|
|
||||||
from discordNotifications import sendDiscordNotification
|
|
||||||
from sentNotifications import isInboundShipmentPlanIDInSentNotifications, updateSentNotifications
|
|
||||||
from timeOperations import isInboundShipmentPlanWithinSpecifiedDelta
|
|
||||||
|
|
||||||
SETTINGS = yaml.safe_load(open('settings.yaml'))
|
|
||||||
|
|
||||||
def getAccessToken(settings=SETTINGS):
|
|
||||||
accessToken = requests.post(
|
|
||||||
'https://api.amazon.com/auth/o2/token',
|
|
||||||
{
|
|
||||||
'grant_type': 'refresh_token',
|
|
||||||
'refresh_token': settings['REFRESH_TOKEN'],
|
|
||||||
'client_id': settings['CLIENT_ID'],
|
|
||||||
'client_secret': settings['CLIENT_SECRET'],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return accessToken.json()['access_token']
|
|
||||||
|
|
||||||
def getProductName(MSKU, settings=SETTINGS):
|
|
||||||
product = requests.get(
|
|
||||||
settings['SPAPI_ENDPOINT'] + '/listings/2021-08-01/items/' + settings['SELLER_ID'] + f'/{MSKU}',
|
|
||||||
headers = {
|
|
||||||
'x-amz-access-token': getAccessToken(),
|
|
||||||
},
|
|
||||||
params = {
|
|
||||||
'marketplaceIds': settings['MARKETPLACE_ID']
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return product.json()['summaries'][0]['itemName']
|
|
||||||
|
|
||||||
def getInboundShipmentPlans(settings=SETTINGS):
|
|
||||||
inboundShipmentPlans = requests.get(
|
|
||||||
settings['SPAPI_ENDPOINT'] + '/inbound/fba/2024-03-20/inboundPlans?pageSize=10&sortBy=CREATION_TIME&sortOrder=DESC&status=SHIPPED',
|
|
||||||
headers = {
|
|
||||||
'x-amz-access-token': getAccessToken(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return inboundShipmentPlans.json()['inboundPlans']
|
|
||||||
|
|
||||||
def getInboundShipmentPlan(inboundShipmentPlanID, settings=SETTINGS):
|
|
||||||
inboundShipmentPlan = requests.get(
|
|
||||||
settings['SPAPI_ENDPOINT'] + f'/inbound/fba/2024-03-20/inboundPlans/{inboundShipmentPlanID}/items',
|
|
||||||
headers = {
|
|
||||||
'x-amz-access-token': getAccessToken(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return inboundShipmentPlan.json()
|
|
||||||
|
|
||||||
def getInboundShipmentData(inboundPlanId, settings=SETTINGS):
|
|
||||||
inboundShipmentData = {inboundPlanId: {'destinations': [], 'shipmentIDs': []}}
|
|
||||||
|
|
||||||
inboundPlanShipmentData = requests.get(
|
|
||||||
settings['SPAPI_ENDPOINT'] + f'/inbound/fba/2024-03-20/inboundPlans/{inboundPlanId}/placementOptions',
|
|
||||||
headers = {
|
|
||||||
'x-amz-access-token': getAccessToken(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
for shipmentID in inboundPlanShipmentData.json()['placementOptions'][0]['shipmentIds']:
|
|
||||||
individualShipmentData = requests.get(
|
|
||||||
settings['SPAPI_ENDPOINT'] + f'/inbound/fba/2024-03-20/inboundPlans/{inboundPlanId}/shipments/{shipmentID}',
|
|
||||||
headers = {
|
|
||||||
'x-amz-access-token': getAccessToken(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
inboundShipmentData[inboundPlanId]['shipmentIDs'].append(individualShipmentData.json()['shipmentConfirmationId'])
|
|
||||||
inboundShipmentData[inboundPlanId]['destinations'].append(individualShipmentData.json()['destination']['warehouseId'])
|
|
||||||
|
|
||||||
return inboundShipmentData
|
|
@ -1,36 +0,0 @@
|
|||||||
import yaml
|
|
||||||
import requests
|
|
||||||
|
|
||||||
SETTINGS = yaml.safe_load(open('settings.yaml'))
|
|
||||||
|
|
||||||
def sendDiscordNotification(*args, settings=SETTINGS):
|
|
||||||
newLine = '\n'
|
|
||||||
shipmentNotification = requests.post(
|
|
||||||
SETTINGS['DISCORD_WEBHOOK'],
|
|
||||||
json = {
|
|
||||||
"embeds": [
|
|
||||||
{
|
|
||||||
"title": ":package: New Inbound Shipment Detected :package:",
|
|
||||||
"url": f"https://sellercentral.amazon.co.uk/fba/sendtoamazon?wf={args[0]}",
|
|
||||||
"color": 4886754,
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "Shipment Information",
|
|
||||||
"value": f'''
|
|
||||||
> Inbound Shipment Plan ID: {args[0]}
|
|
||||||
> Creation Date: {args[1]['creationDate']}
|
|
||||||
> Destination Fulfilment Centres: {', '.join(destination for destination in args[1]['destinations'])}
|
|
||||||
> Shipments: {', '.join(f'[{shipmentID}](https://sellercentral.amazon.co.uk/fba/inbound-shipment/summary/{shipmentID}/contents)' for shipmentID in args[1]['shipmentIDs'])}
|
|
||||||
'''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Shipment Contents",
|
|
||||||
"value": f'''
|
|
||||||
{newLine.join(f"> {MSKU}: {Count}" for MSKU, Count in args[1]['contents'].items())}
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
)
|
|
@ -1,31 +0,0 @@
|
|||||||
[INFO] 🔄 Getting shipments...
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.979052
|
|
||||||
[INFO] Shipment creation time: 2024-07-12 13:07:50
|
|
||||||
[INFO] Time delta: 8:29:14.979052
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.981162
|
|
||||||
[INFO] Shipment creation time: 2024-07-10 09:34:31
|
|
||||||
[INFO] Time delta: 2 days, 12:02:33.981162
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.981349
|
|
||||||
[INFO] Shipment creation time: 2024-07-09 15:47:43
|
|
||||||
[INFO] Time delta: 3 days, 5:49:21.981349
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.981507
|
|
||||||
[INFO] Shipment creation time: 2024-07-08 12:23:20
|
|
||||||
[INFO] Time delta: 4 days, 9:13:44.981507
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.981663
|
|
||||||
[INFO] Shipment creation time: 2024-07-05 12:57:09
|
|
||||||
[INFO] Time delta: 7 days, 8:39:55.981663
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.981816
|
|
||||||
[INFO] Shipment creation time: 2024-07-05 11:39:06
|
|
||||||
[INFO] Time delta: 7 days, 9:57:58.981816
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.981968
|
|
||||||
[INFO] Shipment creation time: 2024-07-04 13:50:17
|
|
||||||
[INFO] Time delta: 8 days, 7:46:47.981968
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.982168
|
|
||||||
[INFO] Shipment creation time: 2024-07-03 13:29:03
|
|
||||||
[INFO] Time delta: 9 days, 8:08:01.982168
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.982320
|
|
||||||
[INFO] Shipment creation time: 2024-07-02 14:06:09
|
|
||||||
[INFO] Time delta: 10 days, 7:30:55.982320
|
|
||||||
[INFO] Current time: 2024-07-12 21:37:04.982470
|
|
||||||
[INFO] Shipment creation time: 2024-07-01 14:54:48
|
|
||||||
[INFO] Time delta: 11 days, 6:42:16.982470
|
|
@ -1,19 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
def updateSentNotifications(inboundPlanId):
|
|
||||||
with open('SentNotifications.json') as sentNotificationsJSON:
|
|
||||||
sentNotifications = json.load(sentNotificationsJSON)
|
|
||||||
|
|
||||||
sentNotifications['sentNotifications'].append(inboundPlanId)
|
|
||||||
|
|
||||||
with open('SentNotifications.json', mode='w') as outputSentNotifications:
|
|
||||||
outputSentNotifications.write(json.dumps(sentNotifications, indent=4))
|
|
||||||
|
|
||||||
def isInboundShipmentPlanIDInSentNotifications(inboundShipmentPlanId):
|
|
||||||
with open('SentNotifications.json') as sentNotificationsJSON:
|
|
||||||
sentNotifications = json.load(sentNotificationsJSON)
|
|
||||||
|
|
||||||
if inboundShipmentPlanId in sentNotifications['sentNotifications']:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
@ -1,16 +0,0 @@
|
|||||||
from datetime import datetime, timedelta
|
|
||||||
from log import log
|
|
||||||
|
|
||||||
def isInboundShipmentPlanWithinSpecifiedDelta(inboundShipmentPlanCreationTime, delta=20160):
|
|
||||||
currentTime = datetime.now()
|
|
||||||
inboundShipmentPlanTime = datetime.strptime(inboundShipmentPlanCreationTime, '%Y-%m-%dT%H:%M:%SZ')
|
|
||||||
timeDelta = currentTime - inboundShipmentPlanTime
|
|
||||||
|
|
||||||
log(f'Current time: {currentTime}', 'info')
|
|
||||||
log(f'Inbound shipment plan creation time: {inboundShipmentPlanTime}', 'info')
|
|
||||||
log(f'Time delta: {timeDelta}', 'info')
|
|
||||||
|
|
||||||
if timeDelta < timedelta(minutes=delta):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
Loading…
x
Reference in New Issue
Block a user