Subversion Repositories SmartDukaan

Rev

Rev 4394 | Rev 4412 | 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
 
4369 rajveer 7
from datetime import date, timedelta
2536 chandransh 8
from elixir import *
3499 mandeep.dh 9
from reportlab.lib.units import inch
2536 chandransh 10
from reportlab.pdfgen.canvas import Canvas
11
from reportlab.rl_config import defaultPageSize
3499 mandeep.dh 12
from shop2020.clients.CatalogClient import CatalogClient
13
from shop2020.clients.HelperClient import HelperClient
14
from shop2020.clients.LogisticsClient import LogisticsClient
2747 chandransh 15
from shop2020.clients.PaymentClient import PaymentClient
3499 mandeep.dh 16
from shop2020.clients.UserClient import UserClient
17
from shop2020.clients.WarehouseClient import WarehouseClient
18
from shop2020.model.v1 import order
19
from shop2020.model.v1.order.impl.DataService import Transaction, LineItem, \
4394 rajveer 20
    Order, BatchNoGenerator, InvoiceIDGenerator, \
21
    TransactionRequiringExtraProcessing, OrderInventory, Alert
2687 chandransh 22
from shop2020.model.v1.order.impl.model.ReturnOrder import ReturnOrder
3499 mandeep.dh 23
from shop2020.thriftpy.logistics.ttypes import DeliveryType
24
from shop2020.thriftpy.model.v1.catalog.ttypes import BillingType
4394 rajveer 25
from shop2020.thriftpy.model.v1.order.ttypes import \
4008 mandeep.dh 26
    TransactionServiceException, TransactionStatus, OrderStatus, DelayReason, \
4369 rajveer 27
    ExtraTransactionProcessingType, HotspotAction, TimeoutSummary
3499 mandeep.dh 28
from shop2020.thriftpy.warehouse.ttypes import PurchaseOrder, \
4365 mandeep.dh 29
    LineItem as POLineItem, ScanType
3499 mandeep.dh 30
from shop2020.utils.EmailAttachmentSender import mail, get_attachment_part
855 rajveer 31
from shop2020.utils.Utils import to_py_date, to_java_date
4008 mandeep.dh 32
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
3499 mandeep.dh 33
from sqlalchemy.sql import func
34
from sqlalchemy.sql.expression import and_, or_, desc, not_, distinct
35
from string import Template
36
from textwrap import dedent
37
import datetime
38
import logging
39
import os
4234 rajveer 40
import sys, traceback
3499 mandeep.dh 41
import time
4019 chandransh 42
from shop2020.config.client.ConfigClient import ConfigClient
3499 mandeep.dh 43
logging.basicConfig(level=logging.DEBUG)
104 ashish 44
 
3499 mandeep.dh 45
 
4019 chandransh 46
try:
47
    config_client = ConfigClient()
48
    PREPAID_SHIPPING_CUTOFF_TIME = int(config_client.get_property('delivery_cutoff_time'))
49
except Exception as ex:
50
    print "[ERROR] Unexpected config error:", sys.exc_info()[0]
51
    PREPAID_SHIPPING_CUTOFF_TIME = 15
3499 mandeep.dh 52
 
4019 chandransh 53
COD_SHIPPING_CUTOFF_TIME = 12
3499 mandeep.dh 54
 
2819 chandransh 55
PAGE_HEIGHT=defaultPageSize[1]
56
PAGE_WIDTH=defaultPageSize[0]
57
 
3499 mandeep.dh 58
ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT = {
59
        OrderStatus.SALES_RET_RESHIPPED     :  3,
60
        OrderStatus.SALES_RETURN_IN_TRANSIT : -5,
61
        OrderStatus.DELIVERY_SUCCESS        :  1,
3578 mandeep.dh 62
        OrderStatus.DOA_CERT_INVALID        : -5
3499 mandeep.dh 63
}
64
 
104 ashish 65
def get_new_transaction():
66
    transaction = Transaction()
67
    transaction.createdOn = datetime.datetime.now()
738 chandransh 68
    transaction.status = TransactionStatus.INIT
104 ashish 69
    transaction.status_message = "New transaction"
483 rajveer 70
    return transaction
71
 
72
def create_order(t_order):
73
    order = Order()
74
    if t_order.warehouse_id:
75
        order.warehouse_id = t_order.warehouse_id
509 rajveer 76
    if t_order.logistics_provider_id:    
483 rajveer 77
        order.logistics_provider_id = t_order.logistics_provider_id
78
        order.airwaybill_no = t_order.airwaybill_no
79
        order.tracking_id = t_order.tracking_id
4009 chandransh 80
    if t_order.expected_shipping_time:
4019 chandransh 81
        order.expected_shipping_time = to_py_date(t_order.expected_shipping_time).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 82
        order.promised_shipping_time = order.expected_shipping_time
4009 chandransh 83
    if t_order.expected_delivery_time:
483 rajveer 84
        order.expected_delivery_time = to_py_date(t_order.expected_delivery_time)
4102 chandransh 85
        order.promised_delivery_time = order.expected_delivery_time
483 rajveer 86
    if t_order.customer_id:    
87
        order.customer_id = t_order.customer_id
88
        order.customer_name = t_order.customer_name
860 rajveer 89
        order.customer_city = t_order.customer_city
90
        order.customer_state = t_order.customer_state
483 rajveer 91
        order.customer_mobilenumber = t_order.customer_mobilenumber
92
        order.customer_pincode = t_order.customer_pincode
738 chandransh 93
        order.customer_address1 = t_order.customer_address1
94
        order.customer_address2 = t_order.customer_address2
483 rajveer 95
        order.customer_email = t_order.customer_email
96
    #new status and status description to be added    
716 rajveer 97
    order.status = t_order.status  
483 rajveer 98
    order.statusDescription = t_order.statusDescription
99
    order.total_amount = t_order.total_amount
100
    order.total_weight = t_order.total_weight
101
    if t_order.created_timestamp:
102
        order.created_timestamp = to_py_date(t_order.created_timestamp)
103
    else:
685 chandransh 104
        order.created_timestamp = datetime.datetime.now()
483 rajveer 105
    return order
106
 
107
def create_transaction(t_transaction):
108
    t_orders = t_transaction.orders
109
    if not t_orders:
110
        raise TransactionServiceException(101, "Orders missing from the transaction")
111
    transaction = get_new_transaction()
112
    transaction.customer_id = t_transaction.customer_id 
113
    transaction.shopping_cart_id = t_transaction.shoppingCartid
2219 varun.gupt 114
    transaction.coupon_code = t_transaction.coupon_code
2815 vikas 115
    transaction.session_source = t_transaction.sessionSource
116
    transaction.session_start_time = to_py_date(t_transaction.sessionStartTime)
3858 vikas 117
    transaction.first_source = t_transaction.firstSource
118
    transaction.first_source_start_time = to_py_date(t_transaction.firstSourceTime)
483 rajveer 119
 
120
    for t_order in t_orders:
121
        order = create_order(t_order)
122
        order.transaction = transaction 
123
        for line_item in t_order.lineitems:
124
            litem = LineItem()
716 rajveer 125
            litem.item_id = line_item.item_id
963 chandransh 126
            litem.productGroup = line_item.productGroup
483 rajveer 127
            litem.brand = line_item.brand
128
            if line_item.model_number:
129
                litem.model_number = line_item.model_number
130
            if line_item.model_name:    
131
                litem.model_name = line_item.model_name
908 chandransh 132
            if line_item.color:
133
                litem.color = line_item.color
483 rajveer 134
            if line_item.extra_info:
135
                litem.extra_info = line_item.extra_info
136
            litem.quantity = line_item.quantity
137
            litem.unit_price = line_item.unit_price
138
            litem.unit_weight = line_item.unit_weight
139
            litem.total_price = line_item.total_price
140
            litem.total_weight = line_item.total_weight
4283 anupam.sin 141
            '''litem.transfer_price = line_item.transfer_price'''
4172 rajveer 142
            litem.dealText = line_item.dealText
4295 varun.gupt 143
            litem.warranty_expiry_timestamp = to_py_date(line_item.warrantry_expiry_timestamp)
1976 varun.gupt 144
 
483 rajveer 145
            """
146
            if line_item.addedOn:
147
                litem.added_on = to_py_date(line_item.addedOn)
148
            else:
149
                litem.added_on = datetime.datetime.now()
150
            """
151
            litem.order = order
152
    session.commit()
153
    return transaction.id
154
 
155
def get_transaction(transaction_id):
156
    transaction = Transaction.get_by(id=transaction_id)
157
    if not transaction:
158
        raise TransactionServiceException(108, "no such transaction")
159
 
160
    return transaction
161
 
162
def get_transactions_for_customer(customer_id, from_date, to_date, status):
163
    if not customer_id:
164
        raise TransactionServiceException(101, "bad customer id")
165
    query = Transaction.query.filter(Transaction.customer_id == customer_id)
1493 vikas 166
    if status is not None:
483 rajveer 167
        query = query.filter(Transaction.status == status)
168
    if from_date:
169
        query = query.filter(Transaction.createdOn >from_date)
170
    if to_date:
171
        query = query.filter(Transaction.createdOn < to_date)
172
    return query.all()
173
 
174
def get_transactions_for_shopping_cart_id(shopping_cart_id):
175
    transactions = Transaction.query.filter_by(shopping_cart_id=shopping_cart_id).all()
176
    return transactions
177
 
178
def get_transaction_status(transaction_id):
179
    if not transaction_id:
180
        raise TransactionServiceException(101, "bad transaction id")
181
 
182
    transaction = get_transaction(transaction_id)
183
 
184
    return transaction.status
185
 
186
def change_transaction_status(transaction_id, new_status, description):
187
    transaction = get_transaction(transaction_id)
188
    transaction.status = new_status
189
    transaction.status_message = description
690 chandransh 190
    if new_status == TransactionStatus.FAILED:
191
        for order in transaction.orders:
192
            order.status = OrderStatus.PAYMENT_FAILED
2339 chandransh 193
            order.statusDescription = "Payment Failed"
4247 rajveer 194
    elif new_status == TransactionStatus.AUTHORIZED or new_status == TransactionStatus.FLAGGED:
690 chandransh 195
        for order in transaction.orders:
4247 rajveer 196
            if new_status == TransactionStatus.AUTHORIZED:
197
                order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
198
                order.statusDescription = "Submitted to warehouse"
199
            elif new_status == TransactionStatus.FLAGGED:
200
                order.status = OrderStatus.PAYMENT_FLAGGED
201
                order.statusDescription = "Payment flagged by gateway"
3092 chandransh 202
            order.cod = False
743 rajveer 203
            #After we got payment success, we will set logistics info also 
204
            logistics_client = LogisticsClient().get_client()
