Subversion Repositories SmartDukaan

Rev

Rev 3226 | Rev 3366 | 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
 
2536 chandransh 4
@author: Chandranshu
104 ashish 5
'''
2536 chandransh 6
 
7
import sys
8
import os
9
import datetime 
10
import time
3010 chandransh 11
import logging
3044 chandransh 12
from shop2020.thriftpy.logistics.ttypes import DeliveryType
3010 chandransh 13
logging.basicConfig(level=logging.DEBUG)
14
 
2536 chandransh 15
from datetime import date
16
from textwrap import dedent
1262 varun.gupt 17
from string import Template
18
 
2851 chandransh 19
from sqlalchemy.sql.expression import and_, or_, desc, not_, distinct
2536 chandransh 20
from sqlalchemy.sql import func
21
 
22
from elixir import *
23
 
24
from reportlab.pdfgen.canvas import Canvas
25
from reportlab.rl_config import defaultPageSize
26
from reportlab.lib.units import inch
2747 chandransh 27
from shop2020.clients.PaymentClient import PaymentClient
2819 chandransh 28
from shop2020.thriftpy.warehouse.ttypes import PurchaseOrder, LineItem as POLineItem
2536 chandransh 29
 
2687 chandransh 30
from shop2020.model.v1.order.impl.model.ReturnOrder import ReturnOrder
104 ashish 31
from shop2020.model.v1.order.impl.DataService import Transaction, LineItem,\
2783 chandransh 32
    Alerts, Order, BatchNoGenerator, InvoiceIDGenerator
104 ashish 33
from shop2020.thriftpy.model.v1.order.ttypes import Transaction as T_Transaction,\
690 chandransh 34
    TransactionServiceException, TransactionStatus, OrderStatus
855 rajveer 35
from shop2020.utils.Utils import to_py_date, to_java_date
483 rajveer 36
from shop2020.model.v1 import order
743 rajveer 37
from shop2020.clients.LogisticsClient import LogisticsClient
3133 rajveer 38
from shop2020.clients.CatalogClient import CatalogClient
1262 varun.gupt 39
from shop2020.clients.UserClient import UserClient
1351 varun.gupt 40
from shop2020.clients.HelperClient import HelperClient
2536 chandransh 41
from shop2020.utils.EmailAttachmentSender import mail, get_attachment_part
2819 chandransh 42
from shop2020.clients.WarehouseClient import WarehouseClient
2842 chandransh 43
from shop2020.thriftpy.model.v1.catalog.ttypes import BillingType
104 ashish 44
 
2819 chandransh 45
PAGE_HEIGHT=defaultPageSize[1]
46
PAGE_WIDTH=defaultPageSize[0]
47
 
104 ashish 48
def get_new_transaction():
49
    transaction = Transaction()
50
    transaction.createdOn = datetime.datetime.now()
738 chandransh 51
    transaction.status = TransactionStatus.INIT
104 ashish 52
    transaction.status_message = "New transaction"
483 rajveer 53
    return transaction
54
 
55
def create_order(t_order):
56
    order = Order()
57
    if t_order.warehouse_id:
58
        order.warehouse_id = t_order.warehouse_id
509 rajveer 59
    if t_order.logistics_provider_id:    
483 rajveer 60
        order.logistics_provider_id = t_order.logistics_provider_id
61
        order.airwaybill_no = t_order.airwaybill_no
62
        order.tracking_id = t_order.tracking_id
63
    if t_order.expected_delivery_time:    
64
        order.expected_delivery_time = to_py_date(t_order.expected_delivery_time)
65
    if t_order.customer_id:    
66
        order.customer_id = t_order.customer_id
67
        order.customer_name = t_order.customer_name
860 rajveer 68
        order.customer_city = t_order.customer_city
69
        order.customer_state = t_order.customer_state
483 rajveer 70
        order.customer_mobilenumber = t_order.customer_mobilenumber
71
        order.customer_pincode = t_order.customer_pincode
738 chandransh 72
        order.customer_address1 = t_order.customer_address1
73
        order.customer_address2 = t_order.customer_address2
483 rajveer 74
        order.customer_email = t_order.customer_email
75
    #new status and status description to be added    
716 rajveer 76
    order.status = t_order.status  
483 rajveer 77
    order.statusDescription = t_order.statusDescription
78
    order.total_amount = t_order.total_amount
79
    order.total_weight = t_order.total_weight
80
    if t_order.created_timestamp:
81
        order.created_timestamp = to_py_date(t_order.created_timestamp)
82
    else:
685 chandransh 83
        order.created_timestamp = datetime.datetime.now()
483 rajveer 84
    return order
85
 
86
def create_transaction(t_transaction):
87
    t_orders = t_transaction.orders
88
    if not t_orders:
89
        raise TransactionServiceException(101, "Orders missing from the transaction")
90
    transaction = get_new_transaction()
91
    transaction.customer_id = t_transaction.customer_id 
92
    transaction.shopping_cart_id = t_transaction.shoppingCartid
2219 varun.gupt 93
    transaction.coupon_code = t_transaction.coupon_code
2815 vikas 94
    transaction.session_source = t_transaction.sessionSource
95
    transaction.session_start_time = to_py_date(t_transaction.sessionStartTime)
483 rajveer 96
 
97
    for t_order in t_orders:
98
        order = create_order(t_order)
99
        order.transaction = transaction 
100
        for line_item in t_order.lineitems:
101
            litem = LineItem()
716 rajveer 102
            litem.item_id = line_item.item_id
963 chandransh 103
            litem.productGroup = line_item.productGroup
483 rajveer 104
            litem.brand = line_item.brand
105
            if line_item.model_number:
106
                litem.model_number = line_item.model_number
107
            if line_item.model_name:    
108
                litem.model_name = line_item.model_name
908 chandransh 109
            if line_item.color:
110
                litem.color = line_item.color
483 rajveer 111
            if line_item.extra_info:
112
                litem.extra_info = line_item.extra_info
113
            litem.quantity = line_item.quantity
114
            litem.unit_price = line_item.unit_price
115
            litem.unit_weight = line_item.unit_weight
116
            litem.total_price = line_item.total_price
117
            litem.total_weight = line_item.total_weight
1262 varun.gupt 118
            litem.transfer_price = line_item.transfer_price
1976 varun.gupt 119
 
483 rajveer 120
            """
121
            if line_item.addedOn:
122
                litem.added_on = to_py_date(line_item.addedOn)
123
            else:
124
                litem.added_on = datetime.datetime.now()
125
            """
126
            litem.order = order
127
    session.commit()
128
    return transaction.id
129
 
130
def get_transaction(transaction_id):
131
    transaction = Transaction.get_by(id=transaction_id)
132
    if not transaction:
133
        raise TransactionServiceException(108, "no such transaction")
134
 
135
    return transaction
136
 
137
def get_transactions_for_customer(customer_id, from_date, to_date, status):
138
    if not customer_id:
139
        raise TransactionServiceException(101, "bad customer id")
140
    query = Transaction.query.filter(Transaction.customer_id == customer_id)
1493 vikas 141
    if status is not None:
483 rajveer 142
        query = query.filter(Transaction.status == status)
143
    if from_date:
144
        query = query.filter(Transaction.createdOn >from_date)
145
    if to_date:
146
        query = query.filter(Transaction.createdOn < to_date)
147
    return query.all()
148
 
149
def get_transactions_for_shopping_cart_id(shopping_cart_id):
150
    transactions = Transaction.query.filter_by(shopping_cart_id=shopping_cart_id).all()
151
    return transactions
152
 
153
def get_transaction_status(transaction_id):
154
    if not transaction_id:
155
        raise TransactionServiceException(101, "bad transaction id")
156
 
157
    transaction = get_transaction(transaction_id)
158
 
159
    return transaction.status
160
 
161
def change_transaction_status(transaction_id, new_status, description):
162
    transaction = get_transaction(transaction_id)
163
    transaction.status = new_status
164
    transaction.status_message = description
690 chandransh 165
    if new_status == TransactionStatus.FAILED:
166
        for order in transaction.orders:
167
            order.status = OrderStatus.PAYMENT_FAILED
2339 chandransh 168
            order.statusDescription = "Payment Failed"
3010 chandransh 169
    elif new_status == TransactionStatus.AUTHORIZED:
690 chandransh 170
        for order in transaction.orders:
171
            order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1219 chandransh 172
            order.statusDescription = "Submitted to warehouse"
3092 chandransh 173
            order.cod = False
743 rajveer 174
            #After we got payment success, we will set logistics info also 
175
            logistics_client = LogisticsClient().get_client()
176
            #FIXME line item is only one now. If multiple will come, need to fix.
871 chandransh 177
            item_id = order.lineitems[0].item_id
3044 chandransh 178
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.PREPAID)
743 rajveer 179
 
1730 ankur.sing 180
            current_time = datetime.datetime.now()
181
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
182
 
743 rajveer 183
            order.warehouse_id = logistics_info.warehouseId
184
            order.logistics_provider_id = logistics_info.providerId
185
            order.airwaybill_no = logistics_info.airway_billno
186
            order.tracking_id = order.airwaybill_no
1730 ankur.sing 187
            order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
871 chandransh 188
 
3133 rajveer 189
            catalog_client = CatalogClient().get_client()
871 chandransh 190
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)
1351 varun.gupt 191
 
1341 chandransh 192
            item_pricing = catalog_client.getItemPricing(item_id, order.warehouse_id)
193
            order.lineitems[0].transfer_price = item_pricing.transferPrice
3064 chandransh 194
    elif new_status == TransactionStatus.COD_IN_PROCESS:
195
        for order in transaction.orders:
196
            order.status = OrderStatus.INIT
197
            order.statusDescription = "Verification Pending"
198
            order.cod = True
199
            #After we got payment success, we will set logistics info also 
200
            logistics_client = LogisticsClient().get_client()
201
            #FIXME line item is only one now. If multiple will come, need to fix.
202
            item_id = order.lineitems[0].item_id
203
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.COD)
204
 
205
            current_time = datetime.datetime.now()
206
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
207
 
208
            order.warehouse_id = logistics_info.warehouseId
209
            order.logistics_provider_id = logistics_info.providerId
210
            order.airwaybill_no = logistics_info.airway_billno
211
            order.tracking_id = order.airwaybill_no
212
            order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
213
 
3133 rajveer 214
            catalog_client = CatalogClient().get_client()
3064 chandransh 215
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)
216
 
217
            item_pricing = catalog_client.getItemPricing(item_id, order.warehouse_id)
218
            order.lineitems[0].transfer_price = item_pricing.transferPrice        
1262 varun.gupt 219
 
483 rajveer 220
    session.commit()
221
    return True
222
 
1730 ankur.sing 223
def adjust_delivery_time(order_time, delivery_days):
224
    order_date = order_time.date()
225
 
226
    delivery_date = order_date + datetime.timedelta(days = delivery_days)
227
    final_delivery_date = delivery_date
228
 
229
    time_format = "%Y-%m-%d %H:%M:%S.%f"
230
    t = time.strptime(str(order_time), time_format)
231
    midnightTime = datetime.datetime(*t[:3])
232
    fromDate = to_java_date(midnightTime)
233
    toDate = -1L
234
 
235
    logistics_client = LogisticsClient().get_client()
236
    holiday_dates = logistics_client.getHolidays(fromDate, toDate)
237
    holiday_dates = [(to_py_date(h_date)).date() for h_date in holiday_dates]
238
 
239
    while order_date <= final_delivery_date:
240
        if order_date.weekday() == 6 or is_holiday(holiday_dates, order_date):
241
            delivery_days = delivery_days + 1
242
            final_delivery_date = final_delivery_date + datetime.timedelta(days = 1)
243
        order_date = order_date + datetime.timedelta(days = 1)
244
    return delivery_days
245
 
246
 
247
 
248
def is_holiday(holidays, date):
249
    try:
250
        holidays.index(date)
251
        return 1
252
    except:
253
        return 0
254
 
1398 varun.gupt 255
def enqueue_transaction_info_email(transaction_id):
1262 varun.gupt 256
    transaction = get_transaction(transaction_id)
257
 
258
    html_header = """
259
<html>
260
<body>
261
<div>
262
    <p>
263
        Hello,<br /><br />
1742 rajveer 264
        Thanks for placing order with us. Following are the details of your order:
1262 varun.gupt 265
    </p>
266
    <div>
267
        Order Date: $order_date
1569 varun.gupt 268
    </div>
1262 varun.gupt 269
    <div>
270
        <table>
1569 varun.gupt 271
        <tr><td colspan="5"><hr /></td></tr>
272
        <tr><td colspan="5" align="left"><b>Order Details</b></td></tr>
273
        <tr><td colspan="5"><hr /></td></tr>
1262 varun.gupt 274
        <tr>
2050 varun.gupt 275
            <th width="100">Order No.</th>
276
            <th>Product</th>
277
            <th width="100">Quantity</th>
278
            <th width="100">Unit Price</th>
279
            <th width="100">Amount</th>
1262 varun.gupt 280
        </tr>
281
    """
1398 varun.gupt 282
    user_email = ""
1262 varun.gupt 283
    total_amount = 0.0
284
    html_table = ""
1569 varun.gupt 285
    order_date = datetime.datetime.now()
1262 varun.gupt 286
 
287
    for order in transaction.orders:
288
        order_date = order.created_timestamp
1398 varun.gupt 289
        user_email = order.customer_email
1569 varun.gupt 290
        html_tr = "<tr><td align='center'>" + str(order.id) + "</td>"
1262 varun.gupt 291
 
292
        for lineitem in order.lineitems:
2050 varun.gupt 293
            lineitem_total_price = round(lineitem.total_price, 2)
294
 
1276 chandransh 295
            html_tr += "<td>" + str(lineitem) + "</td>"
2050 varun.gupt 296
            html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"
297
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"
298
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"
299
            total_amount += lineitem_total_price
1262 varun.gupt 300
            html_table += html_tr
2050 varun.gupt 301
 
1262 varun.gupt 302
    html_footer = """
303
        <tr><td colspan=5>&nbsp;</td></tr>
1565 varun.gupt 304
        <tr><td colspan=5><hr /></td></tr>
1262 varun.gupt 305
        <tr>
306
            <td colspan=4>Total Amount</td>
2050 varun.gupt 307
            <td> Rs. $total_amount</td>
1262 varun.gupt 308
        </tr>
1569 varun.gupt 309
        <tr><td colspan=5><hr /></td></tr>
1262 varun.gupt 310
        </table>
1569 varun.gupt 311
    </div>
1262 varun.gupt 312
    <p>
313
        Best Wishes,<br />
314
        Saholic Team
315
    </p>
316
</div>
317
</body>
318
</html>
319
    """
1398 varun.gupt 320
 
1569 varun.gupt 321
    dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")
1565 varun.gupt 322
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
323
 
1262 varun.gupt 324
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date))
2050 varun.gupt 325
    email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount))
1262 varun.gupt 326
 
1351 varun.gupt 327
    try:
328
        helper_client = HelperClient().get_client()
1398 varun.gupt 329
        helper_client.saveUserEmailForSending(user_email, "", "Saholic - Order Details", email_header + html_table + email_footer, str(transaction_id), "TransactionInfo")
1351 varun.gupt 330
        return True
331
    except Exception as e:
332
        print e
333
        return False
1262 varun.gupt 334
 
483 rajveer 335
def get_order(order_id):
336
    order = Order.get_by(id=order_id)
337
    if not order:
338
        raise TransactionServiceException(108, "no such order")
339
 
340
    return order
341
 
3014 chandransh 342
def get_orders_for_customer(customer_id, from_date, to_date, statuses):
483 rajveer 343
    if not customer_id:
344
        raise TransactionServiceException(101, "bad customer id")
345
    query = Order.query.filter(Order.customer_id == customer_id)
3014 chandransh 346
    if statuses:
347
        query = query.filter(Order.status.in_(tuple(statuses)))
483 rajveer 348
    if from_date:
349
        query = query.filter(Order.created_timestamp >from_date)
350
    if to_date:
351
        query = query.filter(Order.created_timestamp < to_date)
352
    return query.all()
353
 
1528 ankur.sing 354
def get_order_for_customer(order_id, customer_id):
355
    if not customer_id:
356
        raise TransactionServiceException(101, "bad customer id")
357
    order = get_order(order_id)
358
    if order.customer_id != customer_id:
359
        raise TransactionServiceException(108, "order: " + str(order_id) + " does not belong to customer: " + str(customer_id))
360
    return order
361
 
483 rajveer 362
def get_all_orders(status, from_date, to_date, warehouse_id):
363
    if not warehouse_id:
364
        raise TransactionServiceException(101, "bad warehouse id")
365
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
366
    if status:
367
        query = query.filter(Order.status == status)
368
    if from_date:
369
        query = query.filter(Order.created_timestamp >from_date)
370
    if to_date:
371
        query = query.filter(Order.created_timestamp < to_date)
372
    return query.all()
373
 
1382 varun.gupt 374
def get_returnable_orders_for_customer(customer_id, limit = None):
375
    if not customer_id:
376
        raise TransactionServiceException(101, "bad customer id")
377
 
378
    query = Order.query.filter(Order.customer_id == customer_id)
379
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
380
    query = query.filter(Order.status != OrderStatus.REJECTED)
381
    query = query.filter(Order.status > OrderStatus.SHIPPED_FROM_WH)
382
    query = query.filter(or_(Order.status < OrderStatus.DELIVERY_SUCCESS, Order.delivery_timestamp < datetime.datetime.now() + datetime.timedelta(hours = 48)))
383
    orders = query.all()
384
    order_ids = [order.id for order in orders]
385
    return order_ids
386
 
387
def get_cancellable_orders_for_customer(customer_id, limit = None):
388
    if not customer_id:
389
        raise TransactionServiceException(101, "bad customer id")
390
 
391
    query = Order.query.filter(Order.customer_id == customer_id)
392
    query = query.filter(Order.status != OrderStatus.REJECTED)
1483 varun.gupt 393
    query = query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING)
1382 varun.gupt 394
    query = query.filter(Order.status < OrderStatus.BILLED)
395
    orders = query.all()
396
    return [order.id for order in orders]
397
 
995 varun.gupt 398
def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):
399
    if not warehouse_id:
400
        raise TransactionServiceException(101, "bad warehouse id")
401
 
402
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
403
 
404
    if status:
405
        query = query.filter(Order.status == status)
406
 
407
    if start_billing_date:
408
        query = query.filter(Order.billing_timestamp >= start_billing_date)
409
 
410
    if end_billing_date:
411
        query = query.filter(Order.billing_timestamp <= end_billing_date)
412
 
413
    return query.all()
414
 
1528 ankur.sing 415
def get_orders_for_transaction(transaction_id, customer_id):
416
    orders = Order.query.filter_by(transaction_id=transaction_id, customer_id=customer_id).all()
417
 
1208 chandransh 418
    if not orders:
419
        raise TransactionServiceException(101, "No order for the transaction")
420
    return orders
421
 
1405 ankur.sing 422
def get_undelivered_orders(provider_id, warehouse_id):
423
    query = Order.query
424
    if provider_id != -1:
425
        query = query.filter_by(Order.logistics_provider_id == provider_id)
426
    if warehouse_id != -1:
427
        query = query.filter(Order.warehouse_id == warehouse_id)
428
    query = query.filter(and_(Order.status != OrderStatus.DELIVERY_SUCCESS, Order.status != OrderStatus.FAILED, \
429
                              Order.status > OrderStatus.SHIPPED_FROM_WH))
1479 ankur.sing 430
    #Get last midnight time instead of current time as courier company would have sent the 
431
    #delivery records updated at least till midnight and not by the current time.
432
    time_format = "%Y-%m-%d %H:%M:%S.%f"
433
    t = time.strptime(str(datetime.datetime.now()), time_format)
434
    midnightTime = datetime.datetime(*t[:3])
435
    query = query.filter(Order.expected_delivery_time < midnightTime)
1405 ankur.sing 436
    orders = query.all()
437
    return orders
438
 
1208 chandransh 439
def get_line_items_for_order(order_id):
440
    query = LineItem.query.filter(LineItem.order_id == order_id)
441
    return query.all()
442
 
483 rajveer 443
def change_order_status(self, orderId, status, description):
444
    order = get_order(orderId)
445
    order.status = status
446
    order.statusDescription = description
447
    session.commit()
448
    return True
3064 chandransh 449
 
450
def verify_order(self, orderId):
451
    logging.info("Verifying order no: " + str(orderId))
452
    order = get_order(orderId)
453
    if order.status == OrderStatus.INIT:
454
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
455
        order.statusDescription = "Submitted for processing"
456
        order.verification_timestamp = datetime.datetime.now()
457
        session.commit()
458
        logging.info("Successfully verified order no: " + str(orderId))
459
        return True
460
    else:
461
        logging.warning("Verify called for order no." + str(orderId) +" which is not in verification pending state");
462
        return False
463
 
921 rajveer 464
def accept_order(self, orderId):
3064 chandransh 465
    logging.info("Accepting order no: " + str(orderId))
921 rajveer 466
    order = get_order(orderId)
3036 chandransh 467
    if order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW]:
3064 chandransh 468
        if not order.cod:
469
            if order.transaction.status == TransactionStatus.AUTHORIZED:
470
                __capture_txn(order.transaction.id)
3010 chandransh 471
        order.status = OrderStatus.ACCEPTED
472
        order.statusDescription = "Order Accepted"
473
        order.accepted_timestamp = datetime.datetime.now()
474
        session.commit()
3064 chandransh 475
        logging.info("Successfully accepted the order no.:" + str(orderId))
3010 chandransh 476
        return True
477
    else:
3064 chandransh 478
        logging.warning("Accept called for the unacceptable order: " + str(orderId))
3010 chandransh 479
        return False
921 rajveer 480
 
3010 chandransh 481
def __capture_txn(txnId):
482
    logging.info("Capturing payment for merchant txn:" + str(txnId))
483
    payment_client = PaymentClient().get_client()
484
    capture_result = payment_client.capturePayment(txnId)
485
    if capture_result:
3064 chandransh 486
        logging.info("Successfully captured payment for merchant txn:" + str(txnId))
487
        change_transaction_status(txnId, TransactionStatus.IN_PROCESS, "Payment received")
3010 chandransh 488
    else:
489
        raise TransactionServiceException(115, "Payment capture failed.")
490
 
921 rajveer 491
def bill_order(self, orderId):
492
    order = get_order(orderId)
493
    order.status = OrderStatus.BILLED
494
    order.statusDescription = "Order Billed"
495
    order.billing_timestamp = datetime.datetime.now()
496
    session.commit()
1208 chandransh 497
    return True
921 rajveer 498
 
1149 chandransh 499
def add_billing_details(orderId, invoice_number, billed_by):
494 rajveer 500
    order = Order.get_by(id=orderId)
501
    if not order:
2783 chandransh 502
        raise TransactionServiceException(101, "No order found for the given order id:" + str(orderId))
494 rajveer 503
    order.invoice_number = invoice_number
504
    order.billed_by = billed_by
505
    session.commit()
506
    return True
759 chandransh 507
 
2842 chandransh 508
def add_jacket_number(self, orderId, jacket_number, imei_number, item_number, billed_by, billing_type):
2783 chandransh 509
    if jacket_number is None or jacket_number <= 0:
510
        raise TransactionServiceException(110, "Invalid jacket number")
511
 
512
    if item_number is None or item_number.strip() == "":
513
        raise TransactionServiceException(110, "Invalid item number")
514
 
515
    if billed_by is None or billed_by.strip() == "":
516
        raise TransactionServiceException(110, "Invalid Biller")
517
 
1149 chandransh 518
    order = Order.get_by(id=orderId)
519
    if not order:
2783 chandransh 520
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
521
 
522
    order.jacket_number = jacket_number
2842 chandransh 523
    if billing_type == BillingType.OURS:
524
        order.invoice_number = get_next_invoice_number()
525
        order.billed_by = billed_by
526
        order.status = OrderStatus.BILLED
527
        order.statusDescription = "Order Billed"
528
        order.billing_timestamp = datetime.datetime.now()
2783 chandransh 529
 
2842 chandransh 530
        lineitem = order.lineitems[0]
531
        if lineitem.productGroup == "Handsets" and imei_number <= 0:
532
            raise TransactionServiceException(110, "No IMEI number supplied for a handset.")
533
        lineitem.item_number = item_number
534
        if imei_number > 0:
535
            lineitem.imei_number = str(imei_number)
2783 chandransh 536
 
1149 chandransh 537
    session.commit()
538
    return True
539
 
1220 chandransh 540
def batch_orders(warehouseId):
541
    if not warehouseId:
542
        raise TransactionServiceException(101, "bad warehouse id")
1225 chandransh 543
 
544
    batchno_generator = BatchNoGenerator()
545
    session.commit()
1220 chandransh 546
    query = Order.query.filter_by(warehouse_id=warehouseId)
547
    query = query.filter_by(status=OrderStatus.SUBMITTED_FOR_PROCESSING)
548
    query = query.order_by(Order.created_timestamp)
549
    pending_orders = query.all()
1225 chandransh 550
 
1220 chandransh 551
    serial_no = 1
552
    for order in pending_orders:
1276 chandransh 553
        order.batchNo = batchno_generator.id
1220 chandransh 554
        order.serialNo = serial_no
555
        serial_no += 1
556
    session.commit() 
557
    pending_orders = query.all()
558
    return pending_orders
559
 
560
def order_outofstock(orderId):
1911 chandransh 561
    '''
