Initial commit. Loads XLSX file from accounting into sqlite database. Sends HTML email. Started adding variable parts to body pulled from database.
This commit is contained in:
97
InvoiceDatabase.py
Normal file
97
InvoiceDatabase.py
Normal file
@@ -0,0 +1,97 @@
|
||||
from openpyxl import load_workbook
|
||||
from sqlalchemy import create_engine, Column, Integer, String, REAL
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
engine = create_engine('sqlite:///cffInvoice.db')
|
||||
engine.connect()
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class Invoice(Base):
|
||||
__tablename__ = 'Invoice'
|
||||
rowid = Column(Integer, primary_key=True, autoincrement=True)
|
||||
OrderID = Column(String)
|
||||
InvoiceNumber = Column(String)
|
||||
DateCreated = Column(String)
|
||||
ProductionCharges = Column(REAL)
|
||||
ShippingCharges = Column(REAL)
|
||||
AdjustmentsBalance = Column(REAL)
|
||||
DuePayment = Column(REAL)
|
||||
ChargeCode = Column(String)
|
||||
UserLogon = Column(String)
|
||||
UserProfileFirstName = Column(String)
|
||||
UserProfileLastName = Column(String)
|
||||
InvoiceEmailAddress = Column(String)
|
||||
ShippingCompany = Column(String)
|
||||
ShippingFirstName = Column(String)
|
||||
ShippingLastName = Column(String)
|
||||
ShippingAddress1 = Column(String)
|
||||
ShippingAddress2 = Column(String)
|
||||
ShippingCity = Column(String)
|
||||
ShippingState = Column(String)
|
||||
ShippingPostalCode = Column(String)
|
||||
|
||||
|
||||
class ItemDetail(Base):
|
||||
__tablename__ = 'ItemDetail'
|
||||
rowid = Column(Integer, primary_key=True, autoincrement=True)
|
||||
OrderID = Column(String)
|
||||
DocumentID = Column(String)
|
||||
GLIJobNumber = Column(String)
|
||||
ProductName = Column(String)
|
||||
Quantity = Column(String)
|
||||
ItemPrice = Column(REAL)
|
||||
|
||||
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
|
||||
|
||||
def load_sheet(invoiceNumber):
|
||||
|
||||
# starting invoice sub-number
|
||||
count = 2
|
||||
|
||||
#open the xlsx file from accounting and name the two sheets required
|
||||
wb = load_workbook('1.xlsx', data_only=True)
|
||||
shtInvoice = wb.get_sheet_by_name('Invoice')
|
||||
shtItemDetail = wb.get_sheet_by_name('Item Detail')
|
||||
|
||||
#loop through each row in the Invoice sheet except for the first and last
|
||||
#write each row to the database
|
||||
for row in shtInvoice.iter_rows(min_row=2, max_row=shtInvoice.max_row-1):
|
||||
session.add(Invoice(OrderID=row[0].value, InvoiceNumber=invoiceNumber + '-' + str(count), DateCreated=row[2].value,
|
||||
ProductionCharges=row[4].value, ShippingCharges=row[5].value, AdjustmentsBalance=row[6].value,
|
||||
DuePayment=row[7].value, ChargeCode=row[8].value, UserLogon=row[9].value, UserProfileFirstName=row[10].value,
|
||||
UserProfileLastName=row[11].value, InvoiceEmailAddress=row[12].value, ShippingCompany=row[13].value,
|
||||
ShippingFirstName=row[14].value, ShippingLastName=row[15].value, ShippingAddress1=row[16].value,
|
||||
ShippingAddress2=row[17].value, ShippingCity=row[18].value, ShippingState=row[19].value,
|
||||
ShippingPostalCode=row[20].value))
|
||||
count = count + 1
|
||||
session.commit()
|
||||
|
||||
for row in shtItemDetail.iter_rows(min_row=2, max_row=shtItemDetail.max_row-1):
|
||||
session.add(ItemDetail(OrderID=row[0].value, DocumentID=row[1].value, GLIJobNumber=row[4].value, ProductName=row[5].value, Quantity=row[6].value, ItemPrice=row[7].value))
|
||||
session.commit()
|
||||
|
||||
|
||||
def just_work():
|
||||
orders = []
|
||||
for order in session.query(Invoice).all():
|
||||
orders.append(order.OrderID)
|
||||
return orders
|
||||
|
||||
|
||||
def record_lookup(record):
|
||||
result = []
|
||||
for lookup in session.query(Invoice).filter(Invoice.OrderID == record):
|
||||
result.append(lookup.OrderID)
|
||||
result.append(lookup.DateCreated)
|
||||
result.append(lookup.UserLogon)
|
||||
result.append(lookup.UserProfileFirstName)
|
||||
result.append(lookup.UserProfileLastName)
|
||||
result.append(lookup.ChargeCode)
|
||||
result.append(lookup.InvoiceNumber)
|
||||
result.append(lookup.InvoiceEmailAddress)
|
||||
return result
|
||||
32
TableSetup
Normal file
32
TableSetup
Normal file
@@ -0,0 +1,32 @@
|
||||
create table Invoice(
|
||||
OrderID TEXT NOT NULL,
|
||||
InvoiceNumber TEXT NOT NULL,
|
||||
DateCreated TEXT NOT NULL,
|
||||
ProductionCharges REAL NOT NULL,
|
||||
ShippingCharges REAL NOT NULL,
|
||||
AdjustmentsBalance REAL NOT NULL,
|
||||
DuePayment REAL NOT NULL,
|
||||
ChargeCode TEXT,
|
||||
UserLogon TEXT NOT NULL,
|
||||
UserProfileFirstName TEXT NOT NULL,
|
||||
UserProfileLastName TEXT NOT NULL,
|
||||
InvoiceEmailAddress TEXT NOT NULL,
|
||||
ShippingCompany TEXT,
|
||||
ShippingFirstName TEXT NOT NULL,
|
||||
ShippingLastName TEXT NOT NULL,
|
||||
ShippingAddress1 TEXT NOT NULL,
|
||||
ShippingAddress2 TEXT,
|
||||
ShippingCity TEXT NOT NULL,
|
||||
ShippingState TEXT NOT NULL,
|
||||
ShippingPostalCode TEXT NOT NULL
|
||||
);
|
||||
|
||||
|
||||
create table ItemDetail(
|
||||
OrderID TEXT NOT NULL,
|
||||
DocumentID TEXT NOT NULL,
|
||||
GLIJobNumber TEXT NOT NULL,
|
||||
ProductName TEXT NOT NULL,
|
||||
Quantity INT NOT NULL,
|
||||
ItemPrice REAL NOT NULL
|
||||
);
|
||||
20
main.py
Normal file
20
main.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import sendEmail
|
||||
import InvoiceDatabase
|
||||
|
||||
running = True
|
||||
|
||||
while running is True:
|
||||
print('1. load new excel file\n2. Send Test emails\n3. Send Invoices\n4. Quit')
|
||||
option = int(input())
|
||||
if option == 1:
|
||||
print('Enter invoice number')
|
||||
invoiceNumber = str(input())
|
||||
InvoiceDatabase.load_sheet(invoiceNumber)
|
||||
elif option == 2:
|
||||
sendEmail.send_email(True,'ALL')
|
||||
elif option == 3:
|
||||
sendEmail.send_email()
|
||||
elif option == 4:
|
||||
running = False
|
||||
else:
|
||||
print('not an option')
|
||||
7
requirements
Normal file
7
requirements
Normal file
@@ -0,0 +1,7 @@
|
||||
et-xmlfile==1.0.1
|
||||
greenlet==1.0.0
|
||||
importlib-metadata==3.7.3
|
||||
openpyxl==3.0.7
|
||||
SQLAlchemy==1.4.1
|
||||
typing-extensions==3.7.4.3
|
||||
zipp==3.4.1
|
||||
125
sendEmail.py
Normal file
125
sendEmail.py
Normal file
@@ -0,0 +1,125 @@
|
||||
import smtplib
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.base import MIMEBase
|
||||
from datetime import datetime
|
||||
import InvoiceDatabase
|
||||
|
||||
|
||||
def send_email(test, record):
|
||||
|
||||
port = 25
|
||||
smtp_server = "gll-com.mail.protection.outlook.com"
|
||||
|
||||
orders = InvoiceDatabase.just_work()
|
||||
for each in orders:
|
||||
info = InvoiceDatabase.record_lookup(each)
|
||||
print(info)
|
||||
OrderNumber = info[0]
|
||||
OrderDate = info[1]
|
||||
UserLogon = info[2]
|
||||
Name = info[3] + ' ' + info[4]
|
||||
ChargeCode = info[5]
|
||||
InvoiceNumber = info[6]
|
||||
InvoiceEmailAddress = info[7]
|
||||
InvoiceDate = datetime.today().strftime('%m/%d/%Y')
|
||||
|
||||
|
||||
body = '''
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML><HEAD><TITLE>CFF Order Invoice</TITLE>
|
||||
<META content="text/html; charset=utf-8" http-equiv=Content-Type>
|
||||
<META name=GENERATOR content="MSHTML 11.00.9600.18525">
|
||||
<META name=Author content="">
|
||||
<META name=Keywords content="">
|
||||
<META name=Description content="">
|
||||
<STYLE type=text/css>
|
||||
p,
|
||||
span,
|
||||
a,
|
||||
table,
|
||||
td,
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
option {{
|
||||
font-family: Verdana, Tahoma, Geneva, Arial, Helvetica, sans-serif;
|
||||
font-weight: normal;
|
||||
font-size: 13px;
|
||||
margin: 0;
|
||||
}}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<TABLE style="BORDER-COLLAPSE: collapse" width="600">
|
||||
|
||||
<TR>
|
||||
<TD style="BORDER-BOTTOM: #000000 1px solid" width="300"><IMG src="http://cff.gli.us.com/store/custom/images/GLIHeader.png"></TD>
|
||||
<TD style="BORDER-BOTTOM: #000000 1px solid" width="300" align="right"><P style="FONT-SIZE: 18px; FONT-WEIGHT: normal; MARGIN-TOP: 10px"><I>INVOICE</I></P></TD>
|
||||
</TR>
|
||||
|
||||
<TR vAlign="top">
|
||||
<TD style="VERTICAL-ALIGN: top" vAlign="top" width="300">
|
||||
<SPAN contentEditable=false style="" PFVar="AddressBlock">Address Block</SPAN></TD>
|
||||
<TD style="VERTICAL-ALIGN: top" vAlign="top" width="300"> <BR><P><B>Make Checks Payable To:</B> <BR>Great Lakes Integrated <BR>4246 Hudson Dr.<BR>Stow, Ohio 44224<BR> </P></TD>
|
||||
</TR>
|
||||
|
||||
<TR vAlign="top">
|
||||
<TD style="VERTICAL-ALIGN: top" vAlign="top" width="300">
|
||||
<P>
|
||||
<B>Order Number:</B> {OrderNumber}
|
||||
<BR><B>Order Date:</B> {OrderDate}
|
||||
<BR><B>User Logon:</B> {UserLogon}
|
||||
<BR><B>Name:</B> {Name}
|
||||
<BR><B>Charge Code:</B> {ChargeCode}
|
||||
</P>
|
||||
</TD>
|
||||
|
||||
<TD style="VERTICAL-ALIGN: top" vAlign="top" width="300">
|
||||
<P>
|
||||
<B>Invoice Number:</B> {InvoiceNumber}
|
||||
<BR><B>Invoice Date:</B> {InvoiceDate}
|
||||
<BR><B>Customer Number:</B> 1925
|
||||
<BR><B>Terms:</B>Due in 30 days
|
||||
</P>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD width="600" colSpan="2"><P style="MARGIN-TOP: 20px"><B>The order consists of the following items:</B> </P>
|
||||
<SPAN contentEditable=false style="" PFVar="OrderDetail"></SPAN>
|
||||
</TD>
|
||||
</TR>
|
||||
</TBODY>
|
||||
</TABLE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
'''
|
||||
HTMLpart = body.format(OrderNumber=OrderNumber, OrderDate=OrderDate, UserLogon=UserLogon, Name=Name,
|
||||
ChargeCode=ChargeCode, InvoiceDate=InvoiceDate, InvoiceNumber=InvoiceNumber)
|
||||
|
||||
bodyHTML = MIMEText(HTMLpart, "html")
|
||||
|
||||
f = open("sample.html", 'w')
|
||||
f.write(HTMLpart)
|
||||
f.close()
|
||||
|
||||
msg = MIMEMultipart()
|
||||
msg['Subject'] = 'INVOICE ' + InvoiceNumber
|
||||
if test is True:
|
||||
msg['To'] = 'ddembinski@gll.com'
|
||||
else:
|
||||
# msg['To'] = InvoiceEmailAddress
|
||||
msg['To'] = 'ddembinski@gll.com'
|
||||
msg['From'] = 'ddembinski@gll.com'
|
||||
msg.add_header('Content-Type', 'text/html')
|
||||
msg.attach(bodyHTML)
|
||||
|
||||
try:
|
||||
with smtplib.SMTP(smtp_server, port, timeout=120) as server:
|
||||
server.sendmail(msg['From'], msg['To'], msg.as_string())
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
Reference in New Issue
Block a user