205
            #FIXME line item is only one now. If multiple will come, need to fix.
871 chandransh 206
            item_id = order.lineitems[0].item_id
3044 chandransh 207
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.PREPAID)
743 rajveer 208
 
1730 ankur.sing 209
            current_time = datetime.datetime.now()
210
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4009 chandransh 211
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
1730 ankur.sing 212
 
743 rajveer 213
            order.warehouse_id = logistics_info.warehouseId
214
            order.logistics_provider_id = logistics_info.providerId
215
            order.airwaybill_no = logistics_info.airway_billno
216
            order.tracking_id = order.airwaybill_no
4019 chandransh 217
            order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 218
            order.promised_shipping_time = order.expected_shipping_time
1730 ankur.sing 219
            order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 220
            order.promised_delivery_time = order.expected_delivery_time 
871 chandransh 221
 
3133 rajveer 222
            catalog_client = CatalogClient().get_client()
871 chandransh 223
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)
1351 varun.gupt 224
 
4316 anupam.sin 225
            try:
226
                item_pricing = catalog_client.getItemPricing(item_id, -1)
227
                order.lineitems[0].transfer_price = item_pricing.transferPrice
228
            except:
229
                print "Not able to get transfer price. Skipping"
3064 chandransh 230
    elif new_status == TransactionStatus.COD_IN_PROCESS:
231
        for order in transaction.orders:
232
            order.status = OrderStatus.INIT
233
            order.statusDescription = "Verification Pending"
234
            order.cod = True
235
            #After we got payment success, we will set logistics info also 
236
            logistics_client = LogisticsClient().get_client()
237
            #FIXME line item is only one now. If multiple will come, need to fix.
238
            item_id = order.lineitems[0].item_id
239
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.COD)
240
 
241
            current_time = datetime.datetime.now()
242
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4009 chandransh 243
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
3064 chandransh 244
 
245
            order.warehouse_id = logistics_info.warehouseId
246
            order.logistics_provider_id = logistics_info.providerId
247
            order.airwaybill_no = logistics_info.airway_billno
248
            order.tracking_id = order.airwaybill_no
4019 chandransh 249
            order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 250
            order.promised_shipping_time = order.expected_shipping_time
3064 chandransh 251
            order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 252
            order.promised_delivery_time = order.expected_delivery_time
3064 chandransh 253
 
3133 rajveer 254
            catalog_client = CatalogClient().get_client()
3064 chandransh 255
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)
256
 
4316 anupam.sin 257
            try:
258
                item_pricing = catalog_client.getItemPricing(item_id, -1)
259
                order.lineitems[0].transfer_price = item_pricing.transferPrice        
260
            except:
261
                print "Not able to get transfer price. Skipping"
483 rajveer 262
    session.commit()
3499 mandeep.dh 263
 
3530 mandeep.dh 264
    try:
265
        if new_status == TransactionStatus.COD_IN_PROCESS:
4008 mandeep.dh 266
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
267
            transaction_requiring_extra_processing.category = 'COD_VERIFICATION'
268
            transaction_requiring_extra_processing.transaction_id = transaction_id
269
            session.commit()
4247 rajveer 270
        elif new_status == TransactionStatus.FLAGGED:
271
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
272
            transaction_requiring_extra_processing.category = 'PAYMENT_FLAGGED'
273
            transaction_requiring_extra_processing.transaction_id = transaction_id
274
            session.commit()
3530 mandeep.dh 275
    except Exception as e:
4065 mandeep.dh 276
        print "Error inserting transaction Id: " + str(transaction_id) + " due to " + str(e)
3499 mandeep.dh 277
 
483 rajveer 278
    return True
279
 
3994 chandransh 280
def __get_holidays(start_time=0L, to_time=-1L):
281
    '''
282
    Get the list of all public holidays since start time including the
283
    day of start time if it's a holiday
284
    '''
285
    midnightTime = start_time.replace(hour=0, minute=0, second=0, microsecond=0)
1730 ankur.sing 286
    fromDate = to_java_date(midnightTime)
287
    logistics_client = LogisticsClient().get_client()
3994 chandransh 288
    #TODO: This list should be cached after the first call.
289
    #Calling logistics server is also unnecessary.
290
    holidays = logistics_client.getHolidays(fromDate, to_time)
291
    holidays = [to_py_date(holiday).date() for holiday in holidays]
292
    return holidays
293
 
294
 
295
def adjust_delivery_time(start_time, delivery_days):
296
    '''
297
    Returns the actual no. of days which will pass while 'delivery_days'
298
    no. of business days will pass since 'order_time'. 
299
    '''
300
    start_date = start_time.date()
301
    end_date = start_date + datetime.timedelta(days = delivery_days)
302
    holidays = __get_holidays(start_time)
1730 ankur.sing 303
 
3994 chandransh 304
    while start_date <= end_date:
305
        if start_date.weekday() == 6 or start_date in holidays:
1730 ankur.sing 306
            delivery_days = delivery_days + 1
3994 chandransh 307
            end_date = end_date + datetime.timedelta(days = 1)
4088 chandransh 308
        start_date = start_date + datetime.timedelta(days = 1)
3994 chandransh 309
 
1730 ankur.sing 310
    return delivery_days
311
 
1398 varun.gupt 312
def enqueue_transaction_info_email(transaction_id):
1262 varun.gupt 313
    transaction = get_transaction(transaction_id)
314
 
315
    html_header = """
316
<html>
317
<body>
318
<div>
319
    <p>
320
        Hello,<br /><br />
1742 rajveer 321
        Thanks for placing order with us. Following are the details of your order:
1262 varun.gupt 322
    </p>
323
    <div>
324
        Order Date: $order_date
1569 varun.gupt 325
    </div>
1262 varun.gupt 326
    <div>
327
        <table>
1569 varun.gupt 328
        <tr><td colspan="5"><hr /></td></tr>
329
        <tr><td colspan="5" align="left"><b>Order Details</b></td></tr>
330
        <tr><td colspan="5"><hr /></td></tr>
1262 varun.gupt 331
        <tr>
2050 varun.gupt 332
            <th width="100">Order No.</th>
333
            <th>Product</th>
334
            <th width="100">Quantity</th>
335
            <th width="100">Unit Price</th>
336
            <th width="100">Amount</th>
1262 varun.gupt 337
        </tr>
338
    """
1398 varun.gupt 339
    user_email = ""
1262 varun.gupt 340
    total_amount = 0.0
341
    html_table = ""
1569 varun.gupt 342
    order_date = datetime.datetime.now()
1262 varun.gupt 343
 
344
    for order in transaction.orders:
345
        order_date = order.created_timestamp
1398 varun.gupt 346
        user_email = order.customer_email
1569 varun.gupt 347
        html_tr = "<tr><td align='center'>" + str(order.id) + "</td>"
1262 varun.gupt 348
 
349
        for lineitem in order.lineitems:
2050 varun.gupt 350
            lineitem_total_price = round(lineitem.total_price, 2)
351
 
1276 chandransh 352
            html_tr += "<td>" + str(lineitem) + "</td>"
2050 varun.gupt 353
            html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"
354
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"
355
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"
356
            total_amount += lineitem_total_price
1262 varun.gupt 357
            html_table += html_tr
2050 varun.gupt 358
 
1262 varun.gupt 359
    html_footer = """
360
        <tr><td colspan=5>&nbsp;</td></tr>
1565 varun.gupt 361
        <tr><td colspan=5><hr /></td></tr>
1262 varun.gupt 362
        <tr>
363
            <td colspan=4>Total Amount</td>
2050 varun.gupt 364
            <td> Rs. $total_amount</td>
1262 varun.gupt 365
        </tr>
1569 varun.gupt 366
        <tr><td colspan=5><hr /></td></tr>
4232 varun.gupt 367
        <tr>
368
            <td colspan=5>
369
                Note:- With the onset of dense fog in North India, it severely hits the operations of our courier partners. 
370
                We would like to mention that our deliveries might be slightly delayed. 
371
                We look forward to your support and understanding with regards to anticipated delays.
372
            </td>
373
        </tr>
1262 varun.gupt 374
        </table>
1569 varun.gupt 375
    </div>
1262 varun.gupt 376
    <p>
377
        Best Wishes,<br />
378
        Saholic Team
379
    </p>
380
</div>
381
</body>
382
</html>
383
    """
1398 varun.gupt 384
 
1569 varun.gupt 385
    dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")
1565 varun.gupt 386
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
387
 
1262 varun.gupt 388
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date))
2050 varun.gupt 389
    email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount))
1262 varun.gupt 390
 
1351 varun.gupt 391
    try:
392
        helper_client = HelperClient().get_client()
1398 varun.gupt 393
        helper_client.saveUserEmailForSending(user_email, "", "Saholic - Order Details", email_header + html_table + email_footer, str(transaction_id), "TransactionInfo")
1351 varun.gupt 394
        return True
395
    except Exception as e:
396
        print e
397
        return False
1262 varun.gupt 398
 
483 rajveer 399
def get_order(order_id):
400
    order = Order.get_by(id=order_id)
401
    if not order:
402
        raise TransactionServiceException(108, "no such order")
403
 
404
    return order
405
 
3014 chandransh 406
def get_orders_for_customer(customer_id, from_date, to_date, statuses):
483 rajveer 407
    if not customer_id:
408
        raise TransactionServiceException(101, "bad customer id")
409
    query = Order.query.filter(Order.customer_id == customer_id)
3014 chandransh 410
    if statuses:
411
        query = query.filter(Order.status.in_(tuple(statuses)))
483 rajveer 412
    if from_date:
413
        query = query.filter(Order.created_timestamp >from_date)
414
    if to_date:
415
        query = query.filter(Order.created_timestamp < to_date)
416
    return query.all()
417
 
1528 ankur.sing 418
def get_order_for_customer(order_id, customer_id):
419
    if not customer_id:
420
        raise TransactionServiceException(101, "bad customer id")
421
    order = get_order(order_id)
422
    if order.customer_id != customer_id:
423
        raise TransactionServiceException(108, "order: " + str(order_id) + " does not belong to customer: " + str(customer_id))
424
    return order
425
 
483 rajveer 426
def get_all_orders(status, from_date, to_date, warehouse_id):
427
    if not warehouse_id:
428
        raise TransactionServiceException(101, "bad warehouse id")
429
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
430
    if status:
431
        query = query.filter(Order.status == status)
432
    if from_date:
433
        query = query.filter(Order.created_timestamp >from_date)
434
    if to_date:
435
        query = query.filter(Order.created_timestamp < to_date)
436
    return query.all()
437
 
4133 chandransh 438
def get_orders_in_batch(statuses=[], offset=0, limit=0, warehouse_id=None):
4296 rajveer 439
    query = Order.query