562
    Mark order as out of stock
563
    '''
1220 chandransh 564
    order = get_order(orderId)
565
    order.status = OrderStatus.INVENTORY_LOW
566
    order.statusDescription = "Low Inventory"
567
    order.outofstock_timestamp = datetime.datetime.now()
568
    session.commit()
569
    return True
570
 
3064 chandransh 571
def mark_orders_as_manifested(warehouse_id, provider_id, cod):
759 chandransh 572
    try:
986 chandransh 573
        current_timestamp = datetime.datetime.now()
3064 chandransh 574
        orders = Order.query.filter_by(warehouse_id = warehouse_id, logistics_provider_id = provider_id, status = OrderStatus.BILLED, cod = cod).all()
759 chandransh 575
        for order in orders:
576
            order.status = OrderStatus.SHIPPED_FROM_WH
987 chandransh 577
            order.statusDescription = "Order shipped from warehouse"
986 chandransh 578
            order.shipping_timestamp = current_timestamp
759 chandransh 579
        session.commit()
580
        return True
581
    except:
582
        return False
1113 chandransh 583
 
584
def mark_orders_as_picked_up(provider_id, pickup_details):
585
    for awb, pickup_timestamp in pickup_details.iteritems():
1135 chandransh 586
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 587
        if order == None or order.status != OrderStatus.SHIPPED_FROM_WH:
2220 chandransh 588
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
589
            continue
1113 chandransh 590
        order.status = OrderStatus.SHIPPED_TO_LOGST
591
        order.statusDescription = "Order picked up by Courier Company"
1246 chandransh 592
        order.pickup_timestamp = pickup_timestamp
1113 chandransh 593
    session.commit()
1217 chandransh 594
 
1132 chandransh 595
    current_time = datetime.datetime.now()
596
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1246 chandransh 597
    from_datetime = to_datetime - datetime.timedelta(2)
1132 chandransh 598
    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 599
    return orders_not_picked_up
600
 
1132 chandransh 601
def mark_orders_as_delivered(provider_id, delivered_orders):
602
    for awb, detail in delivered_orders.iteritems():
1135 chandransh 603
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 604
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
1911 chandransh 605
            continue
606
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1132 chandransh 607
        order.status = OrderStatus.DELIVERY_SUCCESS
608
        order.statusDescription = "Order delivered"
609
        order.delivery_timestamp, order.receiver = detail.split('|')
610
    session.commit()
611
 
1135 chandransh 612
def mark_orders_as_failed(provider_id, returned_orders):
613
    for awb, detail in returned_orders.iteritems():
614
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 615
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
616
            continue
617
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
618
        order.status = OrderStatus.SALES_RETURN_IN_TRANSIT
1135 chandransh 619
        order.delivery_timestamp, reason = detail.split('|')
620
        order.statusDescription = "Order Returned to Origin:" + reason
1911 chandransh 621
    session.commit()
1135 chandransh 622
 
1246 chandransh 623
def update_non_delivery_reason(provider_id, undelivered_orders):
624
    for awb, reason in undelivered_orders.iteritems():
625
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
626
        if order == None:
2684 chandransh 627
            continue
628
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1246 chandransh 629
        order.statusDescription = reason
630
    session.commit()
631
 
483 rajveer 632
def get_alerts(order_id, all):
633
    query = Alerts.query.filter_by(order_id=order_id)
634
    if not all:
635
        query = query.filter_by(valid=True)
636
    return query.all()
637
 
638
def set_alert(order_id, unset, type, comment):
639
    #get existing alert
640
    if unset:
641
        query = Alerts.query.filter_by(order_id=order_id)
642
        query = query.filter_by(type=type)
643
        alerts = query.all()
644
        for alert in alerts:
645
            if alert.valid:
646
                alert.valid = False
647
                alert.comment = comment
648
                alert.time_unset = datetime.datetime.now()
649
    else:
650
        alert = Alerts()
651
        alert.order_id = order_id
652
        alert.valid = True
653
        alert.type = type
654
        alert.comment = comment
655
        alert.time_set = datetime.datetime.now()
766 rajveer 656
    session.commit()    
657
 
1596 ankur.sing 658
def get_valid_order_count():
2851 chandransh 659
    '''
