Found more code examples from STM. Used claude to generate a summary (CLAUDE.md)
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
'''
|
||||
Created on Jul 15, 2015
|
||||
|
||||
@author: Wes
|
||||
'''
|
||||
from alert import send_alert_html
|
||||
from glob import glob
|
||||
|
||||
import os, sys, logging, time, StringIO
|
||||
|
||||
import pyodbc
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.sql.expression import update
|
||||
|
||||
RECIPIENTS = ['admin@example.com']
|
||||
SUBJECT = 'Invoices Transmitted to Momentum.'
|
||||
MESSAGE = None
|
||||
|
||||
TEST_MODE = False
|
||||
LOG_LEVEL = logging.DEBUG
|
||||
ACC_NUMBERS = ['3398', '4318', '5230', '6600', '4063']
|
||||
|
||||
engine = create_engine("mssql+pyodbc://@jsisbprod", echo=False)
|
||||
Base = declarative_base(engine)
|
||||
metadata = Base.metadata
|
||||
logger = None
|
||||
|
||||
########################################################################
|
||||
# Jomar Invoice (EDI 810) staging tables #
|
||||
########################################################################
|
||||
class CSPINV00(Base):
|
||||
__tablename__ = 'CSPINV00'
|
||||
__table_args__ = {'autoload':True}
|
||||
class CSPINV01(Base):
|
||||
__tablename__ = 'CSPINV01'
|
||||
__table_args__ = {'autoload':True}
|
||||
class TransactionTable(Base):
|
||||
__tablename__ = 'ftp_trans_numbers'
|
||||
__table_args__ = {'autoload':True}
|
||||
|
||||
########################################################################
|
||||
# Jomar Item description tables. Used to look up Pattern name, color, #
|
||||
# style, etc. for a given item number #
|
||||
########################################################################
|
||||
class TXMYAT03(Base):
|
||||
__tablename__ = 'TXMYAT03'
|
||||
__table_args__ = {'autoload':True}
|
||||
########################################################################
|
||||
# Jomar Customer master file. Used to look up account names #
|
||||
########################################################################
|
||||
class CustomerMaster(Base):
|
||||
__tablename__ = 'TXUYKD00'
|
||||
__table_args__ = {'autoload':True}
|
||||
|
||||
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 - %(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)
|
||||
|
||||
'''
|
||||
Gotta get transaction number from AS400 until ALL transmissions
|
||||
are handled on the new system... whoopee
|
||||
'''
|
||||
def getTransNumber():
|
||||
connection = pyodbc.connect(
|
||||
driver='{iSeries Access ODBC Driver}',
|
||||
system='SUNBURY',
|
||||
uid=os.environ['AS400_UID'],
|
||||
pwd=os.environ['AS400_PWD'])
|
||||
c1 = connection.cursor()
|
||||
ret = -1
|
||||
|
||||
c1.execute('select * from stmdata.MGTX#FL')
|
||||
for row in c1:
|
||||
ret = int(row[1]) + 1
|
||||
|
||||
c1.close()
|
||||
|
||||
return ret
|
||||
|
||||
'''
|
||||
Update the Momentum transaction number in the AS400 database
|
||||
'''
|
||||
def updateTransNumber(txnum):
|
||||
connection = pyodbc.connect(
|
||||
driver='{iSeries Access ODBC Driver}',
|
||||
system='SUNBURY',
|
||||
uid=os.environ['AS400_UID'],
|
||||
pwd=os.environ['AS400_PWD'],
|
||||
autocommit=True)
|
||||
c1 = connection.cursor()
|
||||
c1.execute('UPDATE STMDATA.MGTX#FL SET MGSEQ# = ' + str(txnum))
|
||||
c1.close()
|
||||
|
||||
'''
|
||||
Grabs any unprocessed Maharam invoices from the 810 EDI staging tables in Jomar.
|
||||
Formats data into text document to send to Maharam via FTP.
|
||||
Marks invoices as processed.
|
||||
'''
|
||||
def createMomentumInvoiceDocument():
|
||||
global MESSAGE
|
||||
initializeLogger('MOM_810_GENERATE')
|
||||
xmission = [] #List of strings, the individual lines of the transmission file that will be sent
|
||||
invoices_to_flag_processed = []
|
||||
|
||||
#First line of transmission is T or P. 'Test' or 'Production'
|
||||
if(TEST_MODE):
|
||||
logger.info('**RUNNING IN TEST MODE**')
|
||||
xmission.append('T~\n')
|
||||
else:
|
||||
logger.info('**RUNNING IN PRODUCTION MODE**')
|
||||
xmission.append('P~\n')
|
||||
|
||||
logger.debug('Connecting to database...')
|
||||
session = loadSession()
|
||||
|
||||
trans_no = -1
|
||||
# t = session.query(mf_transaction_number).filter(mf_transaction_number.doc == '810')
|
||||
# if t.count() == 1:
|
||||
# for row in t:
|
||||
# trans_no = row.txnum
|
||||
# else:
|
||||
# logger.fatal('Failed to retrieve transaction number from database... Something ain\'t right. %s', t.count())
|
||||
# sys.exit('Failed to retrieve transaction number from database... Something ain\'t right.')
|
||||
trans_no = getTransNumber()
|
||||
|
||||
#Second line (Control Line) of transmission is essentially a boilerplate
|
||||
logger.info('Building Control Line')
|
||||
ctrlLine = 'TP~12~5702863800~12~9498338886~'
|
||||
ctrlLine += time.strftime('%Y%m%d')
|
||||
ctrlLine += '~' + str(trans_no)
|
||||
xmission.append(ctrlLine + "\n")
|
||||
logger.debug(ctrlLine)
|
||||
|
||||
logger.info('Querying EDI table for unprocessed invoices...')
|
||||
logger.debug('SELECT * FROM CSPINV00 WHERE IVCUSTB IN (\'3398\', \'4318\', \'5230\', \'6600\') ORDER BY IVIDAT;')
|
||||
q = session.query(CSPINV00,CustomerMaster).order_by(CSPINV00.IVIDAT).filter(CSPINV00.IVCUSTB.in_(ACC_NUMBERS)).filter(CustomerMaster.KKDN == CSPINV00.IVCUSTB)
|
||||
for row in q:
|
||||
if(row[0].IVPROCSS == 'Y'):
|
||||
continue
|
||||
invoices_to_flag_processed.append(row[0].IVINV)
|
||||
businessGroup = row[0].IVBNR
|
||||
plant = row[0].IVPLT
|
||||
invoiceType = row[0].IVITYP
|
||||
logger.info('Building header line for invoice: ' + row[0].IVINV)
|
||||
|
||||
#Translate Sunbury bill-to account number to Momentum vendor number
|
||||
momVendor = ''
|
||||
if(row[0].IVCUSTB == '3398'):
|
||||
momVendor = '6975'
|
||||
elif(row[0].IVCUSTB == '4318'):
|
||||
momVendor = '0036'
|
||||
elif(row[0].IVCUSTB == '5230'):
|
||||
momVendor = '7738'
|
||||
elif(row[0].IVCUSTB == '6600'):
|
||||
momVendor = '2082'
|
||||
elif(row[0].IVCUSTB == '4063'):
|
||||
momVendor = '2082'
|
||||
logger.debug('Sunbury Account: %s --> Momentum Vendor: %s', row[0].IVCUSTB, momVendor)
|
||||
|
||||
momPO = row[0].IVCPO[-5:]
|
||||
|
||||
hLine = 'H~'
|
||||
hLine += (row[0].IVINV + '~')
|
||||
hLine += (str(row[0].IVIDAT) + '~')
|
||||
hLine += (momVendor + '~')
|
||||
hLine += (momPO + '~')
|
||||
hLine += (row[0].IVCUSTB + '~')
|
||||
#hLine += (row[0].IVTERMS + '~')
|
||||
hLine += ('02~') #Changed to constant '02' per Kim Stolmeier @ Momentum
|
||||
hLine += (row[1].KNA2 + '~')
|
||||
hLine += (row[0].IVSADD1 + '~')
|
||||
hLine += (row[0].IVSCTY + '~')
|
||||
hLine += (row[0].IVSST + '~')
|
||||
hLine += (row[0].IVSZIP + '~')
|
||||
hLine += (row[1].KNA2 + '~')
|
||||
hLine += (row[0].IVBADD1 + '~')
|
||||
hLine += (row[0].IVBCTY + '~')
|
||||
hLine += (row[0].IVBST + '~')
|
||||
hLine += (row[0].IVBZIP + '~')
|
||||
hLine += (str(row[0].IVFRT) + '~')
|
||||
xmission.append(hLine + "\n")
|
||||
logger.debug(hLine)
|
||||
|
||||
logger.info('Querying EDI table for invoice detail lines for invoice: ' + row[0].IVINV)
|
||||
logger.debug('SELECT * FROM CSPINV01 LEFT JOIN TXMYAT03 ON TXMYAT03.XANR = CSPINV01.I1ITEM WHERE CSPINV01.I1BNR = \'' + businessGroup + '\' AND CSPINV01.I1PLT = \'' + plant + '\' AND CSPINV01.I1ITYP = \'' + invoiceType + '\' AND CSPINV01.I1INV = \'' + row[0].IVINV + '\';')
|
||||
q2 = session.query(CSPINV01).filter(CSPINV01.I1BNR == businessGroup, CSPINV01.I1PLT == plant, CSPINV01.I1ITYP == invoiceType, CSPINV01.I1INV == row[0].IVINV).join(TXMYAT03, TXMYAT03.XANR == CSPINV01.I1ITEM).add_entity(TXMYAT03)
|
||||
for row2 in q2:
|
||||
if(row2[0].I1ITEM == 'INSURANCE'):
|
||||
'''
|
||||
@todo: Does Momentum even pay for insurance?
|
||||
'''
|
||||
logger.warn('Skipping insurance line!')
|
||||
continue
|
||||
|
||||
logger.info('Building detail line for line ' + str(row2[0].I1ILINE))
|
||||
dLine = 'D~'
|
||||
dLine += (row2[1].XFLX33 + '~')
|
||||
dLine += (row2[1].XFLX34 + '~')
|
||||
dLine += (row2[1].XFLX35 + '~')
|
||||
dLine += ("{0:.3f}".format(row2[0].I1QTY) + '~')
|
||||
dLine += ("{0:.2f}".format(row2[0].I1PRI) + '~')
|
||||
dLine += (momPO + '~')
|
||||
xmission.append(dLine + "\n")
|
||||
logger.debug(dLine)
|
||||
|
||||
if len(xmission) > 2:
|
||||
xmission.append('S~' + str(len(xmission)) + '~')
|
||||
|
||||
#Write transmission data out to file here
|
||||
logger.info('Creating D:\\FTP\\SEND_MG\\SBR_810_' + str(trans_no) + '.txt')
|
||||
f = open('SEND_MG\\SBR_810_' + str(trans_no) + '.txt', 'w')
|
||||
f.writelines(xmission)
|
||||
f.close()
|
||||
|
||||
try:
|
||||
logger.info('Sending e-mail alert...')
|
||||
send_alert_html(RECIPIENTS, SUBJECT, attachments=glob('D:\\FTP\\SEND_MG\\SBR_810_*.txt'), message=MESSAGE.getvalue())
|
||||
except:
|
||||
logger.error('Unable to send e-mail. Is the internet out?')
|
||||
|
||||
#Update EDI tables and transaction number #mf_transaction_number
|
||||
if(len(invoices_to_flag_processed) > 0 and not TEST_MODE):
|
||||
#Set process flag on these invoices to 'Y'
|
||||
ex = update(CSPINV00.__table__).where(CSPINV00.IVINV.in_(invoices_to_flag_processed)).values(IVPROCSS=u"Y")
|
||||
session.execute(ex)
|
||||
ex = None
|
||||
|
||||
#Might as well keep the table in the new database up to date
|
||||
ex2 = update(TransactionTable.__table__).where(TransactionTable.client.in_(['MOMTEX'])).values(xaction=(trans_no))
|
||||
session.execute(ex2)
|
||||
ex2 = None
|
||||
|
||||
logger.debug('Comitting changes to database...')
|
||||
session.commit()
|
||||
|
||||
updateTransNumber(trans_no) #Update transaction number in AS400
|
||||
|
||||
logger.debug('Closing database connection...')
|
||||
session.close()
|
||||
else:
|
||||
logger.warn('Nothing to send!')
|
||||
session.close()
|
||||
|
||||
MESSAGE.truncate(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
createMomentumInvoiceDocument()
|
||||
Reference in New Issue
Block a user