Subversion Repositories SmartDukaan

Rev

Rev 1246 | Rev 1276 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
104 ashish 1
'''
2
Created on 29-Mar-2010
3
 
4
@author: ashish
5
'''
1262 varun.gupt 6
from string import Template
7
from email.mime.multipart import MIMEMultipart
8
from shop2020.thriftpy.utils.ttypes import HelperServiceException, Mail
9
from email.mime.base import MIMEBase
10
from email import encoders
11
from email.mime.text import MIMEText
12
import os
13
import smtplib
14
import time
15
from time import strftime
16
 
104 ashish 17
from shop2020.model.v1.order.impl.DataService import Transaction, LineItem,\
1225 chandransh 18
    Alerts, Order, BatchNoGenerator
104 ashish 19
from shop2020.thriftpy.model.v1.order.ttypes import Transaction as T_Transaction,\
690 chandransh 20
    TransactionServiceException, TransactionStatus, OrderStatus
104 ashish 21
import datetime
122 ashish 22
from elixir import *
855 rajveer 23
from shop2020.utils.Utils import to_py_date, to_java_date
104 ashish 24
from sqlalchemy.sql.expression import and_
483 rajveer 25
from shop2020.model.v1 import order
743 rajveer 26
from shop2020.clients.LogisticsClient import LogisticsClient
871 chandransh 27
from shop2020.clients.InventoryClient import InventoryClient
1262 varun.gupt 28
from shop2020.clients.UserClient import UserClient
104 ashish 29
 
30
def get_new_transaction():
31
    transaction = Transaction()
32
    transaction.createdOn = datetime.datetime.now()
738 chandransh 33
    transaction.status = TransactionStatus.INIT
104 ashish 34
    transaction.status_message = "New transaction"
483 rajveer 35
    return transaction
36
 
37
def create_order(t_order):
38
    order = Order()
39
    if t_order.warehouse_id:
40
        order.warehouse_id = t_order.warehouse_id
509 rajveer 41
    if t_order.logistics_provider_id:    
483 rajveer 42
        order.logistics_provider_id = t_order.logistics_provider_id
43
        order.airwaybill_no = t_order.airwaybill_no
44
        order.tracking_id = t_order.tracking_id
45
    if t_order.expected_delivery_time:    
46
        order.expected_delivery_time = to_py_date(t_order.expected_delivery_time)
47
    if t_order.customer_id:    
48
        order.customer_id = t_order.customer_id
49
        order.customer_name = t_order.customer_name
860 rajveer 50
        order.customer_city = t_order.customer_city
51
        order.customer_state = t_order.customer_state
483 rajveer 52
        order.customer_mobilenumber = t_order.customer_mobilenumber
53
        order.customer_pincode = t_order.customer_pincode
738 chandransh 54
        order.customer_address1 = t_order.customer_address1
55
        order.customer_address2 = t_order.customer_address2
483 rajveer 56
        order.customer_email = t_order.customer_email
57
    #new status and status description to be added    
716 rajveer 58
    order.status = t_order.status  
483 rajveer 59
    order.statusDescription = t_order.statusDescription
60
    order.total_amount = t_order.total_amount
61
    order.total_weight = t_order.total_weight
62
    if t_order.created_timestamp:
63
        order.created_timestamp = to_py_date(t_order.created_timestamp)
64
    else:
685 chandransh 65
        order.created_timestamp = datetime.datetime.now()
483 rajveer 66
    return order
67
 
68
def create_transaction(t_transaction):
69
    t_orders = t_transaction.orders
70
    if not t_orders:
71
        raise TransactionServiceException(101, "Orders missing from the transaction")
72
    transaction = get_new_transaction()
73
    transaction.customer_id = t_transaction.customer_id 
74
    transaction.shopping_cart_id = t_transaction.shoppingCartid
75
 
76
    for t_order in t_orders:
77
        order = create_order(t_order)
78
        order.transaction = transaction 
79
        for line_item in t_order.lineitems:
80
            litem = LineItem()
716 rajveer 81
            litem.item_id = line_item.item_id
963 chandransh 82
            litem.productGroup = line_item.productGroup