660
    Returns the number of orders which we processed. The reshipped orders are not
661
    counted since there'll always be a new compensating order present.
662
    '''
3216 chandransh 663
    return Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).filter(not_(Order.status.in_((OrderStatus.SALES_RET_RESHIPPED, OrderStatus.DOA_INVALID_RESHIPPED, OrderStatus.DOA_RESHIPPED, OrderStatus.CANCELED)))).count()
1596 ankur.sing 664
 
1627 ankur.sing 665
def get_cust_count_with_successful_txn():
2851 chandransh 666
    '''
667
    Returns the number of distinct customers who have done successful transactions.
668
    It uses the sqlalchemy func module to construct an efficient query.
669
    '''
670
    return session.query(func.count(distinct(Order.customer_id))).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).scalar()
1627 ankur.sing 671
 
1730 ankur.sing 672
def get_valid_orders_amount_range():
2851 chandransh 673
    '''
674
    Returns a list containing the minimum and maximum amount across all
675
    orders placed with us. No need to consider reshippped orders for min/max
676
    amount of orders.
677
    '''
678
    return session.query(func.min(Order.total_amount), func.max(Order.total_amount)).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).one()
1627 ankur.sing 679
 
1886 ankur.sing 680
def get_valid_orders(limit):
2851 chandransh 681
    '''