440
    if warehouse_id:
441
        query = query.filter(Order.warehouse_id == warehouse_id)
4133 chandransh 442
    if statuses:
443
        query = query.filter(Order.status.in_(statuses))
444
    query = query.offset(offset)
445
    if limit:
446
        query = query.limit(limit)
447
    return query.all()
448
 
449
def get_order_count(statuses=[], warehouse_id=None):
450
    if not warehouse_id:
451
        raise TransactionServiceException(101, "bad warehouse id")
452
    query = session.query(func.count(Order.id)).filter(Order.warehouse_id == warehouse_id)
453
    if statuses:
454
        query = query.filter(Order.status.in_(statuses))
455
    return query.scalar()
456
 
1382 varun.gupt 457
def get_returnable_orders_for_customer(customer_id, limit = None):
458
    if not customer_id:
459
        raise TransactionServiceException(101, "bad customer id")
460
 
461
    query = Order.query.filter(Order.customer_id == customer_id)
462
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
463
    query = query.filter(Order.status != OrderStatus.REJECTED)
464
    query = query.filter(Order.status > OrderStatus.SHIPPED_FROM_WH)
465
    query = query.filter(or_(Order.status < OrderStatus.DELIVERY_SUCCESS, Order.delivery_timestamp < datetime.datetime.now() + datetime.timedelta(hours = 48)))
466
    orders = query.all()
467
    order_ids = [order.id for order in orders]
468
    return order_ids
469
 
470
def get_cancellable_orders_for_customer(customer_id, limit = None):
471
    if not customer_id:
472
        raise TransactionServiceException(101, "bad customer id")
473
 
474
    query = Order.query.filter(Order.customer_id == customer_id)
4343 varun.gupt 475
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
1382 varun.gupt 476
    query = query.filter(Order.status != OrderStatus.REJECTED)
4288 anupam.sin 477
    query = query.filter(Order.status <= OrderStatus.BILLED)
1382 varun.gupt 478
    orders = query.all()
479
    return [order.id for order in orders]
480
 
995 varun.gupt 481
def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):
482
    if not warehouse_id:
483
        raise TransactionServiceException(101, "bad warehouse id")
484
 
485
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
486
 
487
    if status:
488
        query = query.filter(Order.status == status)
489
 
490
    if start_billing_date:
491
        query = query.filter(Order.billing_timestamp >= start_billing_date)
492
 
493
    if end_billing_date:
494
        query = query.filter(Order.billing_timestamp <= end_billing_date)
495
 
496
    return query.all()
497
 
3451 chandransh 498
def get_orders_by_shipping_date(from_shipping_date, to_shipping_date, provider_id, warehouse_id, cod):
499
    query = Order.query.filter(Order.cod == cod)
3427 chandransh 500
 
501
    if warehouse_id and warehouse_id != -1:
502
        query = query.filter(Order.warehouse_id == warehouse_id)
503
 
504
    if provider_id and provider_id != -1:
505
        query = query.filter(Order.logistics_provider_id == provider_id)
506
 
507
    if from_shipping_date:
508
        query = query.filter(Order.shipping_timestamp >= from_shipping_date)
509
 
510
    if to_shipping_date:
511
        query = query.filter(Order.shipping_timestamp <= to_shipping_date)
512
 
513
    query = query.order_by(Order.airwaybill_no)
514
 
515
    return query.all()
516
 
1528 ankur.sing 517
def get_orders_for_transaction(transaction_id, customer_id):
518
    orders = Order.query.filter_by(transaction_id=transaction_id, customer_id=customer_id).all()
519
 
1208 chandransh 520
    if not orders:
521
        raise TransactionServiceException(101, "No order for the transaction")
522
    return orders
523
 
1405 ankur.sing 524
def get_undelivered_orders(provider_id, warehouse_id):
525
    query = Order.query
526
    if provider_id != -1:
527
        query = query.filter_by(Order.logistics_provider_id == provider_id)
528
    if warehouse_id != -1:
529
        query = query.filter(Order.warehouse_id == warehouse_id)
530
    query = query.filter(and_(Order.status != OrderStatus.DELIVERY_SUCCESS, Order.status != OrderStatus.FAILED, \
531
                              Order.status > OrderStatus.SHIPPED_FROM_WH))
1479 ankur.sing 532
    #Get last midnight time instead of current time as courier company would have sent the 
533
    #delivery records updated at least till midnight and not by the current time.
534
    time_format = "%Y-%m-%d %H:%M:%S.%f"
535
    t = time.strptime(str(datetime.datetime.now()), time_format)
536
    midnightTime = datetime.datetime(*t[:3])
537
    query = query.filter(Order.expected_delivery_time < midnightTime)
1405 ankur.sing 538
    orders = query.all()
539
    return orders
540
 
1208 chandransh 541
def get_line_items_for_order(order_id):
542
    query = LineItem.query.filter(LineItem.order_id == order_id)
543
    return query.all()
544
 
483 rajveer 545
def change_order_status(self, orderId, status, description):
546
    order = get_order(orderId)
547
    order.status = status
548
    order.statusDescription = description
549
    session.commit()
3578 mandeep.dh 550
    update_trust_level(order)
551
    return True
3499 mandeep.dh 552
 
3578 mandeep.dh 553
def update_trust_level(order):
3530 mandeep.dh 554
    try:
3578 mandeep.dh 555
        trust_level_delta = 0
556
        if order.cod == True:
557
            trust_level_delta = ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT.get(order.status, 0)
558
 
3530 mandeep.dh 559
        if (trust_level_delta != 0):
560
            user_client = UserClient().get_client()
561
            user_client.increaseTrustLevel(order.customer_id, trust_level_delta)
562
    except Exception as e:
563
        print e
3499 mandeep.dh 564
 
483 rajveer 565
    return True
3064 chandransh 566
 
567
def verify_order(self, orderId):
568
    logging.info("Verifying order no: " + str(orderId))
569
    order = get_order(orderId)
570
    if order.status == OrderStatus.INIT:
571
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
572
        order.statusDescription = "Submitted for processing"
573
        order.verification_timestamp = datetime.datetime.now()
574
        session.commit()
575
        logging.info("Successfully verified order no: " + str(orderId))
576
        return True
577
    else:
578
        logging.warning("Verify called for order no." + str(orderId) +" which is not in verification pending state");
579
        return False
580
 
4285 rajveer 581
def accept_order(orderId):
3064 chandransh 582
    logging.info("Accepting order no: " + str(orderId))
921 rajveer 583
    order = get_order(orderId)
4306 rajveer 584
    if order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3064 chandransh 585
        if not order.cod:
586
            if order.transaction.status == TransactionStatus.AUTHORIZED:
587
                __capture_txn(order.transaction.id)
3010 chandransh 588
        order.status = OrderStatus.ACCEPTED
589
        order.statusDescription = "Order Accepted"
590
        order.accepted_timestamp = datetime.datetime.now()
591
        session.commit()
3064 chandransh 592
        logging.info("Successfully accepted the order no.:" + str(orderId))
3010 chandransh 593
        return True
594
    else:
3064 chandransh 595
        logging.warning("Accept called for the unacceptable order: " + str(orderId))
3010 chandransh 596
        return False
921 rajveer 597
 
3010 chandransh 598
def __capture_txn(txnId):
599
    logging.info("Capturing payment for merchant txn:" + str(txnId))
600
    payment_client = PaymentClient().get_client()
601
    capture_result = payment_client.capturePayment(txnId)
602
    if capture_result:
3064 chandransh 603
        logging.info("Successfully captured payment for merchant txn:" + str(txnId))
604
        change_transaction_status(txnId, TransactionStatus.IN_PROCESS, "Payment received")
3010 chandransh 605
    else:
606
        raise TransactionServiceException(115, "Payment capture failed.")
607
 
4285 rajveer 608
def add_billing_details(orderId, invoice_number, imeiNumber, itemNumber, billedBy, jacketNumber, billingType, vendorId):
609
    if jacketNumber is None or jacketNumber <= 0:
2783 chandransh 610
        raise TransactionServiceException(110, "Invalid jacket number")
611
 
4285 rajveer 612
    if billedBy is None or billedBy.strip() == "":
2783 chandransh 613
        raise TransactionServiceException(110, "Invalid Biller")
614
 
1149 chandransh 615
    order = Order.get_by(id=orderId)
616
    if not order:
2783 chandransh 617
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
618
 
4283 anupam.sin 619
    if order.status == OrderStatus.ACCEPTED:
4285 rajveer 620
        order.jacket_number = jacketNumber
621
        if billingType == BillingType.OURS:
622
            if itemNumber is None or itemNumber.strip() == "":
4283 anupam.sin 623
                raise TransactionServiceException(110, "Invalid item number")
624
 
625
            order.invoice_number = get_next_invoice_number()
626
            lineitem = order.lineitems[0]
4285 rajveer 627
            if lineitem.productGroup == "Handsets" and imeiNumber <= 0:
4283 anupam.sin 628
                raise TransactionServiceException(110, "No IMEI number supplied for a handset.")
4285 rajveer 629
            lineitem.item_number = itemNumber
630
            if imeiNumber > 0:
631
                lineitem.imei_number = str(imeiNumber)
4283 anupam.sin 632
        else:
633
            order.invoice_number = invoice_number
634
 
2842 chandransh 635
        order.status = OrderStatus.BILLED
636
        order.statusDescription = "Order Billed"
637
        order.billing_timestamp = datetime.datetime.now()
4285 rajveer 638
        order.billed_by = billedBy
2842 chandransh 639
        lineitem = order.lineitems[0]
4283 anupam.sin 640
        item_id = lineitem.item_id
641
        catalog_client = CatalogClient().get_client()
4285 rajveer 642
        item_pricing = catalog_client.getItemPricing(item_id, vendorId)
643
        order.vendorId = vendorId
4283 anupam.sin 644
        lineitems = order.lineitems
645
        for lineitem in lineitems:
646
            catalog_client.reduceReservationCount(item_id, order.warehouse_id, lineitem.quantity)
647
        order.lineitems[0].transfer_price = item_pricing.transferPrice
648
        session.commit()
4365 mandeep.dh 649
 
650
        # For Mahipal warehouse, we need to scan out items for every billed order
651
        if order.warehouse_id == 7:
652
            try:
653
                warehouse_client = WarehouseClient().get_client()
654
                warehouse_client.scanOut(itemNumber, str(imeiNumber), ScanType.SALE)
655
            except:
656
                print sys.exc_info()[0]
657
                print 'Could not scan out orders'
658
 
4283 anupam.sin 659
        return True
660
    else:
661
        return False
1149 chandransh 662
 
1220 chandransh 663
def batch_orders(warehouseId):
664
    if not warehouseId:
