| 11978 |
kshitij.so |
1 |
from elixir import *
|
|
|
2 |
from sqlalchemy.sql import func
|
|
|
3 |
from shop2020.model.v1.order.impl import DataService
|
|
|
4 |
from shop2020.model.v1.order.impl.DataService import Order, LineItem
|
|
|
5 |
from shop2020.thriftpy.model.v1.order.ttypes import OrderSource
|
|
|
6 |
from datetime import datetime, timedelta
|
|
|
7 |
import MySQLdb
|
|
|
8 |
import xlwt
|
|
|
9 |
from operator import itemgetter
|
|
|
10 |
import smtplib
|
|
|
11 |
from email.mime.text import MIMEText
|
|
|
12 |
from email.mime.multipart import MIMEMultipart
|
|
|
13 |
from email import encoders
|
|
|
14 |
from email.mime.text import MIMEText
|
|
|
15 |
from email.mime.base import MIMEBase
|
|
|
16 |
from email.mime.multipart import MIMEMultipart
|
|
|
17 |
|
|
|
18 |
|
|
|
19 |
DataService.initialize(db_hostname='localhost')
|
|
|
20 |
SaleMap = {}
|
|
|
21 |
BrandCatMap = {}
|
|
|
22 |
UnUsableStatus = [25, 27, 30, 32, 47, 48, 68, 71, 72, 73, 74]
|
|
|
23 |
UsableStatus = [21, 28, 64, 67, 69, 70]
|
|
|
24 |
db = MySQLdb.connect('localhost',"root","shop2020","warehouse" )
|
|
|
25 |
cursor = db.cursor()
|
|
|
26 |
|
|
|
27 |
class __SaleAndReturnInfo:
|
|
|
28 |
def __init__(self, websiteSale, amazonSale, ebaySale, snapdealSale, flipkartSale, productGroup, sellableCountWebsite, nonSellableCountWebsite, sellableCountAmazon, \
|
|
|
29 |
nonSellableCountAmazon,sellableCountEbay,nonSellableCountEbay,sellableCountSnapdeal,nonSellableCountSnapdeal,sellableCountFlipkart,nonSellableCountFlipkart, \
|
|
|
30 |
brand, model_name, model_number, color, sellableWebsitePercentage, nonSellableWebsitePercentage, sellableAmazonPercentage, nonSellableAmazonPercentage, \
|
|
|
31 |
sellableEbayPercentage, nonSellableEbayPercentage, sellableSnapdealPercentage, nonSellableSnapdealPercentage, sellableFlipkartPercentage, nonSellableFlipkartPercentage, \
|
|
|
32 |
sellableOverallPercentage, nonSellableOverallPercentage, item_id):
|
|
|
33 |
|
|
|
34 |
self.websiteSale = websiteSale
|
|
|
35 |
self.amazonSale = amazonSale
|
|
|
36 |
self.ebaySale = ebaySale
|
|
|
37 |
self.snapdealSale = snapdealSale
|
|
|
38 |
self.flipkartSale = flipkartSale
|
|
|
39 |
self.productGroup = productGroup
|
|
|
40 |
self.sellableCountWebsite = sellableCountWebsite
|
|
|
41 |
self.nonSellableCountWebsite = nonSellableCountWebsite
|
|
|
42 |
self.sellableCountAmazon = sellableCountAmazon
|
|
|
43 |
self.nonSellableCountAmazon = nonSellableCountAmazon
|
|
|
44 |
self.sellableCountEbay = sellableCountEbay
|
|
|
45 |
self.nonSellableCountEbay = nonSellableCountEbay
|
|
|
46 |
self.sellableCountSnapdeal = sellableCountSnapdeal
|
|
|
47 |
self.nonSellableCountSnapdeal = nonSellableCountSnapdeal
|
|
|
48 |
self.sellableCountFlipkart = sellableCountFlipkart
|
|
|
49 |
self.nonSellableCountFlipkart = nonSellableCountFlipkart
|
|
|
50 |
self.brand = brand
|
|
|
51 |
self.model_name = model_name
|
|
|
52 |
self.model_number = model_number
|
|
|
53 |
self.color = color
|
|
|
54 |
self.sellableWebsitePercentage = sellableWebsitePercentage
|
|
|
55 |
self.nonSellableWebsitePercentage = nonSellableWebsitePercentage
|
|
|
56 |
self.sellableAmazonPercentage = sellableAmazonPercentage
|
|
|
57 |
self.nonSellableAmazonPercentage = nonSellableAmazonPercentage
|
|
|
58 |
self.sellableEbayPercentage = sellableEbayPercentage
|
|
|
59 |
self.nonSellableEbayPercentage = nonSellableEbayPercentage
|
|
|
60 |
self.sellableSnapdealPercentage = sellableSnapdealPercentage
|
|
|
61 |
self.nonSellableSnapdealPercentage = nonSellableSnapdealPercentage
|
|
|
62 |
self.sellableFlipkartPercentage = sellableFlipkartPercentage
|
|
|
63 |
self.nonSellableFlipkartPercentage = nonSellableFlipkartPercentage
|
|
|
64 |
self.sellablOverallPercentage = sellableOverallPercentage
|
|
|
65 |
self.nonSellableOverallPercentage = nonSellableOverallPercentage
|
|
|
66 |
self.item_id = item_id
|
|
|
67 |
|
|
|
68 |
class __BrandCatInfo:
|
|
|
69 |
def __init__(self, totalSale, nonSellableReturn, nonSellableReturnPercentage, brand, productGroup):
|
|
|
70 |
self.totalSale = totalSale
|
|
|
71 |
self.nonSellableReturn = nonSellableReturn
|
|
|
72 |
self.nonSellableReturnPercentage = nonSellableReturnPercentage
|
|
|
73 |
self.brand = brand
|
|
|
74 |
self.productGroup = productGroup
|
|
|
75 |
|
|
|
76 |
|
|
|
77 |
|
|
|
78 |
def populateSaleInfo():
|
|
|
79 |
global SaleMap
|
|
|
80 |
fromDate = (datetime.now()-timedelta(days=45))
|
|
|
81 |
toDate = (fromDate + timedelta(days=15))
|
|
|
82 |
#allShippedOrders = Order.query.filter(Order.created_timestamp.between(fromDate.date(),toDate.date())).filter(Order.shipping_timestamp!=None).all()
|
|
|
83 |
|
|
|
84 |
allShippedOrders = session.query(LineItem.item_id,LineItem.productGroup,Order.source,Order.status,Order.received_return_timestamp, \
|
|
|
85 |
LineItem.quantity,Order.id,LineItem.brand,LineItem.model_name,LineItem.model_number,LineItem.color) \
|
|
|
86 |
.join((Order,LineItem.order_id==Order.id)).filter(Order.created_timestamp.between(fromDate.date(),toDate.date())) \
|
|
|
87 |
.filter(Order.shipping_timestamp!=None).all()
|
|
|
88 |
|
|
|
89 |
for shippedOrder in allShippedOrders:
|
|
|
90 |
if SaleMap.has_key(shippedOrder[0]):
|
|
|
91 |
val = SaleMap.get(shippedOrder[0])
|
|
|
92 |
if shippedOrder[2] in (OrderSource.WEBSITE,OrderSource.MOBILESITE):
|
|
|
93 |
val.websiteSale = val.websiteSale + shippedOrder[5]
|
|
|
94 |
elif shippedOrder[2]==OrderSource.AMAZON:
|
|
|
95 |
val.amazonSale = val.amazonSale + shippedOrder[5]
|
|
|
96 |
elif shippedOrder[2]==OrderSource.EBAY:
|
|
|
97 |
val.ebaySale = val.ebaySale + shippedOrder[5]
|
|
|
98 |
elif shippedOrder[2]==OrderSource.SNAPDEAL:
|
|
|
99 |
val.snapdealSale = val.snapdealSale + shippedOrder[5]
|
|
|
100 |
elif shippedOrder[2]==OrderSource.FLIPKART:
|
|
|
101 |
val.flipkartSale = val.flipkartSale + shippedOrder[5]
|
|
|
102 |
else:
|
|
|
103 |
print "Unknown source for orderId ",shippedOrder[6]
|
|
|
104 |
else:
|
|
|
105 |
saleInfo = __SaleAndReturnInfo(0,0,0,0,0,shippedOrder[1],0,0,0,0,0,0,0,0,0,0,shippedOrder[7],shippedOrder[8],shippedOrder[9],shippedOrder[10], \
|
|
|
106 |
0,0,0,0,0,0,0,0,0,0,0,0,shippedOrder[0])
|
|
|
107 |
if shippedOrder[2] in (OrderSource.WEBSITE,OrderSource.MOBILESITE):
|
|
|
108 |
saleInfo.websiteSale = saleInfo.websiteSale + shippedOrder[5]
|
|
|
109 |
elif shippedOrder[2]==OrderSource.AMAZON:
|
|
|
110 |
saleInfo.amazonSale = saleInfo.amazonSale + shippedOrder[5]
|
|
|
111 |
elif shippedOrder[2]==OrderSource.EBAY:
|
|
|
112 |
saleInfo.ebaySale = saleInfo.ebaySale + shippedOrder[5]
|
|
|
113 |
elif shippedOrder[2]==OrderSource.SNAPDEAL:
|
|
|
114 |
saleInfo.snapdealSale = saleInfo.snapdealSale + shippedOrder[5]
|
|
|
115 |
elif shippedOrder[2]==OrderSource.FLIPKART:
|
|
|
116 |
saleInfo.flipkartSale = saleInfo.flipkartSale + shippedOrder[5]
|
|
|
117 |
else:
|
|
|
118 |
print "Unknown source for orderId ",shippedOrder[6]
|
|
|
119 |
SaleMap[shippedOrder[0]]=saleInfo
|
|
|
120 |
|
|
|
121 |
#Checking returns
|
|
|
122 |
|
|
|
123 |
for shippedOrder in allShippedOrders:
|
|
|
124 |
if shippedOrder[4] is not None:
|
|
|
125 |
val = SaleMap.get(shippedOrder[0])
|
|
|
126 |
sql = "select quantity,type from scanNew where orderId=%d and type in ('SALE_RET','DOA_IN','SALE_RET_UNUSABLE')" %(shippedOrder[6])
|
|
|
127 |
print sql
|
|
|
128 |
cursor.execute(sql)
|
|
|
129 |
result = cursor.fetchone()
|
|
|
130 |
print result
|
|
|
131 |
if result is None:
|
|
|
132 |
continue
|
|
|
133 |
quantity = result[0]
|
|
|
134 |
returnType = result[1]
|
|
|
135 |
if shippedOrder[2] in (OrderSource.WEBSITE,OrderSource.MOBILESITE):
|
|
|
136 |
if returnType in ('DOA_IN','SALE_RET_UNUSABLE'):
|
|
|
137 |
val.nonSellableCountWebsite = val.nonSellableCountWebsite + quantity
|
|
|
138 |
else:
|
|
|
139 |
val.sellableCountWebsite = val.sellableCountWebsite + quantity
|
|
|
140 |
elif shippedOrder[2]==OrderSource.AMAZON:
|
|
|
141 |
if returnType in ('DOA_IN','SALE_RET_UNUSABLE'):
|
|
|
142 |
val.nonSellableCountAmazon = val.nonSellableCountAmazon + quantity
|
|
|
143 |
else:
|
|
|
144 |
val.sellableCountAmazon = val.sellableCountAmazon + quantity
|
|
|
145 |
elif shippedOrder[2]==OrderSource.EBAY:
|
|
|
146 |
if returnType in ('DOA_IN','SALE_RET_UNUSABLE'):
|
|
|
147 |
val.nonSellableCountEbay = val.nonSellableCountEbay + quantity
|
|
|
148 |
else:
|
|
|
149 |
val.sellableCountEbay = val.sellableCountEbay + quantity
|
|
|
150 |
elif shippedOrder[2]==OrderSource.SNAPDEAL:
|
|
|
151 |
if returnType in ('DOA_IN','SALE_RET_UNUSABLE'):
|
| 12002 |
kshitij.so |
152 |
val.nonSellableCountSnapdeal = val.nonSellableCountSnapdeal + quantity
|
| 11978 |
kshitij.so |
153 |
else:
|
|
|
154 |
val.sellableCountSnapdeal = val.sellableCountSnapdeal + quantity
|
|
|
155 |
elif shippedOrder[2]==OrderSource.FLIPKART:
|
|
|
156 |
if returnType in ('DOA_IN','SALE_RET_UNUSABLE'):
|
|
|
157 |
val.nonSellableCountFlipkart = val.nonSellableCountFlipkart + quantity
|
|
|
158 |
else:
|
|
|
159 |
val.sellableCountFlipkart = val.sellableCountFlipkart + quantity
|
|
|
160 |
else:
|
|
|
161 |
print "Not counting, unknown source"
|
| 12002 |
kshitij.so |
162 |
|
| 11978 |
kshitij.so |
163 |
allShippedOrders[:] = []
|
|
|
164 |
db.close()
|
|
|
165 |
|
|
|
166 |
def calculateReturnPercentage():
|
|
|
167 |
global SaleMap
|
|
|
168 |
for k, v in SaleMap.iteritems():
|
|
|
169 |
if v.websiteSale > 0:
|
|
|
170 |
v.sellableWebsitePercentage = float(v.sellableCountWebsite)/v.websiteSale
|
|
|
171 |
v.nonSellableWebsitePercentage = float(v.nonSellableCountWebsite)/v.websiteSale
|
|
|
172 |
if v.amazonSale > 0:
|
|
|
173 |
v.sellableAmazonPercentage = float(v.sellableCountAmazon)/v.amazonSale
|
|
|
174 |
v.nonSellableAmazonPercentage = float(v.nonSellableCountAmazon)/v.amazonSale
|
|
|
175 |
if v.ebaySale > 0:
|
|
|
176 |
v.sellableEbayPercentage = float(v.sellableCountEbay)/v.ebaySale
|
|
|
177 |
v.nonSellableEbayPercentage = float(v.nonSellableCountEbay)/v.ebaySale
|
|
|
178 |
if v.snapdealSale > 0:
|
|
|
179 |
v.sellableSnapdealPercentage = float(v.sellableCountSnapdeal)/v.snapdealSale
|
|
|
180 |
v.nonSellableSnapdealPercentage = float(v.nonSellableCountSnapdeal)/v.snapdealSale
|
|
|
181 |
if v.flipkartSale > 0:
|
|
|
182 |
v.sellableFlipkartPercentage = float(v.sellableCountFlipkart)/v.flipkartSale
|
|
|
183 |
v.nonSellableFlipkartPercentage = float(v.nonSellableCountFlipkart)/v.flipkartSale
|
|
|
184 |
if (v.websiteSale+v.amazonSale+v.ebaySale+v.snapdealSale+v.flipkartSale) > 0:
|
|
|
185 |
v.sellableOverallPercentage = float(v.sellableCountWebsite+v.sellableCountAmazon+v.sellableCountEbay+ \
|
|
|
186 |
v.sellableCountSnapdeal+v.sellableCountFlipkart)/(v.websiteSale+v.amazonSale+v.ebaySale+v.snapdealSale+v.flipkartSale)
|
|
|
187 |
v.nonSellableOverallPercentage = float(v.nonSellableCountWebsite+v.nonSellableCountAmazon+v.nonSellableCountEbay+ \
|
|
|
188 |
v.nonSellableCountSnapdeal+v.nonSellableCountFlipkart)/(v.websiteSale+v.amazonSale+v.ebaySale+v.snapdealSale+v.flipkartSale)
|
|
|
189 |
|
|
|
190 |
|
|
|
191 |
def exit():
|
|
|
192 |
import sys
|
|
|
193 |
sys.exit(1)
|
|
|
194 |
|
|
|
195 |
|
|
|
196 |
def sendEmail():
|
|
|
197 |
xstr = lambda s: s or ""
|
|
|
198 |
message="""<html>
|
|
|
199 |
<body>
|
|
|
200 |
<h3>Source Wise Return</h3>
|
|
|
201 |
<table border="1" style="width:50%;">
|
|
|
202 |
<thead>
|
|
|
203 |
<tr><th>Source</th>
|
|
|
204 |
<th>Total Sale</th>
|
|
|
205 |
<th>Total Returns</th>
|
|
|
206 |
<th>Total Sellable Returns</th>
|
|
|
207 |
<th>Total Non Sellable Returns</th>
|
|
|
208 |
<th>Return %</th>
|
|
|
209 |
<th>Sellable Return %</th>
|
|
|
210 |
<th>Non Sellable Return %</th>
|
|
|
211 |
</tr></thead>
|
|
|
212 |
<tbody>"""
|
|
|
213 |
websiteSale, websiteSellableReturns, websiteNonSellableReturns, amazonSale, amazonSellableReturns, amazonNonSellableReturns, \
|
|
|
214 |
ebaySale, ebaySellableReturns, ebayNonSellableReturns, snapdealSale, snapdealSellableReturns, snapdealNonSellableReturns, \
|
|
|
215 |
flipkartSale, flipkartSellableReturns , flipkartNonSellableReturns, overallSale, overallSellableReturns, overallNonSellableReturns = (0,)*18
|
|
|
216 |
for k, v in SaleMap.iteritems():
|
|
|
217 |
websiteSale = websiteSale + v.websiteSale
|
|
|
218 |
websiteSellableReturns = websiteSellableReturns + v.sellableCountWebsite
|
|
|
219 |
websiteNonSellableReturns = websiteNonSellableReturns + v.nonSellableCountWebsite
|
|
|
220 |
|
|
|
221 |
amazonSale = amazonSale + v.amazonSale
|
|
|
222 |
amazonSellableReturns = amazonSellableReturns + v.sellableCountAmazon
|
|
|
223 |
amazonNonSellableReturns = amazonNonSellableReturns + v.nonSellableCountAmazon
|
|
|
224 |
|
|
|
225 |
ebaySale = ebaySale + v.ebaySale
|
|
|
226 |
ebaySellableReturns = ebaySellableReturns + v.sellableCountEbay
|
|
|
227 |
ebayNonSellableReturns = ebayNonSellableReturns + v.nonSellableCountEbay
|
|
|
228 |
|
|
|
229 |
snapdealSale = snapdealSale + v.snapdealSale
|
|
|
230 |
snapdealSellableReturns = snapdealSellableReturns + v.sellableCountSnapdeal
|
|
|
231 |
snapdealNonSellableReturns = snapdealNonSellableReturns + v.nonSellableCountSnapdeal
|
|
|
232 |
|
|
|
233 |
flipkartSale = flipkartSale + v.flipkartSale
|
|
|
234 |
flipkartSellableReturns = flipkartSellableReturns + v.sellableCountFlipkart
|
|
|
235 |
flipkartNonSellableReturns = flipkartNonSellableReturns + v.nonSellableCountFlipkart
|
|
|
236 |
|
|
|
237 |
overallSale = overallSale + websiteSale + amazonSale + ebaySale + snapdealSale + flipkartSale
|
|
|
238 |
overallSellableReturns = overallSellableReturns + websiteSellableReturns + amazonSellableReturns + ebaySellableReturns + snapdealSellableReturns + flipkartSellableReturns
|
|
|
239 |
overallNonSellableReturns = overallNonSellableReturns + websiteNonSellableReturns + amazonNonSellableReturns + ebayNonSellableReturns + snapdealNonSellableReturns + flipkartNonSellableReturns
|
|
|
240 |
message+="""<tr>
|
|
|
241 |
<td style="text-align:center">"""+"Website"+"""</td>
|
|
|
242 |
<td style="text-align:center">"""+str(int(websiteSale))+"""</td>
|
|
|
243 |
<td style="text-align:center">"""+str(websiteSellableReturns+websiteNonSellableReturns)+"""</td>
|
|
|
244 |
<td style="text-align:center">"""+str(websiteSellableReturns)+"""</td>
|
|
|
245 |
<td style="text-align:center">"""+str(websiteNonSellableReturns)+"""</td>
|
| 11981 |
kshitij.so |
246 |
<td style="text-align:center">"""+str(round(float(websiteSellableReturns+websiteNonSellableReturns)*100/websiteSale,1))+" %"+"""</td>
|
|
|
247 |
<td style="text-align:center">"""+str(round(float(websiteSellableReturns)*100/websiteSale,1))+" %"+"""</td>
|
|
|
248 |
<td style="text-align:center">"""+str(round(float(websiteNonSellableReturns)*100/websiteSale,1))+" %"+"""</td>
|
| 11978 |
kshitij.so |
249 |
</tr>
|
|
|
250 |
<tr>
|
|
|
251 |
<td style="text-align:center">"""+"Amazon MFN"+"""</td>
|
|
|
252 |
<td style="text-align:center">"""+str(int(amazonSale))+"""</td>
|
|
|
253 |
<td style="text-align:center">"""+str(amazonSellableReturns+amazonNonSellableReturns)+"""</td>
|
|
|
254 |
<td style="text-align:center">"""+str(amazonSellableReturns)+"""</td>
|
|
|
255 |
<td style="text-align:center">"""+str(amazonNonSellableReturns)+"""</td>
|
| 11981 |
kshitij.so |
256 |
<td style="text-align:center">"""+str(round(float(amazonSellableReturns+amazonNonSellableReturns)*100/amazonSale,1))+" %"+"""</td>
|
|
|
257 |
<td style="text-align:center">"""+str(round(float(amazonSellableReturns)*100/amazonSale,1))+" %"+"""</td>
|
|
|
258 |
<td style="text-align:center">"""+str(round(float(amazonNonSellableReturns)*100/amazonSale,1))+" %"+"""</td>
|
| 11978 |
kshitij.so |
259 |
</tr>
|
|
|
260 |
<tr>
|
|
|
261 |
<td style="text-align:center">"""+"Ebay"+"""</td>
|
|
|
262 |
<td style="text-align:center">"""+str(int(ebaySale))+"""</td>
|
|
|
263 |
<td style="text-align:center">"""+str(ebaySellableReturns+ebayNonSellableReturns)+"""</td>
|
|
|
264 |
<td style="text-align:center">"""+str(ebaySellableReturns)+"""</td>
|
|
|
265 |
<td style="text-align:center">"""+str(ebayNonSellableReturns)+"""</td>
|
| 11981 |
kshitij.so |
266 |
<td style="text-align:center">"""+str(round(float(ebaySellableReturns+ebayNonSellableReturns)*100/ebaySale,1))+" %"+"""</td>
|
|
|
267 |
<td style="text-align:center">"""+str(round(float(ebaySellableReturns)*100/ebaySale,1))+" %"+"""</td>
|
|
|
268 |
<td style="text-align:center">"""+str(round(float(ebayNonSellableReturns)*100/ebaySale,1))+" %"+"""</td>
|
| 11978 |
kshitij.so |
269 |
</tr>
|
|
|
270 |
<tr>
|
|
|
271 |
<td style="text-align:center">"""+"Snapdeal"+"""</td>
|
|
|
272 |
<td style="text-align:center">"""+str(int(snapdealSale))+"""</td>
|
|
|
273 |
<td style="text-align:center">"""+str(snapdealSellableReturns+snapdealNonSellableReturns)+"""</td>
|
|
|
274 |
<td style="text-align:center">"""+str(snapdealSellableReturns)+"""</td>
|
|
|
275 |
<td style="text-align:center">"""+str(snapdealNonSellableReturns)+"""</td>
|
| 11981 |
kshitij.so |
276 |
<td style="text-align:center">"""+str(round(float(snapdealSellableReturns+snapdealNonSellableReturns)*100/snapdealSale,1))+" %"+"""</td>
|
|
|
277 |
<td style="text-align:center">"""+str(round(float(snapdealSellableReturns)*100/snapdealSale,1))+" %"+"""</td>
|
|
|
278 |
<td style="text-align:center">"""+str(round(float(snapdealNonSellableReturns)*100/snapdealSale,1))+" %"+"""</td>
|
| 11978 |
kshitij.so |
279 |
</tr>
|
|
|
280 |
<tr>
|
|
|
281 |
<td style="text-align:center">"""+"Flipkart"+"""</td>
|
|
|
282 |
<td style="text-align:center">"""+str(int(flipkartSale))+"""</td>
|
|
|
283 |
<td style="text-align:center">"""+str(flipkartSellableReturns+flipkartNonSellableReturns)+"""</td>
|
|
|
284 |
<td style="text-align:center">"""+str(flipkartSellableReturns)+"""</td>
|
|
|
285 |
<td style="text-align:center">"""+str(flipkartNonSellableReturns)+"""</td>
|
| 11981 |
kshitij.so |
286 |
<td style="text-align:center">"""+str(round(float(flipkartSellableReturns+flipkartNonSellableReturns)*100/flipkartSale,1))+" %"+"""</td>
|
|
|
287 |
<td style="text-align:center">"""+str(round(float(flipkartSellableReturns)*100/flipkartSale,1))+" %"+"""</td>
|
|
|
288 |
<td style="text-align:center">"""+str(round(float(flipkartNonSellableReturns)*100/flipkartSale,1))+" %"+"""</td>
|
| 11978 |
kshitij.so |
289 |
</tr>
|
|
|
290 |
<tr>
|
|
|
291 |
<td style="text-align:center">"""+"Total"+"""</td>
|
|
|
292 |
<td style="text-align:center">"""+str(int(overallSale))+"""</td>
|
|
|
293 |
<td style="text-align:center">"""+str(overallSellableReturns+overallNonSellableReturns)+"""</td>
|
|
|
294 |
<td style="text-align:center">"""+str(overallSellableReturns)+"""</td>
|
|
|
295 |
<td style="text-align:center">"""+str(overallNonSellableReturns)+"""</td>
|
| 11981 |
kshitij.so |
296 |
<td style="text-align:center">"""+str(round(float(overallSellableReturns+overallNonSellableReturns)*100/overallSale,1))+" %"+"""</td>
|
|
|
297 |
<td style="text-align:center">"""+str(round(float(overallSellableReturns)*100/overallSale,1))+" %"+"""</td>
|
|
|
298 |
<td style="text-align:center">"""+str(round(float(overallNonSellableReturns)*100/overallSale,1))+" %"+"""</td>
|
| 11978 |
kshitij.so |
299 |
</tr></tbody></table>"""
|
|
|
300 |
|
|
|
301 |
topWebsite, topAmazon, topEbay, topSnapdeal, topFlipkart, topOverall = [],[],[],[],[],[]
|
|
|
302 |
|
|
|
303 |
for v in SaleMap.itervalues():
|
|
|
304 |
# if v.websiteSale >=10:
|
|
|
305 |
# topWebsite.append(v)
|
|
|
306 |
# if v.amazonSale >=10:
|
|
|
307 |
# topAmazon.append(v)
|
|
|
308 |
# if v.ebaySale >=10:
|
|
|
309 |
# topEbay.append(v)
|
|
|
310 |
# if v.snapdealSale >=10:
|
|
|
311 |
# topSnapdeal.append(v)
|
|
|
312 |
# if v.flipkartSale >=10:
|
|
|
313 |
# topFlipkart.append(v)
|
| 11981 |
kshitij.so |
314 |
if (v.websiteSale + v.amazonSale + v.ebaySale + v.snapdealSale + v.flipkartSale) >=25:
|
| 11978 |
kshitij.so |
315 |
topOverall.append(v)
|
|
|
316 |
|
|
|
317 |
sortedHighReturnRate = sorted(topOverall, key=lambda x: x.nonSellableOverallPercentage, reverse=True)
|
|
|
318 |
|
|
|
319 |
message+="""<h3>Top Sku's with high sale return</h3>
|
|
|
320 |
<table border="1" style="width:100%;">
|
|
|
321 |
<thead>
|
|
|
322 |
<tr><th>Item Id</th>
|
|
|
323 |
<th>Product Name</th>
|
|
|
324 |
<th>Website Sale</th>
|
|
|
325 |
<th>Website Sellable Returns</th>
|
|
|
326 |
<th>Website Non Sellable Returns</th>
|
|
|
327 |
<th>Website Sellable Returns %</th>
|
|
|
328 |
<th>Website Non Sellable Returns %</th>
|
|
|
329 |
<th>Amazon Sale</th>
|
|
|
330 |
<th>Amazon Sellable Returns</th>
|
|
|
331 |
<th>Amazon Non Sellable Returns</th>
|
|
|
332 |
<th>Amazon Sellable Returns %</th>
|
|
|
333 |
<th>Amazon Non Sellable Returns %</th>
|
|
|
334 |
<th>Ebay Sale</th>
|
|
|
335 |
<th>Ebay Sellable Returns</th>
|
|
|
336 |
<th>Ebay Non Sellable Returns</th>
|
|
|
337 |
<th>Ebay Sellable Returns %</th>
|
|
|
338 |
<th>Ebay Non Sellable Returns %</th>
|
|
|
339 |
<th>Snapdeal Sale</th>
|
|
|
340 |
<th>Snapdeal Sellable Returns</th>
|
|
|
341 |
<th>Snapdeal Non Sellable Returns</th>
|
|
|
342 |
<th>Snapdeal Sellable Returns %</th>
|
|
|
343 |
<th>Snapdeal Non Sellable Returns %</th>
|
|
|
344 |
<th>Flipkart Sale</th>
|
|
|
345 |
<th>Flipkart Sellable Returns</th>
|
|
|
346 |
<th>Flipkart Non Sellable Returns</th>
|
|
|
347 |
<th>Flipkart Sellable Returns %</th>
|
|
|
348 |
<th>Flipkart Non Sellable Returns %</th>
|
|
|
349 |
<th>Total Sale</th>
|
|
|
350 |
<th>Total Sellable Returns</th>
|
|
|
351 |
<th>Total Non Sellable Returns</th>
|
|
|
352 |
<th>Total Sellable Returns %</th>
|
|
|
353 |
<th>Total Non Sellable Returns %</th>
|
|
|
354 |
</tr></thead>
|
|
|
355 |
<tbody>"""
|
|
|
356 |
countItems = 0
|
|
|
357 |
for highReturnData in sortedHighReturnRate:
|
|
|
358 |
if countItems==11:
|
|
|
359 |
break
|
|
|
360 |
countItems+=1
|
|
|
361 |
message+="""<tr>
|
|
|
362 |
<td style="text-align:center">"""+str(highReturnData.item_id)+"""</td>
|
|
|
363 |
<td style="text-align:center">"""+xstr(highReturnData.brand)+" "+xstr(highReturnData.model_name)+" "+xstr(highReturnData.model_number)+" "+xstr(highReturnData.color)+"""</td>
|
|
|
364 |
<td style="text-align:center">"""+str(int(highReturnData.websiteSale))+"""</td>
|
|
|
365 |
<td style="text-align:center">"""+str(highReturnData.sellableCountWebsite)+"""</td>
|
|
|
366 |
<td style="text-align:center">"""+str(highReturnData.nonSellableCountWebsite)+"""</td>
|
| 11981 |
kshitij.so |
367 |
<td style="text-align:center">"""+str(round(highReturnData.sellableWebsitePercentage*100,1))+"""</td>
|
|
|
368 |
<td style="text-align:center">"""+str(round(highReturnData.nonSellableWebsitePercentage*100,1))+"""</td>
|
| 11978 |
kshitij.so |
369 |
<td style="text-align:center">"""+str(int(highReturnData.amazonSale))+"""</td>
|
|
|
370 |
<td style="text-align:center">"""+str(highReturnData.sellableCountAmazon)+"""</td>
|
|
|
371 |
<td style="text-align:center">"""+str(highReturnData.nonSellableCountAmazon)+"""</td>
|
| 11981 |
kshitij.so |
372 |
<td style="text-align:center">"""+str(round(highReturnData.sellableAmazonPercentage*100,1))+"""</td>
|
|
|
373 |
<td style="text-align:center">"""+str(round(highReturnData.nonSellableAmazonPercentage*100,1))+"""</td>
|
| 11978 |
kshitij.so |
374 |
<td style="text-align:center">"""+str(int(highReturnData.ebaySale))+"""</td>
|
|
|
375 |
<td style="text-align:center">"""+str(highReturnData.sellableCountEbay)+"""</td>
|
|
|
376 |
<td style="text-align:center">"""+str(highReturnData.nonSellableCountEbay)+"""</td>
|
| 11981 |
kshitij.so |
377 |
<td style="text-align:center">"""+str(round(highReturnData.sellableEbayPercentage*100,1))+"""</td>
|
|
|
378 |
<td style="text-align:center">"""+str(round(highReturnData.nonSellableEbayPercentage*100,1))+"""</td>
|
| 11978 |
kshitij.so |
379 |
<td style="text-align:center">"""+str(int(highReturnData.snapdealSale))+"""</td>
|
|
|
380 |
<td style="text-align:center">"""+str(highReturnData.sellableCountSnapdeal)+"""</td>
|
|
|
381 |
<td style="text-align:center">"""+str(highReturnData.nonSellableCountSnapdeal)+"""</td>
|
| 11981 |
kshitij.so |
382 |
<td style="text-align:center">"""+str(round(highReturnData.sellableSnapdealPercentage*100,1))+"""</td>
|
|
|
383 |
<td style="text-align:center">"""+str(round(highReturnData.nonSellableSnapdealPercentage*100,1))+"""</td>
|
| 11978 |
kshitij.so |
384 |
<td style="text-align:center">"""+str(int(highReturnData.flipkartSale))+"""</td>
|
|
|
385 |
<td style="text-align:center">"""+str(highReturnData.sellableCountFlipkart)+"""</td>
|
|
|
386 |
<td style="text-align:center">"""+str(highReturnData.nonSellableCountFlipkart)+"""</td>
|
| 11981 |
kshitij.so |
387 |
<td style="text-align:center">"""+str(round(highReturnData.sellableFlipkartPercentage*100,1))+"""</td>
|
|
|
388 |
<td style="text-align:center">"""+str(round(highReturnData.nonSellableFlipkartPercentage*100,1))+"""</td>
|
| 11978 |
kshitij.so |
389 |
<td style="text-align:center">"""+str(int(highReturnData.websiteSale+highReturnData.amazonSale+highReturnData.ebaySale+highReturnData.snapdealSale+highReturnData.flipkartSale))+"""</td>
|
|
|
390 |
<td style="text-align:center">"""+str(highReturnData.sellableCountWebsite+highReturnData.sellableCountAmazon+highReturnData.sellableCountEbay+highReturnData.sellableCountSnapdeal+highReturnData.sellableCountFlipkart)+"""</td>
|
|
|
391 |
<td style="text-align:center">"""+str(highReturnData.nonSellableCountWebsite+highReturnData.nonSellableCountAmazon+highReturnData.nonSellableCountEbay+highReturnData.nonSellableCountSnapdeal+highReturnData.nonSellableCountFlipkart)+"""</td>
|
| 11981 |
kshitij.so |
392 |
<td style="text-align:center">"""+str(round(highReturnData.sellableOverallPercentage*100,1))+"""</td>
|
|
|
393 |
<td style="text-align:center">"""+str(round(highReturnData.nonSellableOverallPercentage*100,1))+"""</td>
|
| 11978 |
kshitij.so |
394 |
</tr>"""
|
|
|
395 |
|
|
|
396 |
message+="""</tr></tbody></table>"""
|
|
|
397 |
|
|
|
398 |
topBrandCatReturns = []
|
|
|
399 |
|
|
|
400 |
for y in BrandCatMap.itervalues():
|
| 11998 |
kshitij.so |
401 |
if y.totalSale > 25:
|
| 11978 |
kshitij.so |
402 |
topBrandCatReturns.append(y)
|
|
|
403 |
|
|
|
404 |
sortedHighReturnRateBrandCat = sorted(topBrandCatReturns, key=lambda x: x.nonSellableReturnPercentage, reverse=True)
|
|
|
405 |
message+="""<h3>Brand Category Wise Non-Sellable Return</h3>
|
|
|
406 |
<table border="1" style="width:50%;">
|
|
|
407 |
<thead>
|
|
|
408 |
<tr><th>Brand</th>
|
|
|
409 |
<th>Category</th>
|
|
|
410 |
<th>Total Sale</th>
|
|
|
411 |
<th>Non Sellable Returns</th>
|
|
|
412 |
<th>Non Sellable Returns %</th>
|
|
|
413 |
</tr></thead>
|
|
|
414 |
<tbody>"""
|
|
|
415 |
for highReturnDataBrandCat in sortedHighReturnRateBrandCat:
|
|
|
416 |
message+="""<tr>
|
|
|
417 |
<td style="text-align:center">"""+str(highReturnDataBrandCat.brand)+"""</td>
|
|
|
418 |
<td style="text-align:center">"""+str(highReturnDataBrandCat.productGroup)+"""</td>
|
|
|
419 |
<td style="text-align:center">"""+str(int(highReturnDataBrandCat.totalSale))+"""</td>
|
|
|
420 |
<td style="text-align:center">"""+str(int(highReturnDataBrandCat.nonSellableReturn))+"""</td>
|
| 11981 |
kshitij.so |
421 |
<td style="text-align:center">"""+str(round(highReturnDataBrandCat.nonSellableReturnPercentage*100,1))+"""</td>
|
| 11978 |
kshitij.so |
422 |
</tr>"""
|
|
|
423 |
message+="""</tr></tbody></table></body></html>"""
|
|
|
424 |
|
|
|
425 |
wbk = xlwt.Workbook()
|
|
|
426 |
sheet = wbk.add_sheet('Source Wise Return')
|
|
|
427 |
xstr = lambda s: s or ""
|
|
|
428 |
heading_xf = xlwt.easyxf('font: bold on; align: wrap off, vert centre, horiz center')
|
|
|
429 |
|
|
|
430 |
excel_integer_format = '0'
|
|
|
431 |
integer_style = xlwt.XFStyle()
|
|
|
432 |
integer_style.num_format_str = excel_integer_format
|
|
|
433 |
|
|
|
434 |
sheet.write(0, 0, "Item ID", heading_xf)
|
|
|
435 |
sheet.write(0, 1, "Product Group", heading_xf)
|
|
|
436 |
sheet.write(0, 2, "Brand", heading_xf)
|
|
|
437 |
sheet.write(0, 3, "Product", heading_xf)
|
|
|
438 |
sheet.write(0, 4, "Total Sale", heading_xf)
|
|
|
439 |
sheet.write(0, 5, "Website Sale", heading_xf)
|
|
|
440 |
sheet.write(0, 6, "Amazon Sale", heading_xf)
|
|
|
441 |
sheet.write(0, 7, "Ebay Sale", heading_xf)
|
|
|
442 |
sheet.write(0, 8, "Snapdeal Sale", heading_xf)
|
|
|
443 |
sheet.write(0, 9, "Flipkart Sale", heading_xf)
|
|
|
444 |
sheet.write(0, 10, "Sellable Website", heading_xf)
|
|
|
445 |
sheet.write(0, 11, "Non Sellable Website", heading_xf)
|
|
|
446 |
sheet.write(0, 12, "Sellable Amazon", heading_xf)
|
|
|
447 |
sheet.write(0, 13, "Non Sellable Amazon", heading_xf)
|
|
|
448 |
sheet.write(0, 14, "Sellable Ebay", heading_xf)
|
|
|
449 |
sheet.write(0, 15, "Non Sellable Ebay", heading_xf)
|
|
|
450 |
sheet.write(0, 16, "Sellable Snapdeal", heading_xf)
|
|
|
451 |
sheet.write(0, 17, "Non Sellable Snapdeal", heading_xf)
|
|
|
452 |
sheet.write(0, 18, "Sellable Flipkart", heading_xf)
|
|
|
453 |
sheet.write(0, 19, "Non Sellable Flipkart", heading_xf)
|
|
|
454 |
sheet.write(0, 20, "Total Sellable Returns", heading_xf)
|
|
|
455 |
sheet.write(0, 21, "Sellable Returns %", heading_xf)
|
|
|
456 |
sheet.write(0, 22, "Total Non Sellable Returns", heading_xf)
|
|
|
457 |
sheet.write(0, 23, "Non Sellable Returns %", heading_xf)
|
|
|
458 |
|
|
|
459 |
sheet_iterator=1
|
|
|
460 |
for k, v in SaleMap.iteritems():
|
|
|
461 |
sheet.write(sheet_iterator,0,k)
|
|
|
462 |
sheet.write(sheet_iterator,1,v.productGroup)
|
|
|
463 |
sheet.write(sheet_iterator,2,v.brand)
|
|
|
464 |
sheet.write(sheet_iterator,3,xstr(v.brand)+" "+xstr(v.model_name)+" "+xstr(v.model_number)+" "+xstr(v.color))
|
|
|
465 |
sheet.write(sheet_iterator,4,v.websiteSale+v.amazonSale+v.ebaySale+v.flipkartSale+v.snapdealSale)
|
|
|
466 |
sheet.write(sheet_iterator,5,v.websiteSale)
|
|
|
467 |
sheet.write(sheet_iterator,6,v.amazonSale)
|
|
|
468 |
sheet.write(sheet_iterator,7,v.ebaySale)
|
|
|
469 |
sheet.write(sheet_iterator,8,v.snapdealSale)
|
|
|
470 |
sheet.write(sheet_iterator,9,v.flipkartSale)
|
|
|
471 |
sheet.write(sheet_iterator,10,v.sellableCountWebsite)
|
|
|
472 |
sheet.write(sheet_iterator,11,v.nonSellableCountWebsite)
|
|
|
473 |
sheet.write(sheet_iterator,12,v.sellableCountAmazon)
|
|
|
474 |
sheet.write(sheet_iterator,13,v.nonSellableCountAmazon)
|
|
|
475 |
sheet.write(sheet_iterator,14,v.sellableCountEbay)
|
|
|
476 |
sheet.write(sheet_iterator,15,v.nonSellableCountEbay)
|
|
|
477 |
sheet.write(sheet_iterator,16,v.sellableCountSnapdeal)
|
|
|
478 |
sheet.write(sheet_iterator,17,v.nonSellableCountSnapdeal)
|
|
|
479 |
sheet.write(sheet_iterator,18,v.sellableCountFlipkart)
|
|
|
480 |
sheet.write(sheet_iterator,19,v.nonSellableCountFlipkart)
|
|
|
481 |
sheet.write(sheet_iterator,20,v.sellableCountWebsite+v.sellableCountAmazon+v.sellableCountEbay+v.sellableCountSnapdeal+v.sellableCountFlipkart)
|
|
|
482 |
if (v.websiteSale+v.amazonSale+v.ebaySale+v.flipkartSale+v.snapdealSale) > 0:
|
| 11981 |
kshitij.so |
483 |
sheet.write(sheet_iterator,21,round(float(v.sellableCountWebsite+v.sellableCountAmazon+v.sellableCountEbay+v.sellableCountSnapdeal+v.sellableCountFlipkart)*100/(v.websiteSale+v.amazonSale+v.ebaySale+v.flipkartSale+v.snapdealSale),1))
|
| 11978 |
kshitij.so |
484 |
else:
|
|
|
485 |
sheet.write(sheet_iterator,21,0)
|
|
|
486 |
sheet.write(sheet_iterator,22,v.nonSellableCountWebsite+v.nonSellableCountAmazon+v.nonSellableCountEbay+v.nonSellableCountSnapdeal+v.nonSellableCountFlipkart)
|
|
|
487 |
if (v.nonSellableCountWebsite+v.nonSellableCountAmazon+v.nonSellableCountEbay+v.nonSellableCountSnapdeal+v.nonSellableCountFlipkart) > 0:
|
| 11981 |
kshitij.so |
488 |
sheet.write(sheet_iterator,23,round(float(v.nonSellableCountWebsite+v.nonSellableCountAmazon+v.nonSellableCountEbay+v.nonSellableCountSnapdeal+v.nonSellableCountFlipkart)*100/(v.websiteSale+v.amazonSale+v.ebaySale+v.flipkartSale+v.snapdealSale),1))
|
| 11978 |
kshitij.so |
489 |
else:
|
|
|
490 |
sheet.write(sheet_iterator,23,0)
|
|
|
491 |
sheet_iterator+=1
|
|
|
492 |
filename = "/tmp/return-report-source.xls"
|
|
|
493 |
wbk.save(filename)
|
|
|
494 |
|
|
|
495 |
mailServer = smtplib.SMTP("smtp.gmail.com", 587)
|
|
|
496 |
mailServer.ehlo()
|
|
|
497 |
mailServer.starttls()
|
|
|
498 |
mailServer.ehlo()
|
|
|
499 |
|
|
|
500 |
recipients = ['kshitij.sood@saholic.com']
|
|
|
501 |
msg = MIMEMultipart()
|
|
|
502 |
msg['Subject'] = "Sale Return Source Wise" + ' - ' + str(datetime.now())
|
|
|
503 |
msg['From'] = ""
|
|
|
504 |
msg['To'] = ",".join(recipients)
|
|
|
505 |
msg.preamble = "Sale Return Source Wise" + ' - ' + str(datetime.now())
|
|
|
506 |
html_msg = MIMEText(message, 'html')
|
|
|
507 |
msg.attach(html_msg)
|
|
|
508 |
fileMsg = MIMEBase('application','vnd.ms-excel')
|
|
|
509 |
fileMsg.set_payload(file(filename).read())
|
|
|
510 |
encoders.encode_base64(fileMsg)
|
|
|
511 |
from datetime import date
|
|
|
512 |
fileMsg.add_header('Content-Disposition','attachment;filename=Return-Source-Wise' + ' - ' + date.today().isoformat() + '.xls')
|
|
|
513 |
msg.attach(fileMsg)
|
|
|
514 |
try:
|
| 11984 |
kshitij.so |
515 |
mailServer.login("cnc.center@shop2020.in", "5h0p2o2o")
|
| 11978 |
kshitij.so |
516 |
#mailServer.sendmail("cafe@nes", ['kshitij.sood@saholic.com'], msg.as_string())
|
| 11984 |
kshitij.so |
517 |
mailServer.sendmail("5h0p2o2o", recipients, msg.as_string())
|
| 11978 |
kshitij.so |
518 |
except Exception as e:
|
|
|
519 |
print e
|
| 11979 |
kshitij.so |
520 |
print "Unable to send return .Lets try with local SMTP."
|
| 11978 |
kshitij.so |
521 |
smtpServer = smtplib.SMTP('localhost')
|
|
|
522 |
smtpServer.set_debuglevel(1)
|
| 11984 |
kshitij.so |
523 |
sender = 'cnc.center@shop2020.in'
|
| 11978 |
kshitij.so |
524 |
try:
|
|
|
525 |
smtpServer.sendmail(sender, recipients, msg.as_string())
|
|
|
526 |
print "Successfully sent email"
|
|
|
527 |
except:
|
|
|
528 |
print "Error: unable to send email."
|
|
|
529 |
|
|
|
530 |
def populateBrandCategoryReturn():
|
|
|
531 |
global BrandCatMap
|
|
|
532 |
for v in SaleMap.itervalues():
|
|
|
533 |
if BrandCatMap.has_key(v.productGroup+" "+v.brand):
|
|
|
534 |
brandCatObj = BrandCatMap.get(v.productGroup+" "+v.brand)
|
|
|
535 |
totalSale = brandCatObj.totalSale + v.websiteSale + v.amazonSale + v.ebaySale + v.snapdealSale +v.flipkartSale
|
|
|
536 |
totalNonSellableReturn = brandCatObj.nonSellableReturn + v.nonSellableCountWebsite + v.nonSellableCountAmazon + v.nonSellableCountEbay + v.nonSellableCountSnapdeal + v.nonSellableCountFlipkart
|
|
|
537 |
nonSellableReturnPercentage = float(totalNonSellableReturn)/totalSale
|
|
|
538 |
brandCatObj.totalSale = totalSale
|
|
|
539 |
brandCatObj.nonSellableReturn = totalNonSellableReturn
|
|
|
540 |
brandCatObj.nonSellableReturnPercentage = nonSellableReturnPercentage
|
|
|
541 |
else:
|
|
|
542 |
totalSale = v.websiteSale + v.amazonSale + v.ebaySale + v.snapdealSale +v.flipkartSale
|
|
|
543 |
totalNonSellableReturn = v.nonSellableCountWebsite + v.nonSellableCountAmazon + v.nonSellableCountEbay + v.nonSellableCountSnapdeal + v.nonSellableCountFlipkart
|
|
|
544 |
nonSellableReturnPercentage = float(totalNonSellableReturn)/totalSale
|
|
|
545 |
brandCatObj = __BrandCatInfo(totalSale,totalNonSellableReturn,nonSellableReturnPercentage,v.brand,v.productGroup)
|
|
|
546 |
BrandCatMap[v.productGroup+" "+v.brand] = brandCatObj
|
|
|
547 |
|
|
|
548 |
|
|
|
549 |
def main():
|
|
|
550 |
populateSaleInfo()
|
|
|
551 |
calculateReturnPercentage()
|
|
|
552 |
populateBrandCategoryReturn()
|
|
|
553 |
sendEmail()
|
|
|
554 |
|
|
|
555 |
|
|
|
556 |
if __name__=='__main__':
|
|
|
557 |
main()
|