Found more code examples from STM. Used claude to generate a summary (CLAUDE.md)
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
'''
|
||||
Created on Apr 27, 2017
|
||||
|
||||
Import Glen Raven ASN data into the DB
|
||||
|
||||
@author: Wes
|
||||
'''
|
||||
from alert import send_alert_html
|
||||
|
||||
import datetime, csv, logging, sys, os, StringIO
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from operator import itemgetter
|
||||
from itertools import groupby
|
||||
|
||||
RECIPIENTS = ['admin@example.com']
|
||||
SUBJECT = 'Inbound Glen Raven ASN Processed'
|
||||
MESSAGE = None
|
||||
|
||||
TEST_MODE = False
|
||||
GR_AP_ACCOUNT = '001306'
|
||||
JOMAR_PO_ORDER_TYPE = 'JB'
|
||||
|
||||
VN = 0
|
||||
PACK_SLIP = 1
|
||||
YARN_ITEM = 2
|
||||
COLOR_DESC = 3
|
||||
PO_DO = 4
|
||||
LOT_NUMBER = 5
|
||||
CASE = 6
|
||||
CASE_UNITS = 7
|
||||
GRS_LBS = 8
|
||||
NET_LBS = 9
|
||||
TRNS_DATE = 9
|
||||
SHIP_DATE = 10
|
||||
SHIP_VIA = 11
|
||||
|
||||
logger = None
|
||||
LOG_LEVEL = logging.DEBUG
|
||||
engine = create_engine("mssql+pyodbc://jsisbprod", echo=False)
|
||||
#engine = create_engine("mssql+pyodbc://@JTest", echo=False)
|
||||
Base = declarative_base(engine)
|
||||
metadata = Base.metadata
|
||||
|
||||
#---------------------------------------------------------------------#
|
||||
class PSPASN00(Base):
|
||||
__tablename__ = 'PSPASN00' #Inboud ASN table
|
||||
__table_args__ = {'autoload':True}
|
||||
class TXEYAT00(Base):
|
||||
__tablename__ = 'TXEYAT00' #Vendor Item Cross reference table
|
||||
__table_args__ = {'autoload':True}
|
||||
class TXUYUF01(Base):
|
||||
__tablename__ = 'TXUYUF01' #Order Detail Table
|
||||
__table_args__ = {'autoload':True}
|
||||
#---------------------------------------------------------------------#
|
||||
|
||||
class ItemTranslationError(RuntimeError):
|
||||
''' Raising this if we fail to lookup STM item using GR item '''
|
||||
|
||||
class POError(RuntimeError):
|
||||
''' Raising this if we fail to lookup required info from relevant PO '''
|
||||
|
||||
def loadSession():
|
||||
global engine
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
return session
|
||||
|
||||
def initializeLogger(name='log'):
|
||||
global logger
|
||||
global MESSAGE
|
||||
#logger = logging.getLogger(__name__)
|
||||
logger = logging.getLogger(name)
|
||||
if len(logger.handlers) > 0:
|
||||
return logger
|
||||
logger.setLevel(LOG_LEVEL)
|
||||
handler = logging.FileHandler('D:\\FTP\\logs\\' + name + '.log')
|
||||
handler.setLevel(LOG_LEVEL)
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
|
||||
#Also send logs > DEBUG to stdout
|
||||
ch = logging.StreamHandler(sys.stdout)
|
||||
ch.setLevel(logging.INFO)
|
||||
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
|
||||
ch.setFormatter(formatter)
|
||||
logger.addHandler(ch)
|
||||
|
||||
#Capture log messages in a string for e-mail alert
|
||||
MESSAGE = StringIO.StringIO()
|
||||
sh = logging.StreamHandler(MESSAGE)
|
||||
sh.setLevel(logging.DEBUG)
|
||||
sh.setFormatter(formatter)
|
||||
logger.addHandler(sh)
|
||||
|
||||
'''
|
||||
Query the vendor item xref table to translate GR --> STM
|
||||
|
||||
Likely reasons this failed:
|
||||
* _gr_item_ not entered as a xref for any of our items
|
||||
* _gr_item_ entered for more than 1 of our items
|
||||
|
||||
Returns the matching STM item number if found.
|
||||
'''
|
||||
def GRtoSTM(gr_item):
|
||||
global session
|
||||
global logger
|
||||
q = session.query(TXEYAT00).filter(TXEYAT00.UALNR == GR_AP_ACCOUNT, TXEYAT00.UALAN == gr_item)
|
||||
if(q.count() == 1):
|
||||
for row in q:
|
||||
return row.UAANR
|
||||
else:
|
||||
logger.debug('GRtoSTM() rows returned: %s', q.count())
|
||||
return None
|
||||
|
||||
'''
|
||||
Query the order detail table by _po_ and _item_.
|
||||
|
||||
Likely reasons this failed:
|
||||
* _po_ doesn't actually exist
|
||||
* _item_ not ordered on _po_
|
||||
* _item_ appears on more than 1 line on _po_
|
||||
|
||||
Returns the line number of _item_ on _po_ if found.
|
||||
'''
|
||||
def getLineNum(po, item):
|
||||
global session
|
||||
global logger
|
||||
q = session.query(TXUYUF01).filter(TXUYUF01.VBLA == JOMAR_PO_ORDER_TYPE, TXUYUF01.VBLN == po, TXUYUF01.VANR == item)
|
||||
if(q.count() == 1):
|
||||
for row in q:
|
||||
return row.VLFN
|
||||
else:
|
||||
return None
|
||||
|
||||
def processInboundGRASN(inFile):
|
||||
global MESSAGE
|
||||
global session
|
||||
os.chdir('D:\FTP')
|
||||
initializeLogger('gr_856_inbound_interface')
|
||||
logger.info('****************************************')
|
||||
fileName = inFile.split('\\')[-1]
|
||||
rawLines = []
|
||||
session = loadSession()
|
||||
|
||||
logger.info('Loading: %s', inFile)
|
||||
try:
|
||||
f = open(inFile, 'r')
|
||||
except IOError:
|
||||
logger.fatal('Unable to load file. Did you specify the full path? Exiting...')
|
||||
return
|
||||
filename = inFile.split('\\')[-1]
|
||||
|
||||
try:
|
||||
reader = csv.reader(f)
|
||||
for row in reader:
|
||||
rawLines.append(row)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
rawLines.pop(0) #Remove first line as it is just column headers
|
||||
|
||||
if(len(rawLines) == 0):
|
||||
logger.warning('They sent us an empty file...')
|
||||
logger.info('Moving %s to D:\\FTP\\OLD\\GR\\', inFile)
|
||||
os.rename(inFile, 'OLD\\GR\\' + fileName)
|
||||
session.close()
|
||||
return
|
||||
|
||||
rawLines.sort(key=itemgetter(PO_DO)) #Ensure raw data is sorted by PO number
|
||||
purchaseOrders = groupby(rawLines, itemgetter(PO_DO)) #Create group by iterator based on PO number
|
||||
|
||||
#For each unique PO appearing in this transmission
|
||||
for poNumber, lines in purchaseOrders:
|
||||
logger.info('****')
|
||||
logger.info('Processing records for purchase order: %s', poNumber)
|
||||
|
||||
#For each record of this transmission on poNumber
|
||||
for line in lines:
|
||||
if line[VN] not in ['19']:
|
||||
logger.warn('Encountered record with invalid vendor number!')
|
||||
logger.warn(line)
|
||||
continue
|
||||
|
||||
#Translate GR item to STM item
|
||||
stm_item = GRtoSTM(line[YARN_ITEM])
|
||||
|
||||
if stm_item:
|
||||
#Query order detail by PO and STM item to get the correct PO line number
|
||||
line_num = getLineNum(poNumber, stm_item)
|
||||
|
||||
if line_num:
|
||||
logger.info('Processing Case: %s (%s)', line[CASE], stm_item)
|
||||
asn = PSPASN00()
|
||||
asn.BUSINESS_UNIT = '001'
|
||||
asn.PLANT = '00'
|
||||
asn.VENDOR = GR_AP_ACCOUNT
|
||||
asn.PO_NUMBER = poNumber
|
||||
asn.PO_ITEM = stm_item
|
||||
asn.PO_LINE = line_num
|
||||
asn.PACKING_SLIP = line[PACK_SLIP]
|
||||
asn.CASE_NUMBER = line[CASE]
|
||||
asn.QTY_GROSS = line[GRS_LBS]
|
||||
asn.QTY_NET = line[NET_LBS]
|
||||
asn.VENDOR_LOT = line[LOT_NUMBER]
|
||||
session.add(asn)
|
||||
else:
|
||||
logger.error('Failed to find a line on PO %s for: %s', poNumber, stm_item)
|
||||
|
||||
try:
|
||||
send_alert_html(RECIPIENTS, 'Error Processing GR ASN', attachments=[inFile], message=MESSAGE.getvalue())
|
||||
except:
|
||||
logger.error('Unable to send e-mail. Is the internet out?')
|
||||
|
||||
raise POError('Failed to retrieve PO info from database', poNumber, stm_item)
|
||||
else:
|
||||
logger.error('Failed to lookup STM item number for GR Item: %s', line[YARN_ITEM])
|
||||
|
||||
try:
|
||||
send_alert_html(RECIPIENTS, 'Error Processing GR ASN', attachments=[inFile], message=MESSAGE.getvalue())
|
||||
except:
|
||||
logger.error('Unable to send e-mail. Is the internet out?')
|
||||
|
||||
raise ItemTranslationError('Failed to lookup STM item number for GR Item', line[YARN_ITEM])
|
||||
|
||||
if not TEST_MODE:
|
||||
logger.info('Writing records to database...')
|
||||
session.commit()
|
||||
else:
|
||||
logger.warn('**TEST MODE ENABLED ROLLING BACK TRANSACTIONS**')
|
||||
session.rollback()
|
||||
|
||||
session.close()
|
||||
|
||||
if not TEST_MODE:
|
||||
try:
|
||||
logger.info('Sending e-mail alert...')
|
||||
send_alert_html(RECIPIENTS, SUBJECT, attachments=[inFile], message=MESSAGE.getvalue())
|
||||
except:
|
||||
logger.error('Unable to send e-mail. Is the internet out?')
|
||||
|
||||
logger.info('Moving ' + inFile + ' to D:\\FTP\\OLD\\GR\\')
|
||||
os.rename(inFile, 'OLD\\GR\\' + fileName)
|
||||
|
||||
MESSAGE.truncate(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if(len(sys.argv) < 2):
|
||||
print 'Must supply fully qualified path to csv file ex:'
|
||||
print 'python gr_856_in.py D:\\FTP\\INCOMING\\GR_ASN_0100334639.csv'
|
||||
else:
|
||||
processInboundGRASN(sys.argv[1])
|
||||
Reference in New Issue
Block a user