665
        raise TransactionServiceException(101, "bad warehouse id")
1225 chandransh 666
 
667
    batchno_generator = BatchNoGenerator()
668
    session.commit()
1220 chandransh 669
    query = Order.query.filter_by(warehouse_id=warehouseId)
4381 mandeep.dh 670
    query = query.filter(or_(Order.status == OrderStatus.SUBMITTED_FOR_PROCESSING, Order.status == OrderStatus.INVENTORY_LOW))
1220 chandransh 671
    query = query.order_by(Order.created_timestamp)
672
    pending_orders = query.all()
1225 chandransh 673
 
1220 chandransh 674
    serial_no = 1
675
    for order in pending_orders:
1276 chandransh 676
        order.batchNo = batchno_generator.id
1220 chandransh 677
        order.serialNo = serial_no
678
        serial_no += 1
679
    session.commit() 
680
    pending_orders = query.all()
681
    return pending_orders
682
 
683
def order_outofstock(orderId):
1911 chandransh 684
    '''
685
    Mark order as out of stock
686
    '''
1220 chandransh 687
    order = get_order(orderId)
688
    order.status = OrderStatus.INVENTORY_LOW
689
    order.statusDescription = "Low Inventory"
690
    order.outofstock_timestamp = datetime.datetime.now()
691
    session.commit()
692
    return True
693
 
3064 chandransh 694
def mark_orders_as_manifested(warehouse_id, provider_id, cod):
759 chandransh 695
    try:
3064 chandransh 696
        orders = Order.query.filter_by(warehouse_id = warehouse_id, logistics_provider_id = provider_id, status = OrderStatus.BILLED, cod = cod).all()
759 chandransh 697
        for order in orders:
4410 rajveer 698
            order.status = OrderStatus.MANIFESTED
699
            order.statusDescription = "Order manifested"
700
        session.commit()
701
        return True
702
    except:
703
        return False
704
 
705
def mark_orders_as_shipped_from_warehouse(warehouse_id, provider_id, cod):
706
    try:
707
        current_timestamp = datetime.datetime.now()
708
        orders = Order.query.filter_by(warehouse_id = warehouse_id, logistics_provider_id = provider_id, status = OrderStatus.MANIFESTED, cod = cod).all()
709
        for order in orders:
759 chandransh 710
            order.status = OrderStatus.SHIPPED_FROM_WH
987 chandransh 711
            order.statusDescription = "Order shipped from warehouse"
986 chandransh 712
            order.shipping_timestamp = current_timestamp
759 chandransh 713
        session.commit()
714
        return True
715
    except:
716
        return False
4410 rajveer 717
 
1113 chandransh 718
def mark_orders_as_picked_up(provider_id, pickup_details):
719
    for awb, pickup_timestamp in pickup_details.iteritems():
1135 chandransh 720
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 721
        if order == None or order.status != OrderStatus.SHIPPED_FROM_WH:
2220 chandransh 722
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
723
            continue
1113 chandransh 724
        order.status = OrderStatus.SHIPPED_TO_LOGST
725
        order.statusDescription = "Order picked up by Courier Company"
1246 chandransh 726
        order.pickup_timestamp = pickup_timestamp
1113 chandransh 727
    session.commit()
1217 chandransh 728
 
1132 chandransh 729
    current_time = datetime.datetime.now()
730
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1246 chandransh 731
    from_datetime = to_datetime - datetime.timedelta(2)
1132 chandransh 732
    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 733
    return orders_not_picked_up
734
 
1132 chandransh 735
def mark_orders_as_delivered(provider_id, delivered_orders):
736
    for awb, detail in delivered_orders.iteritems():
1135 chandransh 737
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 738
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
1911 chandransh 739
            continue
740
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1132 chandransh 741
        order.status = OrderStatus.DELIVERY_SUCCESS
742
        order.statusDescription = "Order delivered"
743
        order.delivery_timestamp, order.receiver = detail.split('|')
3578 mandeep.dh 744
        update_trust_level(order)
1132 chandransh 745
    session.commit()
746
 
1135 chandransh 747
def mark_orders_as_failed(provider_id, returned_orders):
748
    for awb, detail in returned_orders.iteritems():
749
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 750
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
751
            continue
752
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
753
        order.status = OrderStatus.SALES_RETURN_IN_TRANSIT
1135 chandransh 754
        order.delivery_timestamp, reason = detail.split('|')
755
        order.statusDescription = "Order Returned to Origin:" + reason
3578 mandeep.dh 756
        update_trust_level(order)
1911 chandransh 757
    session.commit()
1135 chandransh 758
 
1246 chandransh 759
def update_non_delivery_reason(provider_id, undelivered_orders):
760
    for awb, reason in undelivered_orders.iteritems():
761
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
762
        if order == None:
2684 chandransh 763
            continue
764
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1246 chandransh 765
        order.statusDescription = reason
766
    session.commit()
767
 
4394 rajveer 768
def get_alerts(type, status, timestamp):
769
    query = Alert.query.filter(Alert.type == type)
770
    query = query.filter(Alert.status == status)
771
    if timestamp:
772
        query = query.filter(Alert.timestamp >= to_py_date(timestamp))
483 rajveer 773
    return query.all()
774
 
4394 rajveer 775
def add_alert(type, description):
776
    alert = Alert()
777
    alert.type = type
778
    alert.status = 1
779
    alert.description = description
780
    alert.timestamp = datetime.datetime.now()
766 rajveer 781
    session.commit()    
782
 
1596 ankur.sing 783
def get_valid_order_count():
2851 chandransh 784
    '''
785
    Returns the number of orders which we processed. The reshipped orders are not
786
    counted since there'll always be a new compensating order present.
787
    '''
3216 chandransh 788
    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 789
 
1627 ankur.sing 790
def get_cust_count_with_successful_txn():
2851 chandransh 791
    '''
792
    Returns the number of distinct customers who have done successful transactions.
793
    It uses the sqlalchemy func module to construct an efficient query.
794
    '''
795
    return session.query(func.count(distinct(Order.customer_id))).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).scalar()
1627 ankur.sing 796
 
1730 ankur.sing 797
def get_valid_orders_amount_range():
2851 chandransh 798
    '''
799
    Returns a list containing the minimum and maximum amount across all
800
    orders placed with us. No need to consider reshippped orders for min/max
801
    amount of orders.
802
    '''
803
    return session.query(func.min(Order.total_amount), func.max(Order.total_amount)).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).one()
1627 ankur.sing 804
 
1886 ankur.sing 805
def get_valid_orders(limit):
2851 chandransh 806
    '''
807
    Returns the last limit number of valid orders placed with us. Ignored the
808
    limit if it's passed as 0. Raises an excpetion if the supplied limit is 
809
    less than 0. 
810
    '''
811
    if limit < 0:
812
        raise TransactionServiceException(101, "Invalid argument limit " + limit)
3072 chandransh 813
    query = Order.query.filter(Order.status >= OrderStatus.INIT)
1886 ankur.sing 814
    query = query.order_by(desc(Order.created_timestamp))
2851 chandransh 815
    if limit != 0:
1886 ankur.sing 816
        query = query.limit(limit)
817
    return query.all()
818
 
2783 chandransh 819
def get_next_invoice_number():
820
    entity_id = InvoiceIDGenerator.query.with_lockmode("update").one()
821
    invoice_number = entity_id.id + 1
822
    entity_id.id = invoice_number
823
    return invoice_number
824
 
2536 chandransh 825
def toggle_doa_flag(order_id):
826
    order = get_order(order_id)
827
    if(order.doaFlag):
828
        order.doaFlag = False
829
    else:
830
        order.doaFlag = True
831
    session.commit()
832
    return order.doaFlag
833
 
834
def request_pickup_number(order_id):
835
    order = get_order(order_id)
836
    if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_PICKUP_REQUESTED:
837
        return False
838
    from_user = 'cnc.center@shop2020.in'
839
    from_pwd = '5h0p2o2o'
840
 
4227 rajveer 841
    subject = "Pickup request from " + order.customer_city
2536 chandransh 842
    try:
3133 rajveer 843
        catalog_client = CatalogClient().get_client()
2536 chandransh 844
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
845
 
846
        logistics_client = LogisticsClient().get_client()
847
        provider = logistics_client.getProvider(order.logistics_provider_id)
3051 chandransh 848
        to_addr = provider.details[DeliveryType.PREPAID].email
2536 chandransh 849
        raw_message = '''
850
        Dear Sir/Madam,
851
 
2559 chandransh 852
        Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.
2536 chandransh 853
 
854
        Pickup CODE: %(provider_code)s
855
        Total Weight: %(order_weight)s kg
856
 
2559 chandransh 857
        Pickup Address:
2536 chandransh 858
 
859
        %(customer_address)s
860
 
861
        Delivery Address:
862
 
863
        %(warehouse_executive)s
864
        %(warehouse_address)s
865
        PIN %(warehouse_pin)s
866
        Phone: %(warehouse_phone)s
867
 
868
        Thanks and Regards
4227 rajveer 869
        Sandeep Sachdeva
2536 chandransh 870
        '''
2559 chandransh 871
        message = dedent(raw_message) % { 'customer_city' : order.customer_city,
3051 chandransh 872
                                          'provider_code' : provider.details[DeliveryType.PREPAID].accountNo,
2536 chandransh 873
                                          'order_weight' : str(order.total_weight),
874
                                          'customer_address' : __get_order_address(order),
875
                                          'warehouse_executive' : 'Parmod Kumar',
876
                                          'warehouse_address' : warehouse.location,
877
                                          'warehouse_pin' : warehouse.pincode,
878
                                          'warehouse_phone': '9971573026'}
4227 rajveer 879
        #FIXME Email is hardcoded for bluedart
880
        mail(from_user, from_pwd, [to_addr, 'sonikap@bluedart.com'], subject, message)
2536 chandransh 881
        order.status = OrderStatus.DOA_PICKUP_REQUESTED
882
        order.statusDescription = "Pick up requested for DOA"
883
        session.commit()
884
        return True
885
    except Exception as e:
886
        print sys.exc_info()[0]
887
        return False
888
 
889
def authorize_pickup(order_id, pickup_number):
890
    order = get_order(order_id)
891
    if order.status != OrderStatus.DOA_PICKUP_REQUESTED:
892
        return False
893
    from_user = 'help@shop2020.in'
894
    from_pwd = '5h0p2o2o'
895
    subject = 'Pickup details'
896
    filename = "/tmp/" +  str(order.id) +".pdf" 
897
    try:
3133 rajveer 898
        catalog_client = CatalogClient().get_client()
2536 chandransh 899
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
900
 
901
        logistics_client = LogisticsClient().get_client()
902
        provider = logistics_client.getProvider(order.logistics_provider_id)