682
    Returns the last limit number of valid orders placed with us. Ignored the
683
    limit if it's passed as 0. Raises an excpetion if the supplied limit is 
684
    less than 0. 
685
    '''
686
    if limit < 0:
687
        raise TransactionServiceException(101, "Invalid argument limit " + limit)
3072 chandransh 688
    query = Order.query.filter(Order.status >= OrderStatus.INIT)
1886 ankur.sing 689
    query = query.order_by(desc(Order.created_timestamp))
2851 chandransh 690
    if limit != 0:
1886 ankur.sing 691
        query = query.limit(limit)
692
    return query.all()
693
 
2783 chandransh 694
def get_next_invoice_number():
695
    entity_id = InvoiceIDGenerator.query.with_lockmode("update").one()
696
    invoice_number = entity_id.id + 1
697
    entity_id.id = invoice_number
698
    session.commit()
699
    return invoice_number
700
 
2536 chandransh 701
def toggle_doa_flag(order_id):
702
    order = get_order(order_id)
703
    if(order.doaFlag):
704
        order.doaFlag = False
705
    else:
706
        order.doaFlag = True
707
    session.commit()
708
    return order.doaFlag
709
 
710
def request_pickup_number(order_id):
711
    order = get_order(order_id)
712
    if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_PICKUP_REQUESTED:
713
        return False
714
    from_user = 'cnc.center@shop2020.in'
715
    from_pwd = '5h0p2o2o'
716
 
717
    subject = "Pickup request"
718
    try:
3133 rajveer 719
        catalog_client = CatalogClient().get_client()
2536 chandransh 720
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
721
 
722
        logistics_client = LogisticsClient().get_client()
723
        provider = logistics_client.getProvider(order.logistics_provider_id)
3051 chandransh 724
        to_addr = provider.details[DeliveryType.PREPAID].email
2536 chandransh 725
        raw_message = '''