483 rajveer 83
            litem.brand = line_item.brand
84
            if line_item.model_number:
85
                litem.model_number = line_item.model_number
86
            if line_item.model_name:    
87
                litem.model_name = line_item.model_name
908 chandransh 88
            if line_item.color:
89
                litem.color = line_item.color
483 rajveer 90
            if line_item.extra_info:
91
                litem.extra_info = line_item.extra_info
92
            litem.quantity = line_item.quantity
93
            litem.unit_price = line_item.unit_price
94
            litem.unit_weight = line_item.unit_weight
95
            litem.total_price = line_item.total_price
96
            litem.total_weight = line_item.total_weight
1262 varun.gupt 97
            litem.transfer_price = line_item.transfer_price
483 rajveer 98
            """
99
            if line_item.addedOn:
100
                litem.added_on = to_py_date(line_item.addedOn)
101
            else:
102
                litem.added_on = datetime.datetime.now()
103
            """
104
            litem.order = order
105
    session.commit()
106
    return transaction.id
107
 
108
def get_transaction(transaction_id):
109
    transaction = Transaction.get_by(id=transaction_id)
110
    if not transaction:
111
        raise TransactionServiceException(108, "no such transaction")
112
 
113
    return transaction
114
 
115
def get_transactions_for_customer(customer_id, from_date, to_date, status):
116
    if not customer_id:
117
        raise TransactionServiceException(101, "bad customer id")
118
    query = Transaction.query.filter(Transaction.customer_id == customer_id)
119
    if status:
120
        query = query.filter(Transaction.status == status)
121
    if from_date:
122
        query = query.filter(Transaction.createdOn >from_date)
123
    if to_date:
124
        query = query.filter(Transaction.createdOn < to_date)
125
    return query.all()
126
 
127
def get_transactions_for_shopping_cart_id(shopping_cart_id):
128
    transactions = Transaction.query.filter_by(shopping_cart_id=shopping_cart_id).all()
129
    if not transactions:
130
        raise TransactionServiceException(108, "transactions for this shopping cart")
131
    return transactions
132
 
133
def get_transaction_status(transaction_id):
134
    if not transaction_id:
135
        raise TransactionServiceException(101, "bad transaction id")
136
 
137
    transaction = get_transaction(transaction_id)
138
 
139
    return transaction.status
140
 
141
def change_transaction_status(transaction_id, new_status, description):
142
    transaction = get_transaction(transaction_id)
143
    transaction.status = new_status
144
    transaction.status_message = description
690 chandransh 145
    if new_status == TransactionStatus.FAILED:
146
        for order in transaction.orders:
147
            order.status = OrderStatus.PAYMENT_FAILED
148
    elif new_status == TransactionStatus.IN_PROCESS:
149
        for order in transaction.orders:
150
            order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1219 chandransh 151
            order.statusDescription = "Submitted to warehouse"
743 rajveer 152
            #After we got payment success, we will set logistics info also 
153
            logistics_client = LogisticsClient().get_client()
154
            #FIXME line item is only one now. If multiple will come, need to fix.
871 chandransh 155
            item_id = order.lineitems[0].item_id
156
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id)
743 rajveer 157
 
158
            order.warehouse_id = logistics_info.warehouseId
159
            order.logistics_provider_id = logistics_info.providerId
160
            order.airwaybill_no = logistics_info.airway_billno
161
            order.tracking_id = order.airwaybill_no
855 rajveer 162
            order.expected_delivery_time = datetime.datetime.now() + datetime.timedelta(days=logistics_info.deliveryTime)
871 chandransh 163
 
164
            catalog_client = InventoryClient().get_client()
165
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)
1262 varun.gupt 166
 
167
        #Email the information of order placed to customer
168
        email_transaction_info_to_user(transaction_id)
483 rajveer 169
    session.commit()
170
    return True
171
 
1262 varun.gupt 172
def email_transaction_info_to_user(transaction_id):
173
    transaction = get_transaction(transaction_id)
174
 
175
    html_header = """
176
<html>
177
<body>
178
<div>
179
    <p>
180
        Hello,<br /><br />
181
        Thanks for your placing your order with us. Following are the details of your order:
182
    </p>
183
    <div>
184
        Order Date: $order_date
185
    </div><hr />
186
    <div>
187
        <b>Order Details</b>
188
        <hr />
189
        <table>
190
        <tr>
191
            <th>Order No.</th>
192
            <th>Product</th>
193
            <th>Quantity</th>
194
            <th>Unit Price</th>
195
            <th>Amount</th>
196
        </tr>
197
    """
198
    total_amount = 0.0
199
    html_table = ""
200
 
201
    for order in transaction.orders:
202
        order_date = order.created_timestamp
203
        html_tr = "<tr><td>" + str(order.id) + "</td>"
204
 
205
        for lineitem in order.lineitems:
206
            html_tr += "<td>" + " ".join([lineitem.brand, lineitem.model_name, lineitem.model_number, lineitem.color]) + "</td>"
207
            html_tr += "<td>" + str(lineitem.quantity) + "</td>"
208
            html_tr += "<td>" + str(lineitem.unit_price) + "</td>"
209
            html_tr += "<td>" + str(lineitem.total_price) + "</td></tr>"
210
            total_amount += lineitem.total_price
211
            html_table += html_tr
212
    html_footer = """
213
        <tr><td colspan=5>&nbsp;</td></tr>
214
        <tr>
215
            <td colspan=4>Total Amount</td>
216
            <td>$total_amount</td>
217
        </tr>
218
        </table>
219
    </div><hr />
220
    <p>
221
        Best Wishes,<br />
222
        Saholic Team
223
    </p>
224
</div>
225
</body>
226
</html>
227
    """
228
#    formated_order_date = strftime("%B %d, %Y %H:%M %p", time.strptime(order_date, "%Y-%m-%d %H:%M:%S"))
229
    formated_order_date = order_date
230
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date))
231
    email_footer = Template(html_footer).substitute(dict(total_amount = total_amount))
232
 
233
    user_client = UserClient().get_client()
234
    user = user_client.getUserById(transaction.customer_id)
235
    sendMail(Email(email_header + html_table + email_footer, "Saholic - Order Details", user.email))
236
    return True
483 rajveer 237
 
1262 varun.gupt 238
class Email:
239
    def __init__(self, message, subject, to):
240
        self.data = message
241
        self.sender = ''
242
        self.subject = subject
243
        self.to = [to]
244
 
245
def sendMail(mail):
246
    if not mail:
247
        raise Exception(101, "mail not present")
248
    #msg = MIMEMultipart()
249
    #mail = Mail()
250
    if mail.sender:
251
        mail.data = "This mail is sent by " + mail.sender + "\n" + mail.data
252
 
253
    msg = MIMEText(mail.data, 'html')
254
    msg['To'] = ', '.join( mail.to )
255
    if mail.sender:
256
        msg['From'] = mail.sender
257
    else:    
258
        msg['From'] = "help@saholic.com"
259
    msg['Subject'] = mail.subject
260
    #msg.attach(mail.data)
261
 
262
    for to in mail.to:
263
        mail.sender = "help@shop2020.in"
264
        mail.password = "5h0p2o2o"
265
        mailServer = smtplib.SMTP("smtp.gmail.com", 587)
266
        mailServer.ehlo()
267
        mailServer.starttls()
268
        mailServer.ehlo()
269
        mailServer.login(mail.sender, mail.password)
270
        mailServer.sendmail(mail.password, to, msg.as_string())
271
        # Should be mailServer.quit(), but that crashes...
272
        mailServer.close()
273
 
483 rajveer 274
def get_order(order_id):
275
    order = Order.get_by(id=order_id)
276
    if not order:
277
        raise TransactionServiceException(108, "no such order")
278
 
279
    return order
280
 
281
def get_orders_for_customer(customer_id, from_date, to_date, status):
282
    if not customer_id:
283
        raise TransactionServiceException(101, "bad customer id")
284
    query = Order.query.filter(Order.customer_id == customer_id)
285
    if status:
286
        query = query.filter(Order.status == status)
287
    if from_date:
288
        query = query.filter(Order.created_timestamp >from_date)
289
    if to_date:
290
        query = query.filter(Order.created_timestamp < to_date)
291
    return query.all()
292
 
293
def get_all_orders(status, from_date, to_date, warehouse_id):
294
    if not warehouse_id:
295
        raise TransactionServiceException(101, "bad warehouse id")
296
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
297
    if status:
298
        query = query.filter(Order.status == status)
299
    if from_date:
300
        query = query.filter(Order.created_timestamp >from_date)
301
    if to_date:
302
        query = query.filter(Order.created_timestamp < to_date)
303
    return query.all()
304
 
995 varun.gupt 305
def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):
306
    if not warehouse_id:
307
        raise TransactionServiceException(101, "bad warehouse id")
308
 
309
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
310
 
311
    if status:
312
        query = query.filter(Order.status == status)
313
 
314
    if start_billing_date:
315
        query = query.filter(Order.billing_timestamp >= start_billing_date)
316
 
317
    if end_billing_date:
318
        query = query.filter(Order.billing_timestamp <= end_billing_date)
319
 
320
    return query.all()
321
 
1208 chandransh 322
def get_orders_for_transaction(transaction_id):
323
    orders = Order.query.filter_by(transaction_id=transaction_id).all()
324
    if not orders:
325
        raise TransactionServiceException(101, "No order for the transaction")
326
    return orders
327
 
328
def get_line_items_for_order(order_id):
329
    query = LineItem.query.filter(LineItem.order_id == order_id)
330
    return query.all()
331
 
483 rajveer 332
def change_order_status(self, orderId, status, description):
333
    order = get_order(orderId)
334
    order.status = status
335
    order.statusDescription = description
336
    session.commit()
337
    return True
338
 
921 rajveer 339
def accept_order(self, orderId):
340
    order = get_order(orderId)
341
    order.status = OrderStatus.ACCEPTED
342
    order.statusDescription = "Order Accepted"
343
    order.accepted_timestamp = datetime.datetime.now()
344
    session.commit()
345
    return True
346
 
347
def bill_order(self, orderId):
348
    order = get_order(orderId)
349
    order.status = OrderStatus.BILLED
350
    order.statusDescription = "Order Billed"
351
    order.billing_timestamp = datetime.datetime.now()
352
    session.commit()
1208 chandransh 353
    return True
921 rajveer 354
 
1149 chandransh 355
def add_billing_details(orderId, invoice_number, billed_by):
494 rajveer 356
    order = Order.get_by(id=orderId)
357
    if not order:
358
        raise TransactionServiceException(101, "No order found for the givem orderid")
359
    order.invoice_number = invoice_number
360
    order.billed_by = billed_by
361
    session.commit()
362
    return True
759 chandransh 363
 
1149 chandransh 364
def add_jacket_number(orderId, jacket_number):
365
    order = Order.get_by(id=orderId)
366
    if not order:
367
        raise TransactionServiceException(101, "No order found for the givem orderid")
368
    order.jacket_number = jacket_number 
369
    session.commit()
370
    return True
371
 
1220 chandransh 372
def batch_orders(warehouseId):
373
    if not warehouseId:
374
        raise TransactionServiceException(101, "bad warehouse id")
1225 chandransh 375
 
376
    batchno_generator = BatchNoGenerator()
377
    session.commit()
1220 chandransh 378
    query = Order.query.filter_by(warehouse_id=warehouseId)
379
    query = query.filter_by(status=OrderStatus.SUBMITTED_FOR_PROCESSING)
380
    query = query.order_by(Order.created_timestamp)
381
    pending_orders = query.all()
1225 chandransh 382
 
1220 chandransh 383
    serial_no = 1
384
    for order in pending_orders:
1225 chandransh 385
        order.batchNo = batchno_generator.id #FIXME: Batch numbers should be read from a batch number generator
1220 chandransh 386
        order.serialNo = serial_no
387
        serial_no += 1
388
    session.commit() 
389
    pending_orders = query.all()
390
    return pending_orders
391
 
392
def order_outofstock(orderId):
393
    order = get_order(orderId)
394
    order.status = OrderStatus.INVENTORY_LOW
395
    order.statusDescription = "Low Inventory"
396
    order.outofstock_timestamp = datetime.datetime.now()
397
    session.commit()
398
    return True
399
 
759 chandransh 400
def mark_orders_as_manifested(warehouse_id, provider_id):
401
    try:
986 chandransh 402
        current_timestamp = datetime.datetime.now()
852 chandransh 403
        orders = Order.query.filter_by(warehouse_id = warehouse_id, logistics_provider_id = provider_id, status = OrderStatus.BILLED).all()
759 chandransh 404
        for order in orders:
405
            order.status = OrderStatus.SHIPPED_FROM_WH
987 chandransh 406
            order.statusDescription = "Order shipped from warehouse"
986 chandransh 407
            order.shipping_timestamp = current_timestamp
759 chandransh 408
        session.commit()
409
        return True
410
    except:
411
        return False
1113 chandransh 412
 
413
def mark_orders_as_picked_up(provider_id, pickup_details):
414
    for awb, pickup_timestamp in pickup_details.iteritems():
1135 chandransh 415
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1113 chandransh 416
        if order == None:
417
            raise TransactionServiceException(102, "No order found for the awb: " + awb)
418
        order.status = OrderStatus.SHIPPED_TO_LOGST
419
        order.statusDescription = "Order picked up by Courier Company"
1246 chandransh 420
        order.pickup_timestamp = pickup_timestamp
1113 chandransh 421
    session.commit()
1217 chandransh 422
 
1132 chandransh 423
    current_time = datetime.datetime.now()
424
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1246 chandransh 425
    from_datetime = to_datetime - datetime.timedelta(2)
1132 chandransh 426
    orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.SHIPPED_FROM_WH).filter(Order.shipping_timestamp >= from_datetime).filter(Order.shipping_timestamp <= to_datetime).all()
1113 chandransh 427
    return orders_not_picked_up
428
 
1132 chandransh 429
def mark_orders_as_delivered(provider_id, delivered_orders):
430
    for awb, detail in delivered_orders.iteritems():
1135 chandransh 431
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1132 chandransh 432
        if order == None:
433
            raise TransactionServiceException(103, "No order found for the awb:" + awb)
434
        order.status = OrderStatus.DELIVERY_SUCCESS
435
        order.statusDescription = "Order delivered"
436
        order.delivery_timestamp, order.receiver = detail.split('|')
437
    session.commit()
438
 
1135 chandransh 439
def mark_orders_as_failed(provider_id, returned_orders):
440
    for awb, detail in returned_orders.iteritems():
441
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
442
        if order == None:
443
            raise TransactionServiceException(103, "No order found for the awb:" + awb)
444
        order.status = OrderStatus.FAILED
445
        order.delivery_timestamp, reason = detail.split('|')
446
        order.statusDescription = "Order Returned to Origin:" + reason
447
    session.commit()    
448
 
1246 chandransh 449
def update_non_delivery_reason(provider_id, undelivered_orders):
450
    for awb, reason in undelivered_orders.iteritems():
451
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
452
        if order == None:
453
            raise TransactionServiceException(103, "No order found for the awb:" + awb)
454
        order.statusDescription = reason
455
    session.commit()
456
 
483 rajveer 457
def get_alerts(order_id, all):
458
    query = Alerts.query.filter_by(order_id=order_id)
459
    if not all:
460
        query = query.filter_by(valid=True)
461
    return query.all()
462
 
463
def set_alert(order_id, unset, type, comment):
464
    #get existing alert
465
    if unset:
466
        query = Alerts.query.filter_by(order_id=order_id)
467
        query = query.filter_by(type=type)
468
        alerts = query.all()
469
        for alert in alerts:
470
            if alert.valid:
471
                alert.valid = False
472
                alert.comment = comment
473
                alert.time_unset = datetime.datetime.now()
474
    else:
475
        alert = Alerts()
476
        alert.order_id = order_id
477
        alert.valid = True
478
        alert.type = type
479
        alert.comment = comment
480
        alert.time_set = datetime.datetime.now()
766 rajveer 481
    session.commit()    
482
 
483
def close_session():
484
    if session.is_active:
485
        print "session is active. closing it."
486
        session.close()