903
        provider_name = provider.name
904
 
905
        to_addr = order.customer_email
906
        today = date.today().strftime("%d-%B-%Y (%A)")
907
 
908
        raw_message = '''
909
        Dear Mr. %(customer_name)s,
910
 
911
        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.
912
        Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.
913
        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.
914
 
915
        Pickup will happen from the below mentioned address:-
916
 
917
        %(customer_address)s
918
 
919
        Do let us know in case of any concerns
920
 
921
        Thanks & Regards
922
        Saholic Team
923
        '''
924
        message = dedent(raw_message) % {'customer_name' : order.customer_name,
925
                                         'order_id' : order_id,
926
                                         'provider_name' : provider_name,
927
                                         'date': today,
928
                                         'pickup_request_no' : pickup_number,
929
                                         'customer_address' : __get_order_address(order)}
930
        print message
931
        __generate_return_advice(order, warehouse, provider, filename)
3527 chandransh 932
        mail(from_user, from_pwd, [to_addr], subject, message, [get_attachment_part(filename)])
2536 chandransh 933
        order.pickupRequestNo = pickup_number
934
        order.status = OrderStatus.DOA_RETURN_AUTHORIZED
935
        order.statusDescription = "DOA pick up authorized"
2764 chandransh 936
        order.doa_auth_timestamp = datetime.datetime.now()
2536 chandransh 937
        session.commit()
938
        return True
939
    except Exception as e:
4234 rajveer 940
        print sys.exc_info()
941
	traceback.print_tb(sys.exc_info()[2])
2536 chandransh 942
        return False
943
    finally:
944
        if os.path.exists(filename):
945
            os.remove(filename)
946
 
2764 chandransh 947
def mark_doas_as_picked_up(provider_id, pickup_details):
948
    for pickupNo, doa_pickup_timestamp in pickup_details.iteritems():
949
        order = Order.query.filter_by(pickupRequestNo=pickupNo, logistics_provider_id = provider_id).first()
950
        if order == None or order.status != OrderStatus.DOA_RETURN_AUTHORIZED:
951
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
952
            continue
953
        order.status = OrderStatus.DOA_RETURN_IN_TRANSIT
954
        order.statusDescription = "DOA picked up by Courier Company"
955
        order.doa_pickup_timestamp = doa_pickup_timestamp
956
    session.commit()
957
 
958
    current_time = datetime.datetime.now()
959
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
960
    from_datetime = to_datetime - datetime.timedelta(2)
961
    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()
962
    return orders_not_picked_up
963
 
2616 chandransh 964
def receive_return(order_id):
2591 chandransh 965
    order = get_order(order_id)
4365 mandeep.dh 966
 
967
    # FIXME: For Mahipal warehouse, we need to scan in items for every sales return
968
    if order.warehouse_id == 7:
969
        try:
970
            warehouse_client = WarehouseClient().get_client()
971
            lineitem = order.lineitems[0]
972
 
973
            # Inventory should not be updated for DOA returns 
974
            if order.status == OrderStatus.SALES_RETURN_IN_TRANSIT:
975
                warehouse_client.scanIn(order.id, lineitem.item_number, lineitem.imei_number, ScanType.SALE_RET)
976
                catalog_client = CatalogClient().get_client()
977
                catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity)
978
            elif order.status in [OrderStatus.DOA_RETURN_AUTHORIZED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
979
                warehouse_client.scanIn(order.id, lineitem.item_number, lineitem.imei_number, ScanType.DOA_IN)
980
        except:
981
            print sys.exc_info()[0]
982
            print 'Could not scan in sales return orders'
983
 
2616 chandransh 984
    if order.status in [OrderStatus.DOA_RETURN_AUTHORIZED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
985
        order.status = OrderStatus.DOA_RECEIVED
986
        order.statusDescription = "DOA package received"
2764 chandransh 987
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 988
        session.commit()
989
    elif order.status == OrderStatus.SALES_RETURN_IN_TRANSIT :
990
        order.status = OrderStatus.SALES_RET_RECEIVED
991
        order.statusDescription = "Sales return received"
2764 chandransh 992
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 993
        session.commit()
994
    else:
2591 chandransh 995
        return False
996
    return True
997
 
998
def validate_doa(order_id, is_valid):
999
    order = get_order(order_id)
2599 chandransh 1000
    if order.status != OrderStatus.DOA_RECEIVED:
2591 chandransh 1001
        return False
1002
    if is_valid:
2609 chandransh 1003
        order.status = OrderStatus.DOA_CERT_VALID
1004
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 1005
    else:
1006
        order.status = OrderStatus.DOA_CERT_INVALID
1007
        order.statusDescription = "DOA Certificate Invalid"
3578 mandeep.dh 1008
        update_trust_level(order)
2591 chandransh 1009
    session.commit()
1010
    return True
1011
 
2628 chandransh 1012
def reship_order(order_id):
1013
    """
1014
    If the order is in SALES_RET_RECEIVED or DOA_CERT_INVALID state, it does the following:
1015
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
1016
        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.
1017
 
1018
    If the order is in DOA_CERT_VALID state, it does the following:
1019
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
1020
        2. Creates a return order for the warehouse executive to return the DOA material.
1021
        3. Marks the current order as the final DOA_RESHIPPED state.
1022
 
1023
    Returns the id of the newly created order.
1024
 
1025
    Throws an exception if the order with the given id couldn't be found.
1026
 
1027
    Parameters:
1028
     - orderId
1029
    """
1030
    order = get_order(order_id)
1031
    if order.status == OrderStatus.SALES_RET_RECEIVED:
4220 rajveer 1032
        new_order = __clone_order(order, True, order.cod)
2628 chandransh 1033
        order.status = OrderStatus.SALES_RET_RESHIPPED
1034
        order.statusDescription = "Order Reshipped"
1035
        session.commit()
3578 mandeep.dh 1036
        update_trust_level(order)
2628 chandransh 1037
    elif order.status == OrderStatus.DOA_CERT_INVALID:
4220 rajveer 1038
        new_order = __clone_order(order, True, False)
2628 chandransh 1039
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
1040
        order.statusDescription = "Order Reshipped"
1041
        session.commit()
1042
    elif order.status == OrderStatus.DOA_CERT_VALID:
4220 rajveer 1043
        new_order = __clone_order(order, False, False)
2628 chandransh 1044
        ret_order = __create_return_order(order)
1045
        order.status = OrderStatus.DOA_RESHIPPED
1046
        order.statusDescription = "Order Reshipped"
1047
        session.commit()
1048
    else:
1049
        raise TransactionServiceException(112, "This order can't be reshipped")
1050
 
2764 chandransh 1051
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 1052
    order.new_order_id = new_order.id
1053
    session.commit()
1054
 
1055
    return new_order.id
1056
 
3226 chandransh 1057
def refund_order(order_id, refunded_by, reason):
2628 chandransh 1058
    """
1059
    If the order is in SALES_RET_RECEIVED, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
1060
        1. Creates a refund request for batch processing.
1061
        2. Creates a return order for the warehouse executive to return the shipped material.
1062
        3. Marks the current order as SALES_RET_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
1063
 
1064
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
1065
        1. Creates a refund request for batch processing.
3226 chandransh 1066
        2. Cancels the reservation of the item in the warehouse.
1067
        3. Marks the current order as the REFUNDED final state.
2628 chandransh 1068
 
3226 chandransh 1069
    For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
1070
        1. Cancels the reservation of the item in the warehouse.
1071
        2. Marks the current order as CANCELED.
1072
 
1073
    In all cases, it updates the reason for cancellation or refund and the person who performed the action.
1074
 
1075
    Returns True if it is successful, False otherwise.
2628 chandransh 1076
 
1077
    Throws an exception if the order with the given id couldn't be found.
1078
 
1079
    Parameters:
3226 chandransh 1080
     - order_id
1081
     - refunded_by
1082
     - reason
2628 chandransh 1083
    """
3414 chandransh 1084
    logging.info("Refunding order id: " + str(order_id))
2628 chandransh 1085
    order = get_order(order_id)
3186 chandransh 1086
 
1087
 
3366 chandransh 1088
 
3226 chandransh 1089
    if order.cod:
3414 chandransh 1090
        logging.info("Refunding COD order with status " + str(order.status))
3366 chandransh 1091
        status_transition = {OrderStatus.SALES_RET_RECEIVED : OrderStatus.SALES_RET_REFUNDED,
1092
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
1093
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
1094
                     OrderStatus.INIT : OrderStatus.CANCELED,
1095
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELED,
1096
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELED,
4306 rajveer 1097
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELED,
1098
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELED,
1099
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELED,
3366 chandransh 1100
                     OrderStatus.ACCEPTED : OrderStatus.CANCELED,
4247 rajveer 1101
                     OrderStatus.BILLED : OrderStatus.CANCELED,
1102
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST
3366 chandransh 1103
                     }
1104
        if order.status not in status_transition.keys():
1105
            raise TransactionServiceException(114, "This order can't be refunded")
1106
 
3413 chandransh 1107
        if order.status < OrderStatus.BILLED:
3226 chandransh 1108
            __update_inventory_reservation(order)
1109
            order.statusDescription = "Order Cancelled"
3415 chandransh 1110
        elif order.status == OrderStatus.BILLED:
3413 chandransh 1111
            __create_return_order(order)
1112
            order.statusDescription = "Order Cancelled"
4078 chandransh 1113
        elif order.status == OrderStatus.SALES_RET_RECEIVED:
3226 chandransh 1114
            __create_return_order(order)
4078 chandransh 1115
            order.statusDescription = "Order Returned to origin"
1116
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID] :
1117
            __create_return_order(order)
3226 chandransh 1118
            __create_refund(order)
1119
            order.statusDescription = "Order Refunded"
4247 rajveer 1120
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
1121
            if order.previousStatus  < OrderStatus.BILLED:
1122
                __update_inventory_reservation(order)
1123
                order.statusDescription = "Order Cancelled on customer request"
1124
            elif order.previousStatus == OrderStatus.BILLED:
1125
                __create_return_order(order)
1126
                order.statusDescription = "Order Cancelled on customer request"
3226 chandransh 1127
    else:
3366 chandransh 1128
        status_transition = {OrderStatus.SALES_RET_RECEIVED : OrderStatus.SALES_RET_REFUNDED,
1129
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
1130
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
1131
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.REFUNDED,
3731 chandransh 1132
                     OrderStatus.INVENTORY_LOW : OrderStatus.REFUNDED,
4306 rajveer 1133
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.REFUNDED,
1134
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.REFUNDED,
1135
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.REFUNDED,
3731 chandransh 1136
                     OrderStatus.ACCEPTED : OrderStatus.REFUNDED,
4247 rajveer 1137
                     OrderStatus.BILLED : OrderStatus.REFUNDED,
1138
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST,
1139
                     OrderStatus.PAYMENT_FLAGGED : OrderStatus.PAYMENT_FLAGGED_DENIED
3366 chandransh 1140
                     }
1141
        if order.status not in status_transition.keys():
1142
            raise TransactionServiceException(114, "This order can't be refunded")
1143
 
3226 chandransh 1144
        if order.status in [OrderStatus.SALES_RET_RECEIVED, OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID] :
1145
            __create_return_order(order)
1146
            __create_refund(order)
1147
            order.statusDescription = "Order Refunded"
4306 rajveer 1148
        elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3191 chandransh 1149
            __create_cancellation(order)
3226 chandransh 1150
            __update_inventory_reservation(order)
1151
            order.statusDescription = "Order Refunded"
4247 rajveer 1152
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
1153
            if order.previousStatus  < OrderStatus.BILLED:
1154
                __create_refund(order)
1155
                __update_inventory_reservation(order)
1156
                order.statusDescription = "Order Cancelled on customer request"
1157
            elif order.previousStatus == OrderStatus.BILLED:
1158
                __create_return_order(order)
1159
                __create_refund(order)
1160
                order.statusDescription = "Order Cancelled on customer request"
1161
        elif order.status == OrderStatus.PAYMENT_FLAGGED:
1162
            __update_inventory_reservation(order)
1163
            order.statusDescription = "Order Cancelled due to payment flagged"
3195 chandransh 1164
 
1165
    order.status = status_transition[order.status]
1166
    order.refund_timestamp = datetime.datetime.now()
3226 chandransh 1167
    order.refunded_by = refunded_by
1168
    order.refund_reason = reason
2628 chandransh 1169
 
1170
    session.commit()
1171
    return True
1172
 
3186 chandransh 1173
def __update_inventory_reservation(order):
3191 chandransh 1174
    '''
1175
    Reduce the reservation count for all line items of the given order.
1176
    '''
3186 chandransh 1177
    try:
1178
        catalog_client = CatalogClient().get_client()
1179
        for lineitem in order.lineitems:
1180
            catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity);