726
        Dear Sir/Madam,
727
 
2559 chandransh 728
        Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.
2536 chandransh 729
 
730
        Pickup CODE: %(provider_code)s
731
        Total Weight: %(order_weight)s kg
732
 
2559 chandransh 733
        Pickup Address:
2536 chandransh 734
 
735
        %(customer_address)s
736
 
737
        Delivery Address:
738
 
739
        %(warehouse_executive)s
740
        %(warehouse_address)s
741
        PIN %(warehouse_pin)s
742
        Phone: %(warehouse_phone)s
743
 
744
        Thanks and Regards
745
        Anand Sinha
746
        '''
2559 chandransh 747
        message = dedent(raw_message) % { 'customer_city' : order.customer_city,
3051 chandransh 748
                                          'provider_code' : provider.details[DeliveryType.PREPAID].accountNo,
2536 chandransh 749
                                          'order_weight' : str(order.total_weight),
750
                                          'customer_address' : __get_order_address(order),
751
                                          'warehouse_executive' : 'Parmod Kumar',
752
                                          'warehouse_address' : warehouse.location,
753
                                          'warehouse_pin' : warehouse.pincode,
754
                                          'warehouse_phone': '9971573026'}
755
        mail(from_user, from_pwd, to_addr, subject, message)
756
        order.status = OrderStatus.DOA_PICKUP_REQUESTED
757
        order.statusDescription = "Pick up requested for DOA"
758
        session.commit()
759
        return True
760
    except Exception as e:
761
        print sys.exc_info()[0]
762
        return False
763
 
764
def authorize_pickup(order_id, pickup_number):
765
    order = get_order(order_id)
766
    if order.status != OrderStatus.DOA_PICKUP_REQUESTED:
767
        return False
768
    from_user = 'help@shop2020.in'
769
    from_pwd = '5h0p2o2o'
770
    subject = 'Pickup details'
771
    filename = "/tmp/" +  str(order.id) +".pdf" 
772
    try:
3133 rajveer 773
        catalog_client = CatalogClient().get_client()
2536 chandransh 774
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
775
 
776
        logistics_client = LogisticsClient().get_client()
777
        provider = logistics_client.getProvider(order.logistics_provider_id)
778
        provider_name = provider.name
779
 
780
        to_addr = order.customer_email
781
        today = date.today().strftime("%d-%B-%Y (%A)")
782
 
783
        raw_message = '''