1181
    except:
1182
        print "Unable to reduce reservation count"
1183
 
4220 rajveer 1184
def __clone_order(order, should_copy_billing_info, is_cod):
2628 chandransh 1185
    current_time = datetime.datetime.now()
1186
    new_order = Order()
1187
    new_order.customer_id = order.customer_id
1188
    new_order.customer_name = order.customer_name
1189
    new_order.customer_city = order.customer_city
1190
    new_order.customer_state = order.customer_state
1191
    new_order.customer_mobilenumber = order.customer_mobilenumber
1192
    new_order.customer_pincode = order.customer_pincode
1193
    new_order.customer_address1 = order.customer_address1
1194
    new_order.customer_address2 = order.customer_address2
1195
    new_order.customer_email = order.customer_email
1196
    new_order.total_amount = order.total_amount
1197
    new_order.total_weight = order.total_weight
1198
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1199
    new_order.statusDescription = 'Submitted for Processing'
1200
    new_order.created_timestamp = current_time
1201
 
1202
    new_order.transaction = order.transaction
4220 rajveer 1203
    new_order.cod = is_cod
2628 chandransh 1204
 
1205
    for line_item in order.lineitems:
1206
        litem = LineItem()
1207
        litem.item_id = line_item.item_id
1208
        litem.productGroup = line_item.productGroup
1209
        litem.brand = line_item.brand
1210
        if line_item.model_number:
1211
            litem.model_number = line_item.model_number
1212
        if line_item.model_name:    
1213
            litem.model_name = line_item.model_name
1214
        if line_item.color:
1215
            litem.color = line_item.color
1216
        if line_item.extra_info:
1217
            litem.extra_info = line_item.extra_info
1218
        litem.quantity = line_item.quantity
1219
        litem.unit_price = line_item.unit_price
1220
        litem.unit_weight = line_item.unit_weight
1221
        litem.total_price = line_item.total_price
1222
        litem.total_weight = line_item.total_weight
1223
        litem.transfer_price = line_item.transfer_price
1224
        litem.order = new_order
1225
 
1226
    logistics_client = LogisticsClient().get_client()
1227
    item_id = new_order.lineitems[0].item_id
3239 chandransh 1228
    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 1229
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
1230
 
1231
    new_order.warehouse_id = logistics_info.warehouseId
1232
    new_order.logistics_provider_id = logistics_info.providerId
1233
    new_order.airwaybill_no = logistics_info.airway_billno
1234
    new_order.tracking_id = new_order.airwaybill_no
1235
    new_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 1236
    new_order.promised_delivery_time = new_order.expected_delivery_time
4299 rajveer 1237
 
2628 chandransh 1238
    if should_copy_billing_info:
1239
        new_order.invoice_number = order.invoice_number
1240
        new_order.billed_by = order.billed_by
1241
        new_order.warehouse_id = order.warehouse_id
1242
        new_order.accepted_timestamp = current_time
1243
        new_order.billing_timestamp = current_time    
1244
        new_order.status = OrderStatus.BILLED
1245
        new_order.statusDescription = 'Order Billed'
1246
    else:       
3133 rajveer 1247
        catalog_client = CatalogClient().get_client()
2628 chandransh 1248
        catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, new_order.lineitems[0].quantity)
1249
 
1250
    return new_order
1251
 
1252
def __create_return_order(order):
2687 chandransh 1253
    ret_order = ReturnOrder(order)
2628 chandransh 1254
    return ret_order
1255
 
1256
def __create_refund(order):
4078 chandransh 1257
    payment_client = PaymentClient().get_client()
1258
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
2747 chandransh 1259
    return
2628 chandransh 1260
 
3035 chandransh 1261
def __create_cancellation(order):
1262
    return
1263
 
2536 chandransh 1264
def __get_order_address(order):
1265
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
1266
    if order.customer_address2:
1267
        address = address + order.customer_address2 + "\n"
1268
    address = address + order.customer_city + "\n"
1269
    address = address + order.customer_state + "\n"
1270
    address = address + "PIN " + order.customer_pincode + "\n"
1271
    address = address + "Phone: " + order.customer_mobilenumber
1272
    return address
1273
 
1274
def __generate_return_advice(order, warehouse, provider, filename):    
1275
    pdf = Canvas(filename)
1276
    pdf.setFont('Times-Bold',16)
1277
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
1278
    address_text.textLine("To")
1279
    address_text.textLine("Parmod Kumar")
1280
    for line in warehouse.location.split("\n"):
1281
        address_text.textLine(line)
1282
    address_text.textLine("PIN " + warehouse.pincode)
1283
    address_text.textLine("")
1284
    address_text.textLine("Phone: 9971573026")
1285
    pdf.drawText(address_text)
1286
 
1287
    pdf.setFont('Times-Roman',12)
1288
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
3051 chandransh 1289
    order_text.textLine("Pickup CODE: " + provider.details[DeliveryType.PREPAID].accountNo)
2536 chandransh 1290
    lineitem = order.lineitems[0] 
4234 rajveer 1291
    order_text.textLine("Content : " + lineitem.brand + " " + str(lineitem.model_number) + " " + str(lineitem.color))
2536 chandransh 1292
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
1293
    order_text.textLine("Order ID : " + str(order.id))
1294
    pdf.drawText(order_text)
1295
    pdf.showPage()
1296
    pdf.save()
1297
    return filename
1298
 
2697 chandransh 1299
def get_return_orders(warehouse_id, from_date, to_date):
1300
    query = ReturnOrder.query.filter_by(processedStatus = False)
1301
    if warehouse_id != -1:
1302
        query = query.filter_by(warehouseId = warehouse_id)
1303
    if from_date:
4118 chandransh 1304
        query = query.filter(ReturnOrder.createdAt >from_date)
2697 chandransh 1305
    if to_date:
4118 chandransh 1306
        query = query.filter(ReturnOrder.createdAt < to_date)
2697 chandransh 1307
    return [return_order.to_thrift_object() for return_order in query.all()]
1308
 
2700 chandransh 1309
def get_return_order(id):
1310
    ret_order = ReturnOrder.get_by(orderId = id)
1311
    if ret_order is None:
1312
        raise TransactionServiceException(116, "No return order found for the given order id")
1313
    return ret_order.to_thrift_object()
1314
 
2697 chandransh 1315
def process_return(ret_order_id):
1316
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
1317
    if ret_order is None:
1318
        raise TransactionServiceException(116, "No return order found for the given order id")
1319
    ret_order.processedStatus = True
2701 chandransh 1320
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 1321
    session.commit()
1322
 
2819 chandransh 1323
def create_purchase_order(warehouseId):
1324
    if not warehouseId:
1325
        raise TransactionServiceException(101, "bad warehouse id")
1326
 
3451 chandransh 1327
    query = Order.query.with_lockmode("update").filter_by(warehouse_id=warehouseId)
4380 mandeep.dh 1328
    query = query.filter(or_(Order.status == OrderStatus.SUBMITTED_FOR_PROCESSING, Order.status == OrderStatus.INVENTORY_LOW))
2819 chandransh 1329
    query = query.filter_by(purchase_order_id=None)
1330
    query = query.order_by(Order.created_timestamp)
1331
    pending_orders = query.all()
1332
 
1333
    if not pending_orders:
1334
        return -1
1335
 
1336
    t_purchase_order = PurchaseOrder()
4365 mandeep.dh 1337
    t_purchase_order.supplierId = 3 # Putting supplier id as 3 for sarvottam for time being
2819 chandransh 1338
    t_purchase_order.warehouseId = warehouseId
1339
    t_purchase_order.lineitems = []
1340
 
1341
    lineitems = {}
1342
 
4293 rajveer 1343
    catalog_client = CatalogClient().get_client()
4292 rajveer 1344
 
2819 chandransh 1345
    for order in pending_orders:
1346
        for lineitem in order.lineitems:
1347
            item_id = lineitem.item_id
1348
            if lineitems.has_key(item_id):
1349
                lineitems[item_id].quantity = lineitems[item_id].quantity + lineitem.quantity
1350
            else:
1351
                t_po_lineitem = POLineItem()
1352
                t_po_lineitem.productGroup = lineitem.productGroup
1353
                t_po_lineitem.brand = lineitem.brand
1354
                t_po_lineitem.modelNumber = lineitem.model_number
1355
                t_po_lineitem.modelName = lineitem.model_name
1356
                t_po_lineitem.color = lineitem.color
1357
                t_po_lineitem.itemId = lineitem.item_id
1358
                t_po_lineitem.quantity = lineitem.quantity
1359
                lineitems[item_id] = t_po_lineitem
1360
                t_purchase_order.lineitems.append(t_po_lineitem)
4292 rajveer 1361
                #FIXME vendor is hardcoded for servottam
1362
                item_pricing = catalog_client.getItemPricing(item_id, 3)
1363
                t_po_lineitem.unitPrice = item_pricing.transferPrice
1364
 
1365
 
2819 chandransh 1366
    warehouse_client = WarehouseClient().get_client()
1367
    po_id = warehouse_client.createPurchaseOrder(t_purchase_order)
1368
 
1369
    for order in pending_orders:
1370
        order.purchase_order_id = po_id
1371
    session.commit()
1372
    return po_id
1373
 
3451 chandransh 1374
def update_weight(order_id, weight):
3469 chandransh 1375
    '''
1376
    Update the weight of order
1377
    '''
3451 chandransh 1378
    order = get_order(order_id)
1379
    order.total_weight = weight
3469 chandransh 1380
    lineitem = order.lineitems[0]
1381
    lineitem.total_weight = weight
1382
    lineitem.unit_weight = weight
3451 chandransh 1383
 
3469 chandransh 1384
    session.commit()
1385
    return order
1386
 
1387
def change_product(order_id, item_id):
1388
    '''
1389
    Ship a product of a different color to the customer.
1390
    '''
1391
    order = get_order(order_id)
4306 rajveer 1392
    if order.status not in [OrderStatus.INIT, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3469 chandransh 1393
        raise TransactionServiceException(120, "This order has already been processed. Please seek help from engineering.")
1394
 
1395
    lineitem = order.lineitems[0]
3451 chandransh 1396
 
3469 chandransh 1397
    catalog_client = CatalogClient().get_client()
1398
 
1399
    old_item = catalog_client.getItem(lineitem.item_id)
1400
    item = catalog_client.getItem(item_id)
1401
    if old_item.catalogItemId != item.catalogItemId:
1402
        raise TransactionServiceException(121, "You can't ship a different item. You can only ship the same item in a different color.")
1403
 
1404
    catalog_client.reserveItemInWarehouse(item_id, order.warehouse_id, lineitem.quantity)
1405
    catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity)
1406
    #TODO: Check that this new item has the same price
1407
 
1408
    lineitem.item_id = item_id
1409
    lineitem.color = item.color
1410
 
3451 chandransh 1411
    session.commit()
3469 chandransh 1412
 
1413
    order = get_order(order_id)
3451 chandransh 1414
    return order
3469 chandransh 1415
 
1416
def change_warehouse(order_id, warehouse_id):
1417
    '''
1418
    Update the warehouse which will be used to fulfil this order.
1419
    '''
1420
    order = get_order(order_id)
4306 rajveer 1421
    if order.status not in [OrderStatus.INIT, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3469 chandransh 1422
        raise TransactionServiceException(117, "This order has already been processed. Please seek help from engineering.")
1423
 
1424
    if warehouse_id == order.warehouse_id:
1425
        raise TransactionServiceException(118, "You have selected the current warehouse again. Nothing to do")
1426
 
1427
    lineitem = order.lineitems[0]
1428
    catalog_client = CatalogClient().get_client()
1429
    try:
1430
        warehouse = catalog_client.getWarehouse(warehouse_id)
1431
    except:
1432
        raise TransactionServiceException(119, "No warehouse with id" + str(warehouse_id))
1433
 
1434
    catalog_client.reserveItemInWarehouse(lineitem.item_id, warehouse_id, lineitem.quantity)
1435
    catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity)
3451 chandransh 1436
 
3469 chandransh 1437
    order.warehouse_id = warehouse_id
1438
    session.commit()
1439
    return order
3553 chandransh 1440
 
3986 chandransh 1441
def add_delay_reason(order_id, reason, further_delay=0):
3553 chandransh 1442
    '''
3994 chandransh 1443
    Adds a delay reason to the order and updates the expected delivery time.
3553 chandransh 1444
    '''
1445
    order = get_order(order_id)
1446
    try:
3581 chandransh 1447
        order.delay_reason = DelayReason._VALUES_TO_NAMES[reason]
4009 chandransh 1448
        actual_delivery_delay = adjust_delivery_time(order.expected_delivery_time, further_delay)
1449
        order.expected_delivery_time = order.expected_delivery_time + datetime.timedelta(days=actual_delivery_delay)
4102 chandransh 1450
 
1451
        if order.status < OrderStatus.SHIPPED_FROM_WH:
1452
            actual_shipping_delay = adjust_delivery_time(order.expected_shipping_time, further_delay)
1453
            order.expected_shipping_time = order.expected_shipping_time + datetime.timedelta(days=actual_shipping_delay)
1454
 
3553 chandransh 1455
        session.commit()
4008 mandeep.dh 1456
 
1457
        try:
1458
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
1459
            transaction_requiring_extra_processing.category = 'DELAYED_DELIVERY'
1460
            transaction_requiring_extra_processing.transaction_id = order.transaction_id
1461
            session.commit()
1462
        except Exception as e:
4065 mandeep.dh 1463
            print 'Could not persist transaction id: ' + str(order.transaction_id) + ' for further processing due to: ' + str(e)
4008 mandeep.dh 1464
 
3553 chandransh 1465
        return True
1466
    except:
3994 chandransh 1467
        print sys.exc_info()[0]
3553 chandransh 1468
        return False
3956 chandransh 1469
 
1470
def reconcile_cod_collection(collected_amount_map, xferBy, xferTxnId, xferDate):
1471
    unprocessed_awbs = {}
1472
    for awb, amount in collected_amount_map.iteritems():
1473
        try:
1474
            order = Order.query.filter_by(airwaybill_no=awb).one()
1475
        except NoResultFound:
1476
            unprocessed_awbs[awb] = "No order was found for the given AWB: " + awb
1477
            continue
1478
        except MultipleResultsFound:
1479
            unprocessed_awbs[awb] = "Multiple orders were found for the given AWB:" + awb
1480
            continue
1481
 
1482
        if order.cod_reconciliation_timestamp:
1483
            #This order has been processed already! This may be a re-run. Let's allow other orders to be processed.
1484
            continue
1485
 
1486
        if order.status < OrderStatus.DELIVERY_SUCCESS:
1487
            #Order has not been delivered yet. No way we can receive the payment.
1488
            unprocessed_awbs[awb] = "Payment has been received for order: " + str(order.id) + " before delivery reconciliation"
1489
            continue
1490
 
4252 rajveer 1491
        ##As per ticket #743 if amount difference less than 0.5 we should reconcile
1492
        if abs(amount - order.total_amount) > 0.5:
3956 chandransh 1493
            #Received amount is less than or more than the order amount. Mustn't let the user proceed.
1494
            unprocessed_awbs[awb] = "Payment of Rs. " + str(amount) + " has been received against the total value of Rs. " + str(order.total_amount) + " for order: " + str(order.id)
1495
            continue
1496
 
1497
        try:
1498
            payment_client = PaymentClient().get_client()
1499
            payment_client.partiallyCapturePayment(order.transaction.id, amount, xferBy, xferTxnId, xferDate)
1500
        except Exception:
1501
            unprocessed_awbs[awb] = "We were unable to partially capture payment for order id " + str(order.id) + ", AWB: " + awb
1502
            continue
1503
 
1504
        #Payment has been recorded now. We can update the order peacefully.
1505
        order.cod_reconciliation_timestamp = datetime.datetime.now()
1506
        session.commit()
3469 chandransh 1507
 
3956 chandransh 1508
    return unprocessed_awbs
4008 mandeep.dh 1509
 
1510
def get_transactions_requiring_extra_processing(category):
4065 mandeep.dh 1511
    """
1512
    Returns the list of transaction ids that require some extra processing and
1513
    which belong to a particular category. This is currently used by CRM
1514
    application. If no such transaction ids are present, it returns an empty list.
1515
    """
1516
    query = TransactionRequiringExtraProcessing.query
4008 mandeep.dh 1517
 
4065 mandeep.dh 1518
    if category is not None:
1519
        query = query.filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category))
4008 mandeep.dh 1520
 
4065 mandeep.dh 1521
    return [a.transaction_id for a in query.all()]
4008 mandeep.dh 1522
 
1523
def mark_transaction_as_processed(transactionId, category):
4065 mandeep.dh 1524
    """
1525
    Marks a particular transaction as processed for a particular cateogory.
1526
    It essentially deletes the transaction id record for a particular
1527
    processing type category (if present) from DB.
1528
    This is currently used by CRM application.
1529
    """
4008 mandeep.dh 1530
    TransactionRequiringExtraProcessing.query.filter_by(transaction_id = transactionId).filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category)).delete()
1531
    session.commit()
1532
 
4018 chandransh 1533
def get_item_wise_risky_orders_count():
1534
    """
1535
    Returns a map containing the number of risky orders keyed by item id. A risky order
1536
    is defined as one whose shipping date is about to expire.
1537
    """
1538
    item_wise_risky_orders_count = {}
4019 chandransh 1539
    shipping_cutoff_time = (datetime.datetime.now() + datetime.timedelta(days = 1)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4018 chandransh 1540
    orders = Order.query.filter(Order.status.in_(tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.ACCEPTED]))).filter(Order.expected_shipping_time <= shipping_cutoff_time).all()
1541
    for order in orders:
1542
        for lineitem in order.lineitems:
1543
            quantity = lineitem.quantity
1544
            if item_wise_risky_orders_count.has_key(lineitem.item_id):
1545
                quantity = quantity + item_wise_risky_orders_count[lineitem.item_id]
1546
 
1547
            item_wise_risky_orders_count[lineitem.item_id] = quantity
1548
    return item_wise_risky_orders_count
1549
 
4324 mandeep.dh 1550
def update_shipment_address(order_id, address_id):
1551
    """
1552
    Updates shipment address of an order. Delivery and shipping date estimates
1553
    etc. are also updated here.
1554
 
1555
    Throws TransactionServiceException in case address change is not
1556
    possible due to certain reasons such as new pincode in address is
1557
    not serviceable etc.
1558
 
1559
    Parameters:
1560
     - orderId
1561
     - addressId
1562
    """
1563
    user_client = UserClient().get_client()
1564
    address     = user_client.getAddressById(address_id)
1565
    order       = get_order(order_id)
1566
 
1567
    logistics_client = LogisticsClient().get_client()
1568
    logistics_info = logistics_client.getLogisticsEstimation(order.lineitems[0].item_id, address.pin)
1569
 
1570
    # Check for new estimate. Raise exception if new address is not serviceable
1571
    if logistics_info.deliveryTime == -1:
1572
        raise TransactionServiceException(1, 'Location not serviceable')
1573
 
1574
    # COD services are not available everywhere
1575
    if order.cod:
1576
        if not logistics_client.isCodAllowed(address.pin):
1577
            raise TransactionServiceException(2, 'COD service not available')
1578
 
1579
    current_time = datetime.datetime.now()
1580
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
1581
    logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
1582
 
1583
    order.customer_name         = address.name
1584
    order.customer_pincode      = address.pin
1585
    order.customer_address1     = address.line1
1586
    order.customer_address2     = address.line2
1587
    order.customer_city         = address.city
1588
    order.customer_state        = address.state
1589
    order.customer_mobilenumber = address.phone
1590
 
1591
    if order.cod:
1592
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
1593
    else:
1594
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
1595
 
1596
    order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
1597
    order.promised_shipping_time = order.expected_shipping_time
1598
    order.promised_delivery_time = order.expected_delivery_time 
1599
 
1600
    session.commit()
1601
 
4247 rajveer 1602
def mark_order_cancellation_request_received(orderId):
1603
    """
1604
    Mark order as cancellation request received. If customer sends request of cancellation of
1605
    a particular order, this method will be called. It will just change status of the order
1606
    depending on its current status. It also records the previous status, so that we can move
1607
    back to that status if cancellation request is denied.
1608
 
1609
    Parameters:
1610
     - orderId
1611
    """
1612
    status_transition = {OrderStatus.INIT : OrderStatus.CANCEL_REQUEST_RECEIVED,
1613
             OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCEL_REQUEST_RECEIVED,
1614
             OrderStatus.INVENTORY_LOW : OrderStatus.CANCEL_REQUEST_RECEIVED,
4306 rajveer 1615
             OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCEL_REQUEST_RECEIVED,
1616
             OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCEL_REQUEST_RECEIVED,
1617
             OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 1618
             OrderStatus.ACCEPTED : OrderStatus.CANCEL_REQUEST_RECEIVED,
1619
             OrderStatus.BILLED : OrderStatus.CANCEL_REQUEST_RECEIVED,
1620
             OrderStatus.PAYMENT_FLAGGED : OrderStatus.CANCEL_REQUEST_RECEIVED
1621
             }
1622
    if order.status not in status_transition.keys():
1623
        raise TransactionServiceException(114, "This order can't be considered for cancellation")
1624
 
1625
    order = get_order(orderId)
1626
    order.previousStatus = order.status
1627
    order.status = OrderStatus.CANCEL_REQUEST_RECEIVED
1628
    order.statusDescription = "Cancellation request received from user"
1629
    session.commit()
1630
 
4258 rajveer 1631
def mark_transaction_as_payment_flag_removed(transactionId):
4247 rajveer 1632
    """
4258 rajveer 1633
    If we and/or payment gateway has decided to accept the payment, this method needs to be called.
1634
    Changed transaction and all orders status to payment accepted.
4247 rajveer 1635
 
1636
    Parameters:
4258 rajveer 1637
     - transactionId
4247 rajveer 1638
    """
4258 rajveer 1639
    transaction = get_transaction(transactionId)
1640
    transaction.status = TransactionStatus.AUTHORIZED
1641
    for order in transaction.orders:
1642
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1643
        order.statusDescription = "Submitted to warehouse"
4247 rajveer 1644
    session.commit()
1645
 
4259 anupam.sin 1646
def refund_transaction(transactionId, refundedBy, reason):
1647
    """
1648
    This method is called when a flagged payment is deemed unserviceable and the corresponding orders
1649
    need to be cancelled
1650
 
1651
    Parameters:
1652
     - transactionId
1653
    """
1654
    transaction = get_transaction(transactionId)
1655
    transaction.status = TransactionStatus.FAILED
1656
    for order in transaction.orders:
1657
        refund_order(order.id, refundedBy, reason)
1658
    session.commit()
1659
 
4247 rajveer 1660
def mark_order_cancellation_request_denied(orderId):
1661
    """
4283 anupam.sin 1662
    If we decide to not to cancel order, we will move the order to previous status.
4247 rajveer 1663
 
1664
    Parameters:
1665
     - orderId
1666
    """
1667
    order = get_order(orderId)
1668
    order.status = order.previousStatus
1669
    order.previousStatus = None
1670
    order.statusDescription = "Cancellation request denied"
1671
    session.commit()
1672
 
1673
def mark_order_cancellation_request_confirmed(orderId):
1674
    """
1675
    If we decide to to cancel order, CRM will call this method to move the status of order to
1676
    cancellation request confirmed. After this OM will be able to cancel the order.
1677
 
1678
    Parameters:
1679
     - orderId
1680
    """
1681
    order = get_order(orderId)
1682
    order.status = OrderStatus.CANCEL_REQUEST_CONFIRMED
1683
    order.statusDescription = "Cancellation request confirmed"
1684
    session.commit()
1685
 
4285 rajveer 1686
def accept_orders_for_item_id(itemId, inventory):
1687
    """
1688
    Marks the orders as ACCEPTED for the given itemId and inventory. It also updates the accepted timestamp. If the
1689
    given order is not a COD order, it also captures the payment if the same has not been captured.
1690
 
1691
    Parameters:
1692
     - itemId
1693
     - inventory
1694
    """
4351 rajveer 1695
    orders = Order.query.filter(Order.status.in_(tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS]))).order_by(Order.expected_shipping_time).all()
4285 rajveer 1696
    for order in orders:
4301 rajveer 1697
        if inventory > 0:
1698
            lineitem = order.lineitems[0]
1699
            if itemId == lineitem.item_id:
1700
                try:
1701
                    accept_order(order.id)
1702
                    inventory = inventory - lineitem.quantity
1703
                except:
1704
                    logging.info("Unable to accept the order")
1705
        else:
1706
            order_outofstock(order.id)
4285 rajveer 1707
    return
1708
 
4369 rajveer 1709
def mark_orders_as_po_raised(vendorId, itemId, quantity, estimate, isReminder):
1710
    if isReminder:
1711
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
1712
    else:
1713
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
1714
 
1715
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 1716
    for order in orders:
1717
        lineitem = order.lineitems[0]
1718
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
1719
            if estimate > 0:
1720
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
1721
            order.status = OrderStatus.LOW_INV_PO_RAISED
4362 rajveer 1722
            order.statusDescription = "PO Raised"
4303 rajveer 1723
            quantity = quantity - lineitem.quantity
1724
            store_inventory_action(order, itemId, HotspotAction.PO_RAISED, estimate, lineitem.quantity)
1725
            session.commit()
1726
 
4369 rajveer 1727
def mark_orders_as_reversal_initiated(vendorId, itemId, quantity, estimate, isReminder):
1728
    if isReminder:
1729
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
1730
    else:
1731
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
1732
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 1733
    for order in orders:
1734
        lineitem = order.lineitems[0]
1735
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
1736
            if estimate > 0:
1737
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
1738
            order.status = OrderStatus.LOW_INV_REVERSAL_IN_PROCESS
4362 rajveer 1739
            order.statusDescription = "Reversal Initiated"
4303 rajveer 1740
            quantity = quantity - lineitem.quantity
1741
            store_inventory_action(order, itemId, HotspotAction.REVERSAL_INITIATED, estimate, lineitem.quantity)
1742
            session.commit()
1743
 
4369 rajveer 1744
def mark_orders_as_not_available(vendorId, itemId, quantity, estimate, isReminder):
1745
    if isReminder:
1746
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
1747
    else:
1748
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
1749
 
1750
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 1751
    for order in orders:
1752
        lineitem = order.lineitems[0]
1753
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
1754
            order.status = OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT
4362 rajveer 1755
            order.statusDescription = "Not Available"
4303 rajveer 1756
            quantity = quantity - lineitem.quantity
1757
            store_inventory_action(order, itemId, HotspotAction.NOT_AVAILABLE, estimate, lineitem.quantity)
1758
            session.commit()
1759
 
1760
def store_inventory_action(order, itemId, hotspotAction, estimate, quantity):
4369 rajveer 1761
    orderInv = OrderInventory.get_by(order_id=order.id)
1762
    if not orderInv:
1763
        orderInv = OrderInventory()
1764
        orderInv.order = order
4303 rajveer 1765
    orderInv.hotspotAction = hotspotAction  
1766
    orderInv.estimate = estimate
1767
    orderInv.itemId = itemId
1768
    orderInv.timestamp = datetime.datetime.now()
1769
    orderInv.quantity = quantity
1770
 
4369 rajveer 1771
 
1772
def mark_orders_as_timeout(vendorId):
1773
    ret_timeouts = {}
1774
    orderInvs = OrderInventory.query.all()
1775
    for orderInv in orderInvs:
1776
        if orderInv.timestamp +  timedelta(days=orderInv.estimate) < datetime.datetime.now():
1777
            if not ret_timeouts.has_key(orderInv.itemId):
1778
                timeout = TimeoutSummary()
1779
                ret_timeouts[orderInv.itemId] = timeout
1780
            else:
1781
                timeout = ret_timeouts.get(orderInv.itemId)
1782
            if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
1783
                if timeout.poRaised:
1784
                    timeout.poRaised += 1
1785
                else:
1786
                    timeout.poRaised = 1
1787
 
1788
                if timeout.poEstimate:
1789
                    timeout.poEstimate += orderInv.estimate
1790
                else:
1791
                    timeout.poEstimate = orderInv.estimate
1792
                orderInv.order.status = OrderStatus.LOW_INV_PO_RAISED_TIMEOUT
1793
                orderInv.order.statusDescription = "PO Raised Timeout"
1794
            elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
1795
                if timeout.reversalInitiated:
1796
                    timeout.reversalInitiated += 1
1797
                else:
1798
                    timeout.reversalInitiated = 1
1799
 
1800
                if timeout.reversalEstimate:
1801
                    timeout.reversalEstimate += orderInv.estimate
1802
                else:
1803
                    timeout.reversalEstimate = orderInv.estimate
1804
                orderInv.order.status = OrderStatus.LOW_INV_REVERSAL_TIMEOUT
1805
                orderInv.order.statusDescription = "Reversal Initiated Timeout"
1806
            else:
1807
                orderInv.delete()
1808
    session.commit()
1809
    return ret_timeouts
1810
 
4386 anupam.sin 1811
def get_order_for_awb(awb):
1812
    order = Order.get_by(airwaybill_no=awb)
1813
    if not order:
1814
        raise TransactionServiceException(108, "no such order")
1815
 
1816
    return order
4369 rajveer 1817
 
4386 anupam.sin 1818
 
766 rajveer 1819
def close_session():
1820
    if session.is_active:
1821
        print "session is active. closing it."
2783 chandransh 1822
        session.close()
3376 rajveer 1823
 
1824
def is_alive():
1825
    try:
1826
        session.query(Transaction.id).limit(1).one()
1827
        return True
1828
    except:
4343 varun.gupt 1829
        return False