784
        Dear Mr. %(customer_name)s,
785
 
786
        In reference to the return of order ID %(order_id)d. We request you to kindly pack the box properly with bubble wrap, and send it along with the original "DOA" certificate and the invoice.
787
        Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.
788
        We have instructed %(provider_name)s to pick up the material from the below mentioned address on %(date)s. %(provider_name)s pickup request number is %(pickup_request_no)s. Kindly keep the parcel ready.
789
 
790
        Pickup will happen from the below mentioned address:-
791
 
792
        %(customer_address)s
793
 
794
        Do let us know in case of any concerns
795
 
796
        Thanks & Regards
797
        Saholic Team
798
        '''
799
        message = dedent(raw_message) % {'customer_name' : order.customer_name,
800
                                         'order_id' : order_id,
801
                                         'provider_name' : provider_name,
802
                                         'date': today,
803
                                         'pickup_request_no' : pickup_number,
804
                                         'customer_address' : __get_order_address(order)}
805
        print message
806
        __generate_return_advice(order, warehouse, provider, filename)
807
        mail(from_user, from_pwd, to_addr, subject, message, get_attachment_part(filename))
808
        order.pickupRequestNo = pickup_number
809
        order.status = OrderStatus.DOA_RETURN_AUTHORIZED
810
        order.statusDescription = "DOA pick up authorized"
2764 chandransh 811
        order.doa_auth_timestamp = datetime.datetime.now()
2536 chandransh 812
        session.commit()
813
        return True
814
    except Exception as e:
815
        print sys.exc_info()[0]
816
        return False
817
    finally:
818
        if os.path.exists(filename):
819
            os.remove(filename)
820
 
2764 chandransh 821
def mark_doas_as_picked_up(provider_id, pickup_details):
822
    for pickupNo, doa_pickup_timestamp in pickup_details.iteritems():
823
        order = Order.query.filter_by(pickupRequestNo=pickupNo, logistics_provider_id = provider_id).first()
824
        if order == None or order.status != OrderStatus.DOA_RETURN_AUTHORIZED:
825
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
826
            continue
827
        order.status = OrderStatus.DOA_RETURN_IN_TRANSIT
828
        order.statusDescription = "DOA picked up by Courier Company"
829
        order.doa_pickup_timestamp = doa_pickup_timestamp
830
    session.commit()
831
 
832
    current_time = datetime.datetime.now()
833
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
834
    from_datetime = to_datetime - datetime.timedelta(2)
835
    orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.DOA_RETURN_AUTHORIZED).filter(Order.doa_auth_timestamp >= from_datetime).filter(Order.doa_auth_timestamp <= to_datetime).all()
836
    return orders_not_picked_up
837
 
2616 chandransh 838
def receive_return(order_id):
2591 chandransh 839
    order = get_order(order_id)
2616 chandransh 840
    if order.status in [OrderStatus.DOA_RETURN_AUTHORIZED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
841
        order.status = OrderStatus.DOA_RECEIVED
842
        order.statusDescription = "DOA package received"
2764 chandransh 843
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 844
        session.commit()
845
    elif order.status == OrderStatus.SALES_RETURN_IN_TRANSIT :
846
        order.status = OrderStatus.SALES_RET_RECEIVED
847
        order.statusDescription = "Sales return received"
2764 chandransh 848
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 849
        session.commit()
850
    else:
2591 chandransh 851
        return False
852
    return True
853
 
854
def validate_doa(order_id, is_valid):
855
    order = get_order(order_id)
2599 chandransh 856
    if order.status != OrderStatus.DOA_RECEIVED:
2591 chandransh 857
        return False
858
    if is_valid:
2609 chandransh 859
        order.status = OrderStatus.DOA_CERT_VALID
860
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 861
    else:
862
        order.status = OrderStatus.DOA_CERT_INVALID
863
        order.statusDescription = "DOA Certificate Invalid"
864
    session.commit()
865
    return True
866
 
2628 chandransh 867
def reship_order(order_id):
868
    """
869
    If the order is in SALES_RET_RECEIVED or DOA_CERT_INVALID state, it does the following:
870
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
871
        2. Marks the current order as one of the final states SALES_RET_RESHIPPED and DOA_INVALID_RESHIPPED depending on what state the order started in.
872
 
873
    If the order is in DOA_CERT_VALID state, it does the following:
874
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
875
        2. Creates a return order for the warehouse executive to return the DOA material.
876
        3. Marks the current order as the final DOA_RESHIPPED state.
877
 
878
    Returns the id of the newly created order.
879
 
880
    Throws an exception if the order with the given id couldn't be found.
881
 
882
    Parameters:
883
     - orderId
884
    """
885
    order = get_order(order_id)
886
    if order.status == OrderStatus.SALES_RET_RECEIVED:
887
        new_order = __clone_order(order, True)
888
        order.status = OrderStatus.SALES_RET_RESHIPPED
889
        order.statusDescription = "Order Reshipped"
890
        session.commit()
891
    elif order.status == OrderStatus.DOA_CERT_INVALID:
892
        new_order = __clone_order(order, True)
893
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
894
        order.statusDescription = "Order Reshipped"
895
        session.commit()
896
    elif order.status == OrderStatus.DOA_CERT_VALID:
897
        new_order = __clone_order(order, False)
898
        ret_order = __create_return_order(order)
899
        order.status = OrderStatus.DOA_RESHIPPED
900
        order.statusDescription = "Order Reshipped"
901
        session.commit()
902
    else:
903
        raise TransactionServiceException(112, "This order can't be reshipped")
904
 
2764 chandransh 905
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 906
    order.new_order_id = new_order.id
907
    session.commit()
908
 
909
    return new_order.id
910
 
3226 chandransh 911
def refund_order(order_id, refunded_by, reason):
2628 chandransh 912
    """
913
    If the order is in SALES_RET_RECEIVED, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
914
        1. Creates a refund request for batch processing.
915
        2. Creates a return order for the warehouse executive to return the shipped material.
916
        3. Marks the current order as SALES_RET_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
917
 
918
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
919
        1. Creates a refund request for batch processing.
3226 chandransh 920
        2. Cancels the reservation of the item in the warehouse.
921
        3. Marks the current order as the REFUNDED final state.
2628 chandransh 922
 
3226 chandransh 923
    For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
924
        1. Cancels the reservation of the item in the warehouse.
925
        2. Marks the current order as CANCELED.
926
 
927
    In all cases, it updates the reason for cancellation or refund and the person who performed the action.
928
 
929
    Returns True if it is successful, False otherwise.
2628 chandransh 930
 
931
    Throws an exception if the order with the given id couldn't be found.
932
 
933
    Parameters:
3226 chandransh 934
     - order_id
935
     - refunded_by
936
     - reason
2628 chandransh 937
    """
938
    status_transition = {OrderStatus.SALES_RET_RECEIVED : OrderStatus.SALES_RET_REFUNDED,
939
                         OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
940
                         OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
3191 chandransh 941
                         OrderStatus.INIT : OrderStatus.CANCELED,
2628 chandransh 942
                         OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.REFUNDED,
943
                         OrderStatus.INVENTORY_LOW : OrderStatus.REFUNDED
944
                         }
945
    order = get_order(order_id)
3186 chandransh 946
 
947
    if order.status not in status_transition.keys():
948
        raise TransactionServiceException(114, "This order can't be refunded")
949
 
3226 chandransh 950
    if order.cod:
951
        if order.status in [OrderStatus.INIT, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW]:
952
            __update_inventory_reservation(order)
953
            order.statusDescription = "Order Cancelled"
954
        elif order.status in [OrderStatus.SALES_RET_RECEIVED, OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID] :
955
            __create_return_order(order)
956
            __create_refund(order)
957
            order.statusDescription = "Order Refunded"
958
    else:
959
        if order.status in [OrderStatus.SALES_RET_RECEIVED, OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID] :
960
            __create_return_order(order)
961
            __create_refund(order)
962
            order.statusDescription = "Order Refunded"
963
        elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW]:
3191 chandransh 964
            __create_cancellation(order)
3226 chandransh 965
            __update_inventory_reservation(order)
966
            order.statusDescription = "Order Refunded"
3195 chandransh 967
 
968
    order.status = status_transition[order.status]
969
    order.refund_timestamp = datetime.datetime.now()
3226 chandransh 970
    order.refunded_by = refunded_by
971
    order.refund_reason = reason
2628 chandransh 972
 
973
    session.commit()
974
    return True
975
 
3186 chandransh 976
def __update_inventory_reservation(order):
3191 chandransh 977
    '''
978
    Reduce the reservation count for all line items of the given order.
979
    '''
3186 chandransh 980
    try:
981
        catalog_client = CatalogClient().get_client()
982
        for lineitem in order.lineitems:
983
            catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity);
984
    except:
985
        print "Unable to reduce reservation count"
986
 
2628 chandransh 987
def __clone_order(order, should_copy_billing_info):
988
    current_time = datetime.datetime.now()
989
    new_order = Order()
990
    new_order.customer_id = order.customer_id
991
    new_order.customer_name = order.customer_name
992
    new_order.customer_city = order.customer_city
993
    new_order.customer_state = order.customer_state
994
    new_order.customer_mobilenumber = order.customer_mobilenumber
995
    new_order.customer_pincode = order.customer_pincode
996
    new_order.customer_address1 = order.customer_address1
997
    new_order.customer_address2 = order.customer_address2
998
    new_order.customer_email = order.customer_email
999
    new_order.total_amount = order.total_amount
1000
    new_order.total_weight = order.total_weight
1001
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1002
    new_order.statusDescription = 'Submitted for Processing'
1003
    new_order.created_timestamp = current_time
1004
 
1005
    new_order.transaction = order.transaction
3239 chandransh 1006
    new_order.cod = False
2628 chandransh 1007
 
1008
    for line_item in order.lineitems:
1009
        litem = LineItem()
1010
        litem.item_id = line_item.item_id
1011
        litem.productGroup = line_item.productGroup
1012
        litem.brand = line_item.brand
1013
        if line_item.model_number:
1014
            litem.model_number = line_item.model_number
1015
        if line_item.model_name:    
1016
            litem.model_name = line_item.model_name
1017
        if line_item.color:
1018
            litem.color = line_item.color
1019
        if line_item.extra_info:
1020
            litem.extra_info = line_item.extra_info
1021
        litem.quantity = line_item.quantity
1022
        litem.unit_price = line_item.unit_price
1023
        litem.unit_weight = line_item.unit_weight
1024
        litem.total_price = line_item.total_price
1025
        litem.total_weight = line_item.total_weight
1026
        litem.transfer_price = line_item.transfer_price
1027
        litem.order = new_order
1028
 
1029
    logistics_client = LogisticsClient().get_client()
1030
    item_id = new_order.lineitems[0].item_id
3239 chandransh 1031
    logistics_info = logistics_client.getLogisticsInfo(new_order.customer_pincode, item_id, DeliveryType.PREPAID) #TODO: We should be able to pass another flag to suggest ignoring the inventory situation.
2628 chandransh 1032
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
1033
 
1034
    new_order.warehouse_id = logistics_info.warehouseId
1035
    new_order.logistics_provider_id = logistics_info.providerId
1036
    new_order.airwaybill_no = logistics_info.airway_billno
1037
    new_order.tracking_id = new_order.airwaybill_no
1038
    new_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
1039
 
1040
    if should_copy_billing_info:
1041
        new_order.invoice_number = order.invoice_number
1042
        new_order.billed_by = order.billed_by
1043
        new_order.warehouse_id = order.warehouse_id
1044
        new_order.accepted_timestamp = current_time
1045
        new_order.billing_timestamp = current_time    
1046
        new_order.status = OrderStatus.BILLED
1047
        new_order.statusDescription = 'Order Billed'
1048
    else:       
3133 rajveer 1049
        catalog_client = CatalogClient().get_client()
2628 chandransh 1050
        catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, new_order.lineitems[0].quantity)
1051
 
1052
        item_pricing = catalog_client.getItemPricing(item_id, order.warehouse_id)
1053
        new_order.lineitems[0].transfer_price = item_pricing.transferPrice
1054
 
1055
    return new_order
1056
 
1057
def __create_return_order(order):
2687 chandransh 1058
    ret_order = ReturnOrder(order)
2628 chandransh 1059
    return ret_order
1060
 
1061
def __create_refund(order):
2747 chandransh 1062
    payment_client = PaymentClient().get_client()
1063
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
1064
    return
2628 chandransh 1065
 
3035 chandransh 1066
def __create_cancellation(order):
1067
    return
1068
 
2536 chandransh 1069
def __get_order_address(order):
1070
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
1071
    if order.customer_address2:
1072
        address = address + order.customer_address2 + "\n"
1073
    address = address + order.customer_city + "\n"
1074
    address = address + order.customer_state + "\n"
1075
    address = address + "PIN " + order.customer_pincode + "\n"
1076
    address = address + "Phone: " + order.customer_mobilenumber
1077
    return address
1078
 
1079
def __generate_return_advice(order, warehouse, provider, filename):    
1080
    pdf = Canvas(filename)
1081
    pdf.setFont('Times-Bold',16)
1082
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
1083
    address_text.textLine("To")
1084
    address_text.textLine("Parmod Kumar")
1085
    for line in warehouse.location.split("\n"):
1086
        address_text.textLine(line)
1087
    address_text.textLine("PIN " + warehouse.pincode)
1088
    address_text.textLine("")
1089
    address_text.textLine("Phone: 9971573026")
1090
    pdf.drawText(address_text)
1091
 
1092
    pdf.setFont('Times-Roman',12)
1093
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
3051 chandransh 1094
    order_text.textLine("Pickup CODE: " + provider.details[DeliveryType.PREPAID].accountNo)
2536 chandransh 1095
    lineitem = order.lineitems[0] 
1096
    order_text.textLine("Content : " + lineitem.brand + " " + lineitem.model_number + " " + lineitem.color)
1097
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
1098
    order_text.textLine("Order ID : " + str(order.id))
1099
    pdf.drawText(order_text)
1100
    pdf.showPage()
1101
    pdf.save()
1102
    return filename
1103
 
2697 chandransh 1104
def get_return_orders(warehouse_id, from_date, to_date):
1105
    query = ReturnOrder.query.filter_by(processedStatus = False)
1106
    if warehouse_id != -1:
1107
        query = query.filter_by(warehouseId = warehouse_id)
1108
    if from_date:
1109
        query = query.filter(Order.created_timestamp >from_date)
1110
    if to_date:
1111
        query = query.filter(Order.created_timestamp < to_date)
1112
    return [return_order.to_thrift_object() for return_order in query.all()]
1113
 
2700 chandransh 1114
def get_return_order(id):
1115
    ret_order = ReturnOrder.get_by(orderId = id)
1116
    if ret_order is None:
1117
        raise TransactionServiceException(116, "No return order found for the given order id")
1118
    return ret_order.to_thrift_object()
1119
 
2697 chandransh 1120
def process_return(ret_order_id):
1121
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
1122
    if ret_order is None:
1123
        raise TransactionServiceException(116, "No return order found for the given order id")
1124
    ret_order.processedStatus = True
2701 chandransh 1125
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 1126
    session.commit()
1127
 
2819 chandransh 1128
def create_purchase_order(warehouseId):
1129
    if not warehouseId:
1130
        raise TransactionServiceException(101, "bad warehouse id")
1131
 
1132
    query = Order.query.filter_by(warehouse_id=warehouseId)
1133
    query = query.filter_by(status=OrderStatus.SUBMITTED_FOR_PROCESSING)
1134
    query = query.filter_by(purchase_order_id=None)
1135
    query = query.order_by(Order.created_timestamp)
1136
    pending_orders = query.all()
1137
 
1138
    if not pending_orders:
1139
        return -1
1140
 
1141
    t_purchase_order = PurchaseOrder()
2832 chandransh 1142
    t_purchase_order.supplierId = warehouseId
2819 chandransh 1143
    t_purchase_order.warehouseId = warehouseId
1144
    t_purchase_order.lineitems = []
1145
 
1146
    lineitems = {}
1147
 
1148
    for order in pending_orders:
1149
        for lineitem in order.lineitems:
1150
            item_id = lineitem.item_id
1151
            if lineitems.has_key(item_id):
1152
                lineitems[item_id].quantity = lineitems[item_id].quantity + lineitem.quantity
1153
            else:
1154
                t_po_lineitem = POLineItem()
1155
                t_po_lineitem.productGroup = lineitem.productGroup
1156
                t_po_lineitem.brand = lineitem.brand
1157
                t_po_lineitem.modelNumber = lineitem.model_number
1158
                t_po_lineitem.modelName = lineitem.model_name
1159
                t_po_lineitem.color = lineitem.color
1160
                t_po_lineitem.itemId = lineitem.item_id
1161
                t_po_lineitem.quantity = lineitem.quantity
1162
                t_po_lineitem.unitPrice = lineitem.transfer_price
1163
                lineitems[item_id] = t_po_lineitem
1164
                t_purchase_order.lineitems.append(t_po_lineitem)
1165
 
1166
    warehouse_client = WarehouseClient().get_client()
1167
    po_id = warehouse_client.createPurchaseOrder(t_purchase_order)
1168
 
1169
    for order in pending_orders:
1170
        order.purchase_order_id = po_id
1171
    session.commit()
1172
    return po_id
1173
 
766 rajveer 1174
def close_session():
1175
    if session.is_active:
1176
        print "session is active. closing it."
2783 chandransh 1177
        session.close()