Subversion Repositories SmartDukaan

Rev

Rev 5637 | Rev 5676 | 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, \
4435 mandeep.dh 20
    Order, BatchNoGenerator, InvoiceIDGenerator, TransactionRequiringExtraProcessing, \
5348 anupam.sin 21
    OrderInventory, Alert, PaymentSettlement, EBSSettlementSummary, \
5527 anupam.sin 22
    CodVerificationAgent, Attribute, RechargeVoucherTracker
23
 
2687 chandransh 24
from shop2020.model.v1.order.impl.model.ReturnOrder import ReturnOrder
4541 mandeep.dh 25
from shop2020.thriftpy.generic.ttypes import ExceptionType
5636 amar.kumar 26
from shop2020.thriftpy.alert.ttypes import MonitoredEntity, EntityType
5527 anupam.sin 27
from shop2020.thriftpy.logistics.ttypes import DeliveryType, PickUpType
4435 mandeep.dh 28
from shop2020.thriftpy.model.v1.catalog.ttypes import BillingType, \
5110 mandeep.dh 29
    InventoryServiceException, WarehouseType, ItemType, InventoryType
4435 mandeep.dh 30
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, \
31
    TransactionStatus, OrderStatus, DelayReason, ExtraTransactionProcessingType, \
5527 anupam.sin 32
    HotspotAction, TimeoutSummary, OrderStatusGroups, OrderType
4421 mandeep.dh 33
from shop2020.thriftpy.payments.ttypes import PaymentException
5110 mandeep.dh 34
from shop2020.thriftpy.warehouse.ttypes import ScanType, \
35
    WarehouseServiceException
3499 mandeep.dh 36
from shop2020.utils.EmailAttachmentSender import mail, get_attachment_part
855 rajveer 37
from shop2020.utils.Utils import to_py_date, to_java_date
4008 mandeep.dh 38
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
3499 mandeep.dh 39
from sqlalchemy.sql import func
5527 anupam.sin 40
from sqlalchemy.sql.expression import and_, or_, desc, not_, distinct, select
3499 mandeep.dh 41
from string import Template
42
from textwrap import dedent
43
import datetime
44
import logging
45
import os
4421 mandeep.dh 46
import sys
4435 mandeep.dh 47
import time
4421 mandeep.dh 48
import traceback
5508 rajveer 49
from shop2020.thriftpy.model.v1.user.ttypes import VoucherType
5636 amar.kumar 50
from shop2020.clients.AlertClient import AlertClient
3499 mandeep.dh 51
logging.basicConfig(level=logging.DEBUG)
104 ashish 52
 
3499 mandeep.dh 53
 
4763 rajveer 54
PREPAID_SHIPPING_CUTOFF_TIME = 15
4019 chandransh 55
COD_SHIPPING_CUTOFF_TIME = 12
3499 mandeep.dh 56
 
2819 chandransh 57
PAGE_HEIGHT=defaultPageSize[1]
58
PAGE_WIDTH=defaultPageSize[0]
59
 
4763 rajveer 60
billedOrdersColorMap = {}
61
 
3499 mandeep.dh 62
ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT = {
4873 mandeep.dh 63
        OrderStatus.RTO_RESHIPPED    :  3,
64
        OrderStatus.RTO_IN_TRANSIT   : -5,
65
        OrderStatus.DELIVERY_SUCCESS :  1,
66
        OrderStatus.DOA_CERT_INVALID : -5
3499 mandeep.dh 67
}
68
 
104 ashish 69
def get_new_transaction():
70
    transaction = Transaction()
71
    transaction.createdOn = datetime.datetime.now()
738 chandransh 72
    transaction.status = TransactionStatus.INIT
104 ashish 73
    transaction.status_message = "New transaction"
483 rajveer 74
    return transaction
75
 
76
def create_order(t_order):
77
    order = Order()
78
    if t_order.warehouse_id:
79
        order.warehouse_id = t_order.warehouse_id
509 rajveer 80
    if t_order.logistics_provider_id:    
483 rajveer 81
        order.logistics_provider_id = t_order.logistics_provider_id
82
        order.airwaybill_no = t_order.airwaybill_no
83
        order.tracking_id = t_order.tracking_id
4009 chandransh 84
    if t_order.expected_shipping_time:
4019 chandransh 85
        order.expected_shipping_time = to_py_date(t_order.expected_shipping_time).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 86
        order.promised_shipping_time = order.expected_shipping_time
4009 chandransh 87
    if t_order.expected_delivery_time:
483 rajveer 88
        order.expected_delivery_time = to_py_date(t_order.expected_delivery_time)
4102 chandransh 89
        order.promised_delivery_time = order.expected_delivery_time
483 rajveer 90
    if t_order.customer_id:    
91
        order.customer_id = t_order.customer_id
92
        order.customer_name = t_order.customer_name
860 rajveer 93
        order.customer_city = t_order.customer_city
94
        order.customer_state = t_order.customer_state
483 rajveer 95
        order.customer_mobilenumber = t_order.customer_mobilenumber
96
        order.customer_pincode = t_order.customer_pincode
738 chandransh 97
        order.customer_address1 = t_order.customer_address1
98
        order.customer_address2 = t_order.customer_address2
483 rajveer 99
        order.customer_email = t_order.customer_email
100
    #new status and status description to be added    
716 rajveer 101
    order.status = t_order.status  
483 rajveer 102
    order.statusDescription = t_order.statusDescription
103
    order.total_amount = t_order.total_amount
104
    order.total_weight = t_order.total_weight
105
    if t_order.created_timestamp:
106
        order.created_timestamp = to_py_date(t_order.created_timestamp)
107
    else:
685 chandransh 108
        order.created_timestamp = datetime.datetime.now()
5555 rajveer 109
    order.pickupStoreId = t_order.pickupStoreId
483 rajveer 110
    return order
111
 
112
def create_transaction(t_transaction):
113
    t_orders = t_transaction.orders
114
    if not t_orders:
115
        raise TransactionServiceException(101, "Orders missing from the transaction")
116
    transaction = get_new_transaction()
117
    transaction.customer_id = t_transaction.customer_id 
118
    transaction.shopping_cart_id = t_transaction.shoppingCartid
2219 varun.gupt 119
    transaction.coupon_code = t_transaction.coupon_code
2815 vikas 120
    transaction.session_source = t_transaction.sessionSource
121
    transaction.session_start_time = to_py_date(t_transaction.sessionStartTime)
3858 vikas 122
    transaction.first_source = t_transaction.firstSource
123
    transaction.first_source_start_time = to_py_date(t_transaction.firstSourceTime)
483 rajveer 124
 
125
    for t_order in t_orders:
126
        order = create_order(t_order)
127
        order.transaction = transaction 
128
        for line_item in t_order.lineitems:
129
            litem = LineItem()
716 rajveer 130
            litem.item_id = line_item.item_id
963 chandransh 131
            litem.productGroup = line_item.productGroup
483 rajveer 132
            litem.brand = line_item.brand
133
            if line_item.model_number:
134
                litem.model_number = line_item.model_number
135
            if line_item.model_name:    
136
                litem.model_name = line_item.model_name
908 chandransh 137
            if line_item.color:
138
                litem.color = line_item.color
483 rajveer 139
            if line_item.extra_info:
140
                litem.extra_info = line_item.extra_info
141
            litem.quantity = line_item.quantity
142
            litem.unit_price = line_item.unit_price
143
            litem.unit_weight = line_item.unit_weight
144
            litem.total_price = line_item.total_price
145
            litem.total_weight = line_item.total_weight
4283 anupam.sin 146
            '''litem.transfer_price = line_item.transfer_price'''
4172 rajveer 147
            litem.dealText = line_item.dealText
4295 varun.gupt 148
            litem.warranty_expiry_timestamp = to_py_date(line_item.warrantry_expiry_timestamp)
1976 varun.gupt 149
 
483 rajveer 150
            """
151
            if line_item.addedOn:
152
                litem.added_on = to_py_date(line_item.addedOn)
153
            else:
154
                litem.added_on = datetime.datetime.now()
155
            """
156
            litem.order = order
157
    session.commit()
158
    return transaction.id
159
 
160
def get_transaction(transaction_id):
161
    transaction = Transaction.get_by(id=transaction_id)
162
    if not transaction:
163
        raise TransactionServiceException(108, "no such transaction")
164
 
165
    return transaction
166
 
167
def get_transactions_for_customer(customer_id, from_date, to_date, status):
168
    if not customer_id:
169
        raise TransactionServiceException(101, "bad customer id")
170
    query = Transaction.query.filter(Transaction.customer_id == customer_id)
1493 vikas 171
    if status is not None:
483 rajveer 172
        query = query.filter(Transaction.status == status)
173
    if from_date:
174
        query = query.filter(Transaction.createdOn >from_date)
175
    if to_date:
176
        query = query.filter(Transaction.createdOn < to_date)
177
    return query.all()
178
 
179
def get_transactions_for_shopping_cart_id(shopping_cart_id):
180
    transactions = Transaction.query.filter_by(shopping_cart_id=shopping_cart_id).all()
181
    return transactions
182
 
183
def get_transaction_status(transaction_id):
184
    if not transaction_id:
185
        raise TransactionServiceException(101, "bad transaction id")
186
 
187
    transaction = get_transaction(transaction_id)
188
 
189
    return transaction.status
190
 
5527 anupam.sin 191
def change_transaction_status(transaction_id, new_status, description, pickUp, orderType):
483 rajveer 192
    transaction = get_transaction(transaction_id)
193
    transaction.status = new_status
194
    transaction.status_message = description
690 chandransh 195
    if new_status == TransactionStatus.FAILED:
196
        for order in transaction.orders:
197
            order.status = OrderStatus.PAYMENT_FAILED
2339 chandransh 198
            order.statusDescription = "Payment Failed"
4247 rajveer 199
    elif new_status == TransactionStatus.AUTHORIZED or new_status == TransactionStatus.FLAGGED:
690 chandransh 200
        for order in transaction.orders:
4247 rajveer 201
            if new_status == TransactionStatus.AUTHORIZED:
202
                order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
203
                order.statusDescription = "Submitted to warehouse"
204
            elif new_status == TransactionStatus.FLAGGED:
205
                order.status = OrderStatus.PAYMENT_FLAGGED
206
                order.statusDescription = "Payment flagged by gateway"
3092 chandransh 207
            order.cod = False
5527 anupam.sin 208
            order.orderType = orderType
743 rajveer 209
            #After we got payment success, we will set logistics info also 
210
            logistics_client = LogisticsClient().get_client()
211
            #FIXME line item is only one now. If multiple will come, need to fix.
871 chandransh 212
            item_id = order.lineitems[0].item_id
3044 chandransh 213
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.PREPAID)
743 rajveer 214
 
1730 ankur.sing 215
            current_time = datetime.datetime.now()
216
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4009 chandransh 217
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
5110 mandeep.dh 218
 
743 rajveer 219
            order.warehouse_id = logistics_info.warehouseId
5110 mandeep.dh 220
            order.fulfilmentWarehouseId = logistics_info.fulfilmentWarehouseId
743 rajveer 221
            order.logistics_provider_id = logistics_info.providerId
222
            order.airwaybill_no = logistics_info.airway_billno
223
            order.tracking_id = order.airwaybill_no
4019 chandransh 224
            order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 225
            order.promised_shipping_time = order.expected_shipping_time
5165 rajveer 226
            order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
3986 chandransh 227
            order.promised_delivery_time = order.expected_delivery_time 
871 chandransh 228
 
3133 rajveer 229
            catalog_client = CatalogClient().get_client()
5110 mandeep.dh 230
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.fulfilmentWarehouseId, order.lineitems[0].quantity)
1351 varun.gupt 231
 
4316 anupam.sin 232
            try:
233
                item_pricing = catalog_client.getItemPricing(item_id, -1)
234
                order.lineitems[0].transfer_price = item_pricing.transferPrice
235
            except:
236
                print "Not able to get transfer price. Skipping"
5387 rajveer 237
 
5527 anupam.sin 238
            if pickUp == PickUpType.SELF or pickUp == PickUpType.RUNNER:
239
                logisticsClient = LogisticsClient().get_client()
240
                order.logistics_provider_id = logisticsClient.getProviderForPickupType(pickUp)
241
                order.airwaybill_no = PickUpType._VALUES_TO_NAMES.get(pickUp)
5387 rajveer 242
                order.tracking_id = order.airwaybill_no
5508 rajveer 243
 
244
            voucherAmount = catalog_client.getVoucherAmount(item_id, VoucherType.SPICEDECK_MOBILE)
245
            if voucherAmount:
5514 rajveer 246
                __create_recharge_voucher_tracker(order, voucherAmount, VoucherType.SPICEDECK_MOBILE)
5508 rajveer 247
 
3064 chandransh 248
    elif new_status == TransactionStatus.COD_IN_PROCESS:
249
        for order in transaction.orders:
4662 rajveer 250
            order.status = OrderStatus.COD_VERIFICATION_PENDING
3064 chandransh 251
            order.statusDescription = "Verification Pending"
252
            order.cod = True
5527 anupam.sin 253
            order.orderType = orderType
3064 chandransh 254
            #After we got payment success, we will set logistics info also 
255
            logistics_client = LogisticsClient().get_client()
256
            #FIXME line item is only one now. If multiple will come, need to fix.
257
            item_id = order.lineitems[0].item_id
5555 rajveer 258
            if order.pickupStoreId:
259
                logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.PREPAID)
260
            else:
261
                logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.COD)
3064 chandransh 262
            current_time = datetime.datetime.now()
263
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4009 chandransh 264
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
3064 chandransh 265
 
266
            order.warehouse_id = logistics_info.warehouseId
5110 mandeep.dh 267
            order.fulfilmentWarehouseId = logistics_info.fulfilmentWarehouseId
3064 chandransh 268
            order.logistics_provider_id = logistics_info.providerId
269
            order.airwaybill_no = logistics_info.airway_billno
270
            order.tracking_id = order.airwaybill_no
4019 chandransh 271
            order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 272
            order.promised_shipping_time = order.expected_shipping_time
5165 rajveer 273
            order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
3986 chandransh 274
            order.promised_delivery_time = order.expected_delivery_time
3064 chandransh 275
 
3133 rajveer 276
            catalog_client = CatalogClient().get_client()
5110 mandeep.dh 277
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.fulfilmentWarehouseId, order.lineitems[0].quantity)
3064 chandransh 278
 
4316 anupam.sin 279
            try:
280
                item_pricing = catalog_client.getItemPricing(item_id, -1)
281
                order.lineitems[0].transfer_price = item_pricing.transferPrice        
282
            except:
283
                print "Not able to get transfer price. Skipping"
5508 rajveer 284
 
285
            voucherAmount = catalog_client.getVoucherAmount(item_id, VoucherType.SPICEDECK_MOBILE)
286
            if voucherAmount:
5514 rajveer 287
                __create_recharge_voucher_tracker(order, voucherAmount, VoucherType.SPICEDECK_MOBILE)
483 rajveer 288
    session.commit()
3499 mandeep.dh 289
 
3530 mandeep.dh 290
    try:
291
        if new_status == TransactionStatus.COD_IN_PROCESS:
4008 mandeep.dh 292
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
293
            transaction_requiring_extra_processing.category = 'COD_VERIFICATION'
294
            transaction_requiring_extra_processing.transaction_id = transaction_id
295
            session.commit()
4247 rajveer 296
        elif new_status == TransactionStatus.FLAGGED:
297
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
298
            transaction_requiring_extra_processing.category = 'PAYMENT_FLAGGED'
299
            transaction_requiring_extra_processing.transaction_id = transaction_id
300
            session.commit()
3530 mandeep.dh 301
    except Exception as e:
4065 mandeep.dh 302
        print "Error inserting transaction Id: " + str(transaction_id) + " due to " + str(e)
3499 mandeep.dh 303
 
483 rajveer 304
    return True
305
 
5514 rajveer 306
def __create_recharge_voucher_tracker(order, amount, voucherType):
5508 rajveer 307
    rvt = RechargeVoucherTracker()
308
    rvt.order = order
309
    rvt.amount = amount
310
    rvt.voucherIssued = False
5514 rajveer 311
    rvt.voucherType = voucherType
5508 rajveer 312
 
3994 chandransh 313
def __get_holidays(start_time=0L, to_time=-1L):
314
    '''
315
    Get the list of all public holidays since start time including the
316
    day of start time if it's a holiday
317
    '''
318
    midnightTime = start_time.replace(hour=0, minute=0, second=0, microsecond=0)
1730 ankur.sing 319
    fromDate = to_java_date(midnightTime)
320
    logistics_client = LogisticsClient().get_client()
3994 chandransh 321
    #TODO: This list should be cached after the first call.
322
    #Calling logistics server is also unnecessary.
323
    holidays = logistics_client.getHolidays(fromDate, to_time)
324
    holidays = [to_py_date(holiday).date() for holiday in holidays]
325
    return holidays
326
 
327
def adjust_delivery_time(start_time, delivery_days):
328
    '''
329
    Returns the actual no. of days which will pass while 'delivery_days'
330
    no. of business days will pass since 'order_time'. 
331
    '''
332
    start_date = start_time.date()
333
    end_date = start_date + datetime.timedelta(days = delivery_days)
334
    holidays = __get_holidays(start_time)
1730 ankur.sing 335
 
3994 chandransh 336
    while start_date <= end_date:
337
        if start_date.weekday() == 6 or start_date in holidays:
1730 ankur.sing 338
            delivery_days = delivery_days + 1
3994 chandransh 339
            end_date = end_date + datetime.timedelta(days = 1)
4088 chandransh 340
        start_date = start_date + datetime.timedelta(days = 1)
3994 chandransh 341
 
1730 ankur.sing 342
    return delivery_days
343
 
1398 varun.gupt 344
def enqueue_transaction_info_email(transaction_id):
1262 varun.gupt 345
    transaction = get_transaction(transaction_id)
346
 
347
    html_header = """
348
<html>
349
<body>
350
<div>
351
    <p>
352
        Hello,<br /><br />
1742 rajveer 353
        Thanks for placing order with us. Following are the details of your order:
1262 varun.gupt 354
    </p>
355
    <div>
356
        Order Date: $order_date
1569 varun.gupt 357
    </div>
1262 varun.gupt 358
    <div>
359
        <table>
1569 varun.gupt 360
        <tr><td colspan="5"><hr /></td></tr>
361
        <tr><td colspan="5" align="left"><b>Order Details</b></td></tr>
362
        <tr><td colspan="5"><hr /></td></tr>
1262 varun.gupt 363
        <tr>
2050 varun.gupt 364
            <th width="100">Order No.</th>
365
            <th>Product</th>
366
            <th width="100">Quantity</th>
367
            <th width="100">Unit Price</th>
368
            <th width="100">Amount</th>
1262 varun.gupt 369
        </tr>
370
    """
1398 varun.gupt 371
    user_email = ""
1262 varun.gupt 372
    total_amount = 0.0
373
    html_table = ""
1569 varun.gupt 374
    order_date = datetime.datetime.now()
1262 varun.gupt 375
 
376
    for order in transaction.orders:
377
        order_date = order.created_timestamp
1398 varun.gupt 378
        user_email = order.customer_email
1569 varun.gupt 379
        html_tr = "<tr><td align='center'>" + str(order.id) + "</td>"
1262 varun.gupt 380
 
381
        for lineitem in order.lineitems:
2050 varun.gupt 382
            lineitem_total_price = round(lineitem.total_price, 2)
383
 
1276 chandransh 384
            html_tr += "<td>" + str(lineitem) + "</td>"
2050 varun.gupt 385
            html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"
386
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"
387
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"
388
            total_amount += lineitem_total_price
1262 varun.gupt 389
            html_table += html_tr
2050 varun.gupt 390
 
1262 varun.gupt 391
    html_footer = """
392
        <tr><td colspan=5>&nbsp;</td></tr>
1565 varun.gupt 393
        <tr><td colspan=5><hr /></td></tr>
1262 varun.gupt 394
        <tr>
395
            <td colspan=4>Total Amount</td>
2050 varun.gupt 396
            <td> Rs. $total_amount</td>
1262 varun.gupt 397
        </tr>
398
        </table>
1569 varun.gupt 399
    </div>
1262 varun.gupt 400
    <p>
401
        Best Wishes,<br />
402
        Saholic Team
403
    </p>
404
</div>
405
</body>
406
</html>
407
    """
1398 varun.gupt 408
 
1569 varun.gupt 409
    dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")
1565 varun.gupt 410
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
411
 
1262 varun.gupt 412
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date))
2050 varun.gupt 413
    email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount))
1262 varun.gupt 414
 
1351 varun.gupt 415
    try:
416
        helper_client = HelperClient().get_client()
1398 varun.gupt 417
        helper_client.saveUserEmailForSending(user_email, "", "Saholic - Order Details", email_header + html_table + email_footer, str(transaction_id), "TransactionInfo")
1351 varun.gupt 418
        return True
419
    except Exception as e:
420
        print e
421
        return False
1262 varun.gupt 422
 
483 rajveer 423
def get_order(order_id):
424
    order = Order.get_by(id=order_id)
425
    if not order:
426
        raise TransactionServiceException(108, "no such order")
427
 
428
    return order
429
 
4999 phani.kuma 430
def get_order_list(order_ids):
431
    orders = Order.query.filter(Order.id.in_(tuple(order_ids)))
432
    return orders
433
 
5386 phani.kuma 434
def get_order_list_for_vendor(order_ids, vendor_id):
435
    if vendor_id == -1:
436
        return get_order_list(order_ids)
437
    else:
438
        orders = Order.query.filter_by(vendorId = vendor_id).filter(Order.id.in_(tuple(order_ids)))
439
        return orders
440
 
3014 chandransh 441
def get_orders_for_customer(customer_id, from_date, to_date, statuses):
483 rajveer 442
    if not customer_id:
443
        raise TransactionServiceException(101, "bad customer id")
444
    query = Order.query.filter(Order.customer_id == customer_id)
3014 chandransh 445
    if statuses:
446
        query = query.filter(Order.status.in_(tuple(statuses)))
483 rajveer 447
    if from_date:
448
        query = query.filter(Order.created_timestamp >from_date)
449
    if to_date:
450
        query = query.filter(Order.created_timestamp < to_date)
451
    return query.all()
452
 
1528 ankur.sing 453
def get_order_for_customer(order_id, customer_id):
454
    if not customer_id:
455
        raise TransactionServiceException(101, "bad customer id")
456
    order = get_order(order_id)
457
    if order.customer_id != customer_id:
458
        raise TransactionServiceException(108, "order: " + str(order_id) + " does not belong to customer: " + str(customer_id))
459
    return order
460
 
4801 anupam.sin 461
def get_all_orders(statuses, from_date, to_date, warehouse_id):
462
    if not len(statuses):
463
        raise TransactionServiceException(101, "Status list is empty")
464
    query = Order.query.filter(Order.status.in_(statuses))
465
    if warehouse_id:
466
        query = query.filter(Order.warehouse_id == warehouse_id)
467
        #raise TransactionServiceException(101, "bad warehouse id")
483 rajveer 468
    if from_date:
469
        query = query.filter(Order.created_timestamp >from_date)
470
    if to_date:
471
        query = query.filter(Order.created_timestamp < to_date)
472
    return query.all()
473
 
4133 chandransh 474
def get_orders_in_batch(statuses=[], offset=0, limit=0, warehouse_id=None):
4296 rajveer 475
    query = Order.query
476
    if warehouse_id:
477
        query = query.filter(Order.warehouse_id == warehouse_id)
4133 chandransh 478
    if statuses:
479
        query = query.filter(Order.status.in_(statuses))
480
    query = query.offset(offset)
481
    if limit:
482
        query = query.limit(limit)
483
    return query.all()
484
 
485
def get_order_count(statuses=[], warehouse_id=None):
486
    if not warehouse_id:
487
        raise TransactionServiceException(101, "bad warehouse id")
488
    query = session.query(func.count(Order.id)).filter(Order.warehouse_id == warehouse_id)
489
    if statuses:
490
        query = query.filter(Order.status.in_(statuses))
491
    return query.scalar()
492
 
1382 varun.gupt 493
def get_returnable_orders_for_customer(customer_id, limit = None):
494
    if not customer_id:
495
        raise TransactionServiceException(101, "bad customer id")
496
 
497
    query = Order.query.filter(Order.customer_id == customer_id)
498
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
499
    query = query.filter(Order.status != OrderStatus.REJECTED)
500
    query = query.filter(Order.status > OrderStatus.SHIPPED_FROM_WH)
501
    query = query.filter(or_(Order.status < OrderStatus.DELIVERY_SUCCESS, Order.delivery_timestamp < datetime.datetime.now() + datetime.timedelta(hours = 48)))
502
    orders = query.all()
503
    order_ids = [order.id for order in orders]
504
    return order_ids
505
 
506
def get_cancellable_orders_for_customer(customer_id, limit = None):
507
    if not customer_id:
508
        raise TransactionServiceException(101, "bad customer id")
4815 phani.kuma 509
    cancellableOrderStatuses = OrderStatusGroups().codCancellable
1382 varun.gupt 510
    query = Order.query.filter(Order.customer_id == customer_id)
4815 phani.kuma 511
    query = query.filter(Order.status.in_(cancellableOrderStatuses))
1382 varun.gupt 512
    orders = query.all()
513
    return [order.id for order in orders]
514
 
995 varun.gupt 515
def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):
516
    if not warehouse_id:
517
        raise TransactionServiceException(101, "bad warehouse id")
518
 
519
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
520
 
521
    if status:
522
        query = query.filter(Order.status == status)
523
 
524
    if start_billing_date:
525
        query = query.filter(Order.billing_timestamp >= start_billing_date)
526
 
527
    if end_billing_date:
528
        query = query.filter(Order.billing_timestamp <= end_billing_date)
529
 
530
    return query.all()
531
 
3451 chandransh 532
def get_orders_by_shipping_date(from_shipping_date, to_shipping_date, provider_id, warehouse_id, cod):
533
    query = Order.query.filter(Order.cod == cod)
3427 chandransh 534
 
535
    if warehouse_id and warehouse_id != -1:
536
        query = query.filter(Order.warehouse_id == warehouse_id)
537
 
538
    if provider_id and provider_id != -1:
539
        query = query.filter(Order.logistics_provider_id == provider_id)
540
 
541
    if from_shipping_date:
542
        query = query.filter(Order.shipping_timestamp >= from_shipping_date)
543
 
544
    if to_shipping_date:
545
        query = query.filter(Order.shipping_timestamp <= to_shipping_date)
546
 
547
    query = query.order_by(Order.airwaybill_no)
548
 
549
    return query.all()
550
 
1528 ankur.sing 551
def get_orders_for_transaction(transaction_id, customer_id):
552
    orders = Order.query.filter_by(transaction_id=transaction_id, customer_id=customer_id).all()
553
 
1208 chandransh 554
    if not orders:
555
        raise TransactionServiceException(101, "No order for the transaction")
556
    return orders
557
 
1405 ankur.sing 558
def get_undelivered_orders(provider_id, warehouse_id):
559
    query = Order.query
560
    if provider_id != -1:
561
        query = query.filter_by(Order.logistics_provider_id == provider_id)
562
    if warehouse_id != -1:
563
        query = query.filter(Order.warehouse_id == warehouse_id)
564
    query = query.filter(and_(Order.status != OrderStatus.DELIVERY_SUCCESS, Order.status != OrderStatus.FAILED, \
565
                              Order.status > OrderStatus.SHIPPED_FROM_WH))
1479 ankur.sing 566
    #Get last midnight time instead of current time as courier company would have sent the 
567
    #delivery records updated at least till midnight and not by the current time.
568
    time_format = "%Y-%m-%d %H:%M:%S.%f"
569
    t = time.strptime(str(datetime.datetime.now()), time_format)
570
    midnightTime = datetime.datetime(*t[:3])
571
    query = query.filter(Order.expected_delivery_time < midnightTime)
1405 ankur.sing 572
    orders = query.all()
573
    return orders
574
 
1208 chandransh 575
def get_line_items_for_order(order_id):
576
    query = LineItem.query.filter(LineItem.order_id == order_id)
577
    return query.all()
578
 
483 rajveer 579
def change_order_status(self, orderId, status, description):
580
    order = get_order(orderId)
581
    order.status = status
582
    order.statusDescription = description
583
    session.commit()
3578 mandeep.dh 584
    update_trust_level(order)
585
    return True
3499 mandeep.dh 586
 
3578 mandeep.dh 587
def update_trust_level(order):
3530 mandeep.dh 588
    try:
3578 mandeep.dh 589
        trust_level_delta = 0
590
        if order.cod == True:
591
            trust_level_delta = ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT.get(order.status, 0)
592
 
3530 mandeep.dh 593
        if (trust_level_delta != 0):
594
            user_client = UserClient().get_client()
595
            user_client.increaseTrustLevel(order.customer_id, trust_level_delta)
596
    except Exception as e:
597
        print e
3499 mandeep.dh 598
 
483 rajveer 599
    return True
3064 chandransh 600
 
601
def verify_order(self, orderId):
602
    logging.info("Verifying order no: " + str(orderId))
603
    order = get_order(orderId)
4662 rajveer 604
    if order.status == OrderStatus.COD_VERIFICATION_PENDING:
3064 chandransh 605
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
606
        order.statusDescription = "Submitted for processing"
607
        order.verification_timestamp = datetime.datetime.now()
608
        session.commit()
609
        logging.info("Successfully verified order no: " + str(orderId))
610
        return True
611
    else:
612
        logging.warning("Verify called for order no." + str(orderId) +" which is not in verification pending state");
613
        return False
614
 
4285 rajveer 615
def accept_order(orderId):
3064 chandransh 616
    logging.info("Accepting order no: " + str(orderId))
921 rajveer 617
    order = get_order(orderId)
5110 mandeep.dh 618
    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, OrderStatus.CAPTURE_IN_PROCESS]:
3064 chandransh 619
        if not order.cod:
620
            if order.transaction.status == TransactionStatus.AUTHORIZED:
4421 mandeep.dh 621
                __capture_txn(order)
3010 chandransh 622
        order.status = OrderStatus.ACCEPTED
623
        order.statusDescription = "Order Accepted"
624
        order.accepted_timestamp = datetime.datetime.now()
5530 mandeep.dh 625
        __amend_fulfilment_warehouse(order)
3010 chandransh 626
        session.commit()
3064 chandransh 627
        logging.info("Successfully accepted the order no.:" + str(orderId))
3010 chandransh 628
        return True
629
    else:
3064 chandransh 630
        logging.warning("Accept called for the unacceptable order: " + str(orderId))
3010 chandransh 631
        return False
921 rajveer 632
 
4421 mandeep.dh 633
def __capture_txn(order):
634
    txnId = order.transaction_id
3010 chandransh 635
    logging.info("Capturing payment for merchant txn:" + str(txnId))
4421 mandeep.dh 636
    try:
637
        payment_client = PaymentClient().get_client()
638
        capture_result = payment_client.capturePayment(txnId)
639
        if capture_result:
640
            logging.info("Successfully captured payment for merchant txn:" + str(txnId))
5527 anupam.sin 641
            change_transaction_status(txnId, TransactionStatus.IN_PROCESS, "Payment received", PickUpType.COURIER, order.orderType)
4421 mandeep.dh 642
        else:
643
            raise TransactionServiceException(115, "Payment capture failed.")
644
    except PaymentException as e:
645
        if e.error_code == 106:
646
            order.status = OrderStatus.CAPTURE_IN_PROCESS
647
            session.commit()
648
            raise TransactionServiceException(122, "Unable to capture payment due to connection issue.")
649
        else:
650
            raise TransactionServiceException(115, "Payment capture failed.")
3010 chandransh 651
 
5530 mandeep.dh 652
def __amend_fulfilment_warehouse(order):
653
    itemId = order.lineitems[0].item_id
654
    catalogClient = CatalogClient().get_client()
655
    inventory = catalogClient.getItemInventoryByItemId(itemId)
656
    if not (inventory.availability.has_key(order.fulfilmentWarehouseId) and inventory.availability[order.fulfilmentWarehouseId]):
657
        for warehouse in catalogClient.getWarehouses(WarehouseType.OURS, InventoryType.GOOD, 0, order.warehouse_id, 0):
5558 mandeep.dh 658
            if inventory.availability.has_key(warehouse.id) and inventory.availability[warehouse.id] >= inventory.reserved[warehouse.id] + order.lineitems[0].quantity:
5530 mandeep.dh 659
                catalogClient.reduceReservationCount(itemId, order.fulfilmentWarehouseId, order.lineitems[0].quantity)
660
                catalogClient.reserveItemInWarehouse(itemId, warehouse.id, order.lineitems[0].quantity)
5637 mandeep.dh 661
                order.fulfilmentWarehouseId = warehouse.id
5530 mandeep.dh 662
                break
663
 
5411 rajveer 664
def add_billing_details(orderId, invoice_number, serialNumbers, itemNumbers, billedBy, jacketNumber, billingType, fulfilmentWarehouseId, authorize):
4285 rajveer 665
    if jacketNumber is None or jacketNumber <= 0:
2783 chandransh 666
        raise TransactionServiceException(110, "Invalid jacket number")
667
 
4285 rajveer 668
    if billedBy is None or billedBy.strip() == "":
2783 chandransh 669
        raise TransactionServiceException(110, "Invalid Biller")
670
 
1149 chandransh 671
    order = Order.get_by(id=orderId)
672
    if not order:
2783 chandransh 673
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
5110 mandeep.dh 674
 
675
    lineitem = order.lineitems[0]
676
    item_id = lineitem.item_id
677
    catalog_client = CatalogClient().get_client()
678
    item = catalog_client.getItem(item_id)
4283 anupam.sin 679
    if order.status == OrderStatus.ACCEPTED:
4285 rajveer 680
        order.jacket_number = jacketNumber
681
        if billingType == BillingType.OURS:
5411 rajveer 682
            if itemNumbers:
683
                lineitem.item_number = itemNumbers[0]    
4283 anupam.sin 684
 
5411 rajveer 685
            if ItemType.SERIALIZED == item.type and not (serialNumbers and serialNumbers[0]):
686
                raise TransactionServiceException(110, "No Serial Number supplied")
687
            if serialNumbers:
688
                lineitem.serial_number = serialNumbers[0]
689
 
5527 anupam.sin 690
            order.invoice_number = get_next_invoice_number(order.orderType)
4283 anupam.sin 691
        else:
692
            order.invoice_number = invoice_number
4763 rajveer 693
            # In case of hotspot billing, we should try to verify that color billed in ETP is same as color in order.
694
            if billedOrdersColorMap.has_key(orderId):
695
                etpColor = billedOrdersColorMap.get(orderId)
696
                ourColor = order.lineitems[0].color
4781 rajveer 697
                if ourColor and etpColor != ourColor and not authorize:
4763 rajveer 698
                    raise TransactionServiceException(777, "ETP color: " + etpColor + " and Order color: " + ourColor)
699
                else:
700
                    billedOrdersColorMap.pop(orderId)
4283 anupam.sin 701
 
2842 chandransh 702
        order.status = OrderStatus.BILLED
703
        order.statusDescription = "Order Billed"
704
        order.billing_timestamp = datetime.datetime.now()
4285 rajveer 705
        order.billed_by = billedBy
4435 mandeep.dh 706
 
5436 mandeep.dh 707
        # Letting the billing process fail in cases where we are unable to 
4435 mandeep.dh 708
        # fill in transfer price
709
        try:
710
            catalog_client = CatalogClient().get_client()
5110 mandeep.dh 711
            warehouse = catalog_client.getWarehouse(fulfilmentWarehouseId)
712
            item_pricing = catalog_client.getItemPricing(item_id, warehouse.vendor.id)
713
            lineitem.transfer_price = item_pricing.transferPrice
714
            order.vendorId = warehouse.vendor.id
4435 mandeep.dh 715
        except InventoryServiceException as e:
716
            print sys.exc_info()[0]
717
            print e.message
5110 mandeep.dh 718
            raise TransactionServiceException(110, 'Transfer price missing for itemId: ' + str(item_id) + ' and vendor: ' + str(warehouse.vendor.id))
4435 mandeep.dh 719
 
5110 mandeep.dh 720
        # For OUR warehouse, we need to scan out items for every billed order
721
        if billingType == BillingType.OURS:
5530 mandeep.dh 722
            for index, serialNumber in enumerate(serialNumbers):
5411 rajveer 723
                try:
724
                    warehouse_client = WarehouseClient().get_client()
5436 mandeep.dh 725
                    # Fetching GOOD w/h corresponding to the virtual one here
726
                    if warehouse.billingWarehouseId is None:
727
                        warehouse = catalog_client.getWarehouses(None, InventoryType.GOOD, warehouse.vendor.id, order.warehouse_id, 0)[0]
728
 
5411 rajveer 729
                    if ItemType.SERIALIZED == item.type:
730
                        inventoryItem = warehouse_client.getInventoryItem(serialNumber)
731
                    else:
5661 mandeep.dh 732
                        inventoryItem = warehouse_client.getNonSeralizedInventoryItem(itemNumbers[index], item_id, warehouse.id)
5411 rajveer 733
 
734
                    if (inventoryItem.itemId != item_id):
735
                        catalog_client = CatalogClient().get_client()
736
                        item = catalog_client.getItem(inventoryItem.itemId)
737
                        scanItemString = " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
738
                        lineItemString = " ".join([str(lineitem.brand), str(lineitem.model_name), str(lineitem.model_number), str(lineitem.color)])
739
                        raise TransactionServiceException(110, 'Trying to scan ' + scanItemString + ' instead of ' + lineItemString)
740
 
741
                    if ItemType.SERIALIZED == item.type:
5661 mandeep.dh 742
                        inventoryItem = warehouse_client.scanSerializedItemForOrder(serialNumber, ScanType.SALE, orderId, warehouse.id, 1, order.warehouse_id)
5411 rajveer 743
                    else:
5661 mandeep.dh 744
                        inventoryItem = warehouse_client.scanForOrder(inventoryItem, ScanType.SALE, 1, order.id, warehouse.id, order.warehouse_id)
5411 rajveer 745
 
746
                    lineitem.transfer_price = inventoryItem.unitPrice
747
                    order.vendorId = inventoryItem.supplierId
5636 amar.kumar 748
                    catalog_client = CatalogClient().get_client()
5411 rajveer 749
                except WarehouseServiceException as e:
750
                    print sys.exc_info()[0]
751
                    print 'Could not scan out orders due to: ' + e.message
752
                    raise TransactionServiceException(110, e.message)
5123 mandeep.dh 753
        else:
754
            if not warehouse.isAvailabilityMonitored:
755
                catalog_client = CatalogClient().get_client()
756
                catalog_client.addInventory(item.id, warehouse.id, -1 * lineitem.quantity)
4365 mandeep.dh 757
 
5110 mandeep.dh 758
        __update_inventory_reservation(order)
5661 mandeep.dh 759
        order.fulfilmentWarehouseId = warehouse.id
4541 mandeep.dh 760
        session.commit()
4283 anupam.sin 761
        return True
762
    else:
763
        return False
1149 chandransh 764
 
4763 rajveer 765
def add_invoice_number(orderId, invoiceNumber, color):
4579 rajveer 766
    order = Order.get_by(id=orderId)
767
    if not order:
768
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
769
 
770
    if order.status == OrderStatus.ACCEPTED:
771
        order.invoice_number = invoiceNumber
4767 rajveer 772
        if color:
773
            billedOrdersColorMap[orderId] = color;
4579 rajveer 774
    session.commit()
775
 
1220 chandransh 776
def batch_orders(warehouseId):
777
    if not warehouseId:
778
        raise TransactionServiceException(101, "bad warehouse id")
1225 chandransh 779
 
780
    batchno_generator = BatchNoGenerator()
781
    session.commit()
1220 chandransh 782
    query = Order.query.filter_by(warehouse_id=warehouseId)
4592 mandeep.dh 783
    query = query.filter(Order.status == OrderStatus.LOW_INV_PO_RAISED)
1220 chandransh 784
    query = query.order_by(Order.created_timestamp)
785
    pending_orders = query.all()
1225 chandransh 786
 
1220 chandransh 787
    serial_no = 1
788
    for order in pending_orders:
1276 chandransh 789
        order.batchNo = batchno_generator.id
1220 chandransh 790
        order.serialNo = serial_no
791
        serial_no += 1
792
    session.commit() 
793
    pending_orders = query.all()
794
    return pending_orders
795
 
796
def order_outofstock(orderId):
1911 chandransh 797
    '''
798
    Mark order as out of stock
799
    '''
1220 chandransh 800
    order = get_order(orderId)
801
    order.status = OrderStatus.INVENTORY_LOW
802
    order.statusDescription = "Low Inventory"
803
    order.outofstock_timestamp = datetime.datetime.now()
804
    session.commit()
805
    return True
806
 
4789 rajveer 807
def mark_orders_as_shipped_from_warehouse(warehouseId, providerId, cod, orderIds):
4410 rajveer 808
    try:
809
        current_timestamp = datetime.datetime.now()
4789 rajveer 810
        orders = Order.query.filter_by(warehouse_id = warehouseId, logistics_provider_id = providerId, status = OrderStatus.BILLED, cod = cod).all()
4410 rajveer 811
        for order in orders:
4789 rajveer 812
            if order.id in orderIds:
813
                order.status = OrderStatus.SHIPPED_FROM_WH
814
                order.statusDescription = "Order shipped from warehouse"
815
                order.shipping_timestamp = current_timestamp
5636 amar.kumar 816
                try:
817
                    print "Trying to schedule alert"
818
                    monitoredEntity = MonitoredEntity();
819
                    monitoredEntity.entityType=EntityType.COURIER;
820
                    monitoredEntity.eventType=OrderStatus.SHIPPED_FROM_WH;
821
                    monitoredEntity.entityIdentifier="orderId = " + str(order.id);
822
                    seconds_epoch = time.time()
823
                    #Warn alert time is taken as 15 hrs
824
                    warn_time = (seconds_epoch+15*3600)*1000
825
                    #Critical alert time is taken as 25 hrs                    
826
                    critical_time = (seconds_epoch+25*3600)*1000
827
                    monitoredEntity.warnExpiryTime = warn_time
828
                    monitoredEntity.criticalExpiryTime = critical_time
829
                    monitoredEntity.description="warehouseId = " + str(warehouseId) + " providerId = " + str(providerId) + " orderId = "  + str(order.id);
830
                    print monitoredEntity
831
                    print monitoredEntity.description
832
                    print monitoredEntity.warnExpiryTime
833
                    print monitoredEntity.entityIdentifier
834
                    alert_client = AlertClient().get_client()
835
                    alert_client.scheduleAlert(monitoredEntity)
836
                except Exception as e:
837
                    print e
759 chandransh 838
        session.commit()
4749 varun.gupt 839
 
840
        try:
841
            enqueue_shipping_confirmation_email(orders)
842
        except Exception as e:
843
            print e
844
 
759 chandransh 845
        return True
846
    except:
847
        return False
4410 rajveer 848
 
1113 chandransh 849
def mark_orders_as_picked_up(provider_id, pickup_details):
850
    for awb, pickup_timestamp in pickup_details.iteritems():
1135 chandransh 851
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 852
        if order == None or order.status != OrderStatus.SHIPPED_FROM_WH:
2220 chandransh 853
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
854
            continue
1113 chandransh 855
        order.status = OrderStatus.SHIPPED_TO_LOGST
856
        order.statusDescription = "Order picked up by Courier Company"
1246 chandransh 857
        order.pickup_timestamp = pickup_timestamp
5636 amar.kumar 858
 
859
        try:
860
            monitoredEntity = MonitoredEntity();
861
            monitoredEntity.entityType=EntityType.COURIER;
862
            monitoredEntity.eventType=OrderStatus.SHIPPED_TO_LOGST
863
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
864
            seconds_epoch = time.time()
865
            #Warn alert time is taken as 15 hrs
866
            warn_time = (seconds_epoch+15*3600)*1000
867
            #Critical alert time is taken as 25 hrs                    
868
            critical_time = (seconds_epoch+25*3600)*1000
869
            monitoredEntity.warnExpiryTime = warn_time
870
            monitoredEntity.criticalExpiryTime = critical_time
871
            monitoredEntity.description="providerId = " + str(provider_id) + "   " + pickup_details
872
            alert_client = AlertClient().get_client()
873
            alert_client.updateMonitoredObject(monitoredEntity)
874
        except Exception as e:
875
            print e
1113 chandransh 876
    session.commit()
1217 chandransh 877
 
4910 phani.kuma 878
def get_orders_not_picked_up(provider_id):
1132 chandransh 879
    current_time = datetime.datetime.now()
880
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4741 phani.kuma 881
    orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.SHIPPED_FROM_WH).filter(Order.shipping_timestamp <= to_datetime).all()
1113 chandransh 882
    return orders_not_picked_up
883
 
1132 chandransh 884
def mark_orders_as_delivered(provider_id, delivered_orders):
885
    for awb, detail in delivered_orders.iteritems():
1135 chandransh 886
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
4910 phani.kuma 887
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
1911 chandransh 888
            continue
889
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
5555 rajveer 890
        if order.pickupStoreId:
891
            order.status = OrderStatus.DELIVERED_AT_STORE
892
            order.statusDescription = "Order delivered At Store"
893
        else:
894
            order.status = OrderStatus.DELIVERY_SUCCESS
895
            order.statusDescription = "Order delivered"
4910 phani.kuma 896
        timestamp, receiver = detail.split('|')
897
        if order.first_dlvyatmp_timestamp is None:
898
            order.first_dlvyatmp_timestamp = timestamp
899
        order.delivery_timestamp = timestamp
900
        order.receiver = receiver
3578 mandeep.dh 901
        update_trust_level(order)
5636 amar.kumar 902
        try:
903
            alert_client = AlertClient().get_client()
904
            alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + order.id)
905
        except Exception as e:
906
            print e
907
 
1132 chandransh 908
    session.commit()
909
 
4712 rajveer 910
def mark_order_as_delivered(orderId, deliveryTimestamp, receiver):
911
    order = Order.get_by(id=orderId)
5555 rajveer 912
    if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.DOA_PICKUP_REQUEST_RAISED, OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.RET_REQUEST_RECEIVED, OrderStatus.RET_PICKUP_CONFIRMED, OrderStatus.RET_REQUEST_AUTHORIZED, OrderStatus.RET_PICKUP_REQUEST_RAISED, OrderStatus.RTO_IN_TRANSIT, OrderStatus.BILLED, OrderStatus.RECEIVED_AT_STORE]:
4712 rajveer 913
        raise TransactionServiceException(101, "Either wrond order id or invalid state " + str(orderId))
5402 rajveer 914
 
915
    # Provider is 4 is for self pickup and hardcoded. We should figure out a way to not to hard code.   
916
    if order.status == OrderStatus.BILLED and order.logistics_provider_id != 4:
917
            raise TransactionServiceException(101, "Order is not marked for self pickup: " + str(orderId))
918
 
5555 rajveer 919
    if order.status in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.RTO_IN_TRANSIT, OrderStatus.BILLED, OrderStatus.RECEIVED_AT_STORE]:
4712 rajveer 920
        order.delivery_timestamp = deliveryTimestamp
921
        order.receiver = receiver
922
    order.status = OrderStatus.DELIVERY_SUCCESS
923
    order.statusDescription = "Order delivered"
924
    update_trust_level(order)
925
    session.commit()
5636 amar.kumar 926
    try:
927
        alert_client = AlertClient().get_client()
928
        alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + order.id)
929
    except Exception as e:
930
        print e
931
 
4712 rajveer 932
 
5555 rajveer 933
def mark_order_as_received_at_store(orderId, deliveryTimestamp):
934
    order = Order.get_by(id=orderId)
935
    if order != None or order.status in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.DELIVERED_AT_STORE]:
936
        order.status = OrderStatus.RECEIVED_AT_STORE
937
        order.statusDescription = "Order received at store"
938
        order.delivery_timestamp = deliveryTimestamp
939
    session.commit()
940
 
4910 phani.kuma 941
def mark_orders_as_rto(provider_id, returned_orders):
1135 chandransh 942
    for awb, detail in returned_orders.iteritems():
943
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
4910 phani.kuma 944
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
2684 chandransh 945
            continue
946
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
4484 rajveer 947
        order.status = OrderStatus.RTO_IN_TRANSIT
1135 chandransh 948
        order.delivery_timestamp, reason = detail.split('|')
949
        order.statusDescription = "Order Returned to Origin:" + reason
3578 mandeep.dh 950
        update_trust_level(order)
1911 chandransh 951
    session.commit()
5636 amar.kumar 952
    try:
953
        alert_client = AlertClient().get_client()
954
        alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + order.id)
955
    except Exception as e:
956
        print e
1135 chandransh 957
 
4910 phani.kuma 958
def get_rto_orders(provider_id):
959
    current_time = datetime.datetime.now()
960
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
961
    rto_orders = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.RTO_IN_TRANSIT).filter(Order.delivery_timestamp <= to_datetime).all()
962
    return rto_orders
963
 
5555 rajveer 964
def get_receive_pending_orders(storeId):
965
    return Order.query.filter_by(pickupStoreId = storeId).filter(Order.status.in_((OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.DELIVERED_AT_STORE))).all()
966
 
967
def get_received_at_store_orders(storeId):
968
    return Order.query.filter_by(pickupStoreId = storeId).filter_by(status = OrderStatus.RECEIVED_AT_STORE).all()
969
 
1246 chandransh 970
def update_non_delivery_reason(provider_id, undelivered_orders):
971
    for awb, reason in undelivered_orders.iteritems():
972
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
4920 phani.kuma 973
        if order == None or order.status == OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE:
2684 chandransh 974
            continue
975
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1246 chandransh 976
        order.statusDescription = reason
977
    session.commit()
4910 phani.kuma 978
 
979
def get_non_delivered_orders_by_courier(provider_id):
4581 phani.kuma 980
    current_time = datetime.datetime.now()
981
    today_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
982
    upto_datetime = today_datetime - datetime.timedelta(4)
4910 phani.kuma 983
    orders_not_delivered = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_((OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE))).filter(or_(Order.shipping_timestamp <= upto_datetime, Order.pickup_timestamp <= upto_datetime)).all()
4581 phani.kuma 984
    return orders_not_delivered
1246 chandransh 985
 
4910 phani.kuma 986
def mark_orders_as_local_connected(provider_id, local_connected_orders):
987
    for awb, timestamp in local_connected_orders.iteritems():
988
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
989
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
990
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
991
            continue
992
        order.status = OrderStatus.SHIPPED_TO_DESTINATION_CITY
993
        order.statusDescription = "Left Out of Origin City"
5636 amar.kumar 994
        current_time = datetime.datetime.now()
995
        order.local_connected_timestamp = datetime.datetime(current_time.year, current_time.month, current_time.day)
996
        try:
997
            monitoredEntity = MonitoredEntity();
998
            monitoredEntity.entityType=EntityType.COURIER;
999
            monitoredEntity.eventType=OrderStatus.SHIPPED_TO_DESTINATION_CITY
1000
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
1001
            #Warn alert time is taken as 15 hrs
1002
            warn_time = (order.promised_delivery_time-23*3600*1000)
1003
            #Critical alert time is taken as 25 hrs                    
1004
            critical_time = (order.promised_delivery_time-13*3600*1000)
1005
            monitoredEntity.warnExpiryTime = warn_time
1006
            monitoredEntity.criticalExpiryTime = critical_time
1007
            monitoredEntity.description="providerId = " + str(provider_id) + " destination city " + order.customer_city 
1008
            alert_client = AlertClient().get_client()
1009
            alert_client.updateMonitoredObject(monitoredEntity)
1010
        except Exception as e:
1011
            print e
1012
        session.commit()
4910 phani.kuma 1013
 
1014
def get_orders_not_local_connected(provider_id):
1015
    current_time = datetime.datetime.now()
1016
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1017
    orders_pending_local_connection = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_((OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST))).filter(or_(Order.shipping_timestamp <= to_datetime, Order.pickup_timestamp <= to_datetime)).all()
1018
    return orders_pending_local_connection
1019
 
1020
def mark_orders_as_destinationCityReached(provider_id, destination_city_reached_orders):
1021
    for awb, timestamp in destination_city_reached_orders.iteritems():
1022
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1023
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY]:
1024
            continue
1025
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1026
        order.status = OrderStatus.REACHED_DESTINATION_CITY
1027
        order.statusDescription = "Reached Destination City"
1028
        order.reached_destination_timestamp = timestamp
5636 amar.kumar 1029
        try:
1030
            monitoredEntity = MonitoredEntity();
1031
            monitoredEntity.entityType=EntityType.COURIER;
1032
            monitoredEntity.eventType=OrderStatus.REACHED_DESTINATION_CITY
1033
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
1034
            warn_time = (order.promised_delivery_time)
1035
            critical_time = (order.promised_delivery_time+12*3600*1000)
1036
            monitoredEntity.warnExpiryTime = warn_time
1037
            monitoredEntity.criticalExpiryTime = critical_time
1038
            monitoredEntity.description="providerId = " + str(provider_id) + " destination city " + order.customer_city 
1039
            alert_client = AlertClient().get_client()
1040
            alert_client.updateMonitoredObject(monitoredEntity)
1041
        except Exception as e:
1042
            print e
4910 phani.kuma 1043
    session.commit()
1044
 
1045
def mark_orders_as_firstDeliveryAttempted(provider_id, first_atdl_orders):
1046
    for awb, detail in first_atdl_orders.iteritems():
1047
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1048
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY]:
1049
            continue
1050
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1051
        order.status = OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE
1052
        order.first_dlvyatmp_timestamp, reason = detail.split('|')
1053
        order.statusDescription = reason
5636 amar.kumar 1054
        try:
1055
            monitoredEntity = MonitoredEntity();
1056
            monitoredEntity.entityType=EntityType.COURIER;
1057
            monitoredEntity.eventType=OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE
1058
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
1059
            seconds_epoch = time.time()
1060
            #Warn alert time is taken as 15 hrs
1061
            warn_time = (seconds_epoch+24*3600)*1000
1062
            #Critical alert time is taken as 25 hrs                    
1063
            critical_time = (seconds_epoch+36*3600)*1000
1064
            monitoredEntity.warnExpiryTime = warn_time
1065
            monitoredEntity.criticalExpiryTime = critical_time
1066
            monitoredEntity.description="providerId = " + str(provider_id) + " first attempt timestamp" + order.first_dlvyatmp_timestamp
1067
            alert_client = AlertClient().get_client()
1068
            alert_client.updateMonitoredObject(monitoredEntity)
1069
        except Exception as e:
1070
            print e
4910 phani.kuma 1071
    session.commit()
1072
 
4783 phani.kuma 1073
def get_orders_not_met_expected_delivery_date():
1074
    current_time = datetime.datetime.now()
1075
    today_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4910 phani.kuma 1076
    orders_not_delivered = Order.query.filter(Order.status.in_((OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY))).filter(Order.expected_delivery_time <= today_datetime).all()
4783 phani.kuma 1077
    return orders_not_delivered
1078
 
4444 rajveer 1079
def get_alerts(type, warehouseId, status, timestamp):
1080
    query = Alert.query.filter(Alert.warehouseId == warehouseId)
1081
    if type != -1 :
1082
        query = query.filter(Alert.type == type)
1083
    if status != -1 :
1084
        query = query.filter(Alert.status == status)
4394 rajveer 1085
    if timestamp:
1086
        query = query.filter(Alert.timestamp >= to_py_date(timestamp))
4412 rajveer 1087
    query = query.order_by(desc(Alert.timestamp))
483 rajveer 1088
    return query.all()
1089
 
4447 rajveer 1090
def add_alert(type, warehouseId, description):
4394 rajveer 1091
    alert = Alert()
1092
    alert.type = type
1093
    alert.status = 1
1094
    alert.description = description
1095
    alert.timestamp = datetime.datetime.now()
4447 rajveer 1096
    alert.warehouseId = warehouseId
4444 rajveer 1097
    session.commit()
766 rajveer 1098
 
4444 rajveer 1099
def mark_alerts_as_seen(warehouseId):
1100
    query = Alert.query.filter(Alert.warehouseId == warehouseId).filter(Alert.status == 1)
1101
    alerts = query.all()
1102
    for alert in alerts:
1103
        alert.status = 0    
1104
    session.commit()
1105
 
1596 ankur.sing 1106
def get_valid_order_count():
2851 chandransh 1107
    '''
1108
    Returns the number of orders which we processed. The reshipped orders are not
1109
    counted since there'll always be a new compensating order present.
1110
    '''
4682 rajveer 1111
    return Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).filter(not_(Order.status.in_((OrderStatus.RTO_RESHIPPED, OrderStatus.DOA_INVALID_RESHIPPED, OrderStatus.DOA_VALID_RESHIPPED, OrderStatus.COD_VERIFICATION_FAILED)))).count()
1596 ankur.sing 1112
 
1627 ankur.sing 1113
def get_cust_count_with_successful_txn():
2851 chandransh 1114
    '''
1115
    Returns the number of distinct customers who have done successful transactions.
1116
    It uses the sqlalchemy func module to construct an efficient query.
1117
    '''
1118
    return session.query(func.count(distinct(Order.customer_id))).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).scalar()
1627 ankur.sing 1119
 
1730 ankur.sing 1120
def get_valid_orders_amount_range():
2851 chandransh 1121
    '''
1122
    Returns a list containing the minimum and maximum amount across all
1123
    orders placed with us. No need to consider reshippped orders for min/max
1124
    amount of orders.
1125
    '''
1126
    return session.query(func.min(Order.total_amount), func.max(Order.total_amount)).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).one()
1627 ankur.sing 1127
 
1886 ankur.sing 1128
def get_valid_orders(limit):
2851 chandransh 1129
    '''
1130
    Returns the last limit number of valid orders placed with us. Ignored the
1131
    limit if it's passed as 0. Raises an excpetion if the supplied limit is 
1132
    less than 0. 
1133
    '''
1134
    if limit < 0:
1135
        raise TransactionServiceException(101, "Invalid argument limit " + limit)
4662 rajveer 1136
    query = Order.query.filter(Order.status >= OrderStatus.COD_VERIFICATION_PENDING)
1886 ankur.sing 1137
    query = query.order_by(desc(Order.created_timestamp))
2851 chandransh 1138
    if limit != 0:
1886 ankur.sing 1139
        query = query.limit(limit)
1140
    return query.all()
1141
 
5527 anupam.sin 1142
def get_next_invoice_number(orderType):
1143
    if OrderType.B2Cbulk == orderType:
1144
        orderType = OrderType.B2C
1145
    entity_id = InvoiceIDGenerator.query.filter(InvoiceIDGenerator.orderType == orderType).with_lockmode("update").one()
2783 chandransh 1146
    invoice_number = entity_id.id + 1
1147
    entity_id.id = invoice_number
1148
    return invoice_number
1149
 
2536 chandransh 1150
def toggle_doa_flag(order_id):
1151
    order = get_order(order_id)
1152
    if(order.doaFlag):
1153
        order.doaFlag = False
1154
    else:
1155
        order.doaFlag = True
1156
    session.commit()
1157
    return order.doaFlag
1158
 
4454 rajveer 1159
def mark_order_doa_request_received(orderId):
1160
    order = get_order(orderId)
1161
    if order.status != OrderStatus.DELIVERY_SUCCESS:
1162
        return False
1163
    order.status = OrderStatus.DOA_REQUEST_RECEIVED
4459 rajveer 1164
    order.statusDescription = "DOA Request Received"
4454 rajveer 1165
    session.commit()
1166
    return True
1167
 
1168
def mark_order_doa_request_authorized(orderId, isAuthorized):
1169
    order = get_order(orderId)
1170
    if order.status != OrderStatus.DOA_REQUEST_RECEIVED:
1171
        return False
1172
    if isAuthorized:
1173
        order.status = OrderStatus.DOA_REQUEST_AUTHORIZED
4459 rajveer 1174
        order.statusDescription = "DOA Request Authorized"
4454 rajveer 1175
    else:
1176
        order.status = OrderStatus.DELIVERY_SUCCESS
4459 rajveer 1177
        order.statusDescription = "Order delivered"
4454 rajveer 1178
    session.commit()
1179
    return True
1180
 
4488 rajveer 1181
def mark_order_return_request_received(orderId):
1182
    order = get_order(orderId)
1183
    if order.status != OrderStatus.DELIVERY_SUCCESS:
1184
        return False
1185
    order.status = OrderStatus.RET_REQUEST_RECEIVED
1186
    order.statusDescription = "Return Request Received"
1187
    session.commit()
1188
    return True
1189
 
1190
def mark_order_return_request_authorized(orderId, isAuthorized):
1191
    order = get_order(orderId)
1192
    if order.status != OrderStatus.RET_REQUEST_RECEIVED:
1193
        return False
1194
    if isAuthorized:
1195
        order.status = OrderStatus.RET_REQUEST_AUTHORIZED
1196
        order.statusDescription = "Return Request Authorized"
1197
    else:
1198
        order.status = OrderStatus.DELIVERY_SUCCESS
1199
        order.statusDescription = "Order delivered"
1200
    session.commit()
1201
    return True
1202
 
4579 rajveer 1203
def request_pickup_number(order_id, providerId):
2536 chandransh 1204
    order = get_order(order_id)
4495 rajveer 1205
    if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_REQUEST_AUTHORIZED and order.status != OrderStatus.RET_REQUEST_AUTHORIZED:
2536 chandransh 1206
        return False
1207
    from_user = 'cnc.center@shop2020.in'
1208
    from_pwd = '5h0p2o2o'
1209
 
4227 rajveer 1210
    subject = "Pickup request from " + order.customer_city
2536 chandransh 1211
    try:
3133 rajveer 1212
        catalog_client = CatalogClient().get_client()
2536 chandransh 1213
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
1214
 
1215
        logistics_client = LogisticsClient().get_client()
4579 rajveer 1216
        provider = logistics_client.getProvider(providerId)
3051 chandransh 1217
        to_addr = provider.details[DeliveryType.PREPAID].email
2536 chandransh 1218
        raw_message = '''
1219
        Dear Sir/Madam,
1220
 
2559 chandransh 1221
        Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.
2536 chandransh 1222
 
1223
        Pickup CODE: %(provider_code)s
1224
        Total Weight: %(order_weight)s kg
1225
 
2559 chandransh 1226
        Pickup Address:
2536 chandransh 1227
 
1228
        %(customer_address)s
1229
 
1230
        Delivery Address:
1231
 
1232
        %(warehouse_executive)s
1233
        %(warehouse_address)s
1234
        PIN %(warehouse_pin)s
1235
 
1236
        Thanks and Regards
4227 rajveer 1237
        Sandeep Sachdeva
2536 chandransh 1238
        '''
4579 rajveer 1239
 
1240
        if warehouse.id == 7:
1241
            executive = 'Amit Kumar'
1242
        else:
4966 phani.kuma 1243
            executive = 'Dinesh Kumar'
4579 rajveer 1244
 
2559 chandransh 1245
        message = dedent(raw_message) % { 'customer_city' : order.customer_city,
3051 chandransh 1246
                                          'provider_code' : provider.details[DeliveryType.PREPAID].accountNo,
2536 chandransh 1247
                                          'order_weight' : str(order.total_weight),
1248
                                          'customer_address' : __get_order_address(order),
4579 rajveer 1249
                                          'warehouse_executive' : executive,
2536 chandransh 1250
                                          'warehouse_address' : warehouse.location,
4966 phani.kuma 1251
                                          'warehouse_pin' : warehouse.pincode}
5256 rajveer 1252
        to_addresses = [to_addr, 'zaffar.kar@shop2020.in', 'suraj.sharma@shop2020.in']
4966 phani.kuma 1253
 
4606 rajveer 1254
        mail(from_user, from_pwd, to_addresses, subject, message)
4495 rajveer 1255
        if order.status == OrderStatus.RET_REQUEST_AUTHORIZED:
1256
            order.status = OrderStatus.RET_PICKUP_REQUEST_RAISED
1257
            order.statusDescription = "Pick up requested for RETURN"
1258
        else:
1259
            order.status = OrderStatus.DOA_PICKUP_REQUEST_RAISED
1260
            order.statusDescription = "Pick up requested for DOA"
4815 phani.kuma 1261
        order.doa_logistics_provider_id = providerId
2536 chandransh 1262
        session.commit()
1263
        return True
1264
    except Exception as e:
1265
        print sys.exc_info()[0]
1266
        return False
1267
 
4602 rajveer 1268
def authorize_pickup(order_id, pickup_number, providerId):
2536 chandransh 1269
    order = get_order(order_id)
4495 rajveer 1270
    if order.status not in [OrderStatus.DOA_PICKUP_REQUEST_RAISED, OrderStatus.RET_PICKUP_REQUEST_RAISED]:
2536 chandransh 1271
        return False
4815 phani.kuma 1272
    if order.doa_logistics_provider_id is not None:
1273
        providerId = order.doa_logistics_provider_id    #previously we are not storing this so data is taken from omdashboarduser
2536 chandransh 1274
    from_user = 'help@shop2020.in'
1275
    from_pwd = '5h0p2o2o'
1276
    subject = 'Pickup details'
1277
    filename = "/tmp/" +  str(order.id) +".pdf" 
1278
    try:
3133 rajveer 1279
        catalog_client = CatalogClient().get_client()
2536 chandransh 1280
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
1281
 
1282
        logistics_client = LogisticsClient().get_client()
4602 rajveer 1283
        provider = logistics_client.getProvider(providerId)
2536 chandransh 1284
        provider_name = provider.name
1285
 
1286
        to_addr = order.customer_email
1287
        today = date.today().strftime("%d-%B-%Y (%A)")
1288
 
1289
        raw_message = '''
1290
        Dear Mr. %(customer_name)s,
1291
 
4815 phani.kuma 1292
        In reference to the return of order ID %(order_id)d, ''' + __generate_mail_body_for_authorize_pickup(order)
1293
        raw_message = raw_message + '''
2536 chandransh 1294
        Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.
1295
        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.
1296
 
1297
        Pickup will happen from the below mentioned address:-
1298
 
1299
        %(customer_address)s
1300
 
1301
        Do let us know in case of any concerns
1302
 
1303
        Thanks & Regards
1304
        Saholic Team
1305
        '''
1306
        message = dedent(raw_message) % {'customer_name' : order.customer_name,
1307
                                         'order_id' : order_id,
1308
                                         'provider_name' : provider_name,
1309
                                         'date': today,
1310
                                         'pickup_request_no' : pickup_number,
1311
                                         'customer_address' : __get_order_address(order)}
1312
        print message
1313
        __generate_return_advice(order, warehouse, provider, filename)
3527 chandransh 1314
        mail(from_user, from_pwd, [to_addr], subject, message, [get_attachment_part(filename)])
2536 chandransh 1315
        order.pickupRequestNo = pickup_number
4495 rajveer 1316
        if order.status == OrderStatus.RET_PICKUP_REQUEST_RAISED:
1317
            order.status = OrderStatus.RET_PICKUP_CONFIRMED
1318
            order.statusDescription = "RETURN pick up confirmed"
1319
        else:
1320
            order.status = OrderStatus.DOA_PICKUP_CONFIRMED
1321
            order.statusDescription = "DOA pick up confirmed"
2764 chandransh 1322
        order.doa_auth_timestamp = datetime.datetime.now()
2536 chandransh 1323
        session.commit()
1324
        return True
1325
    except Exception as e:
4234 rajveer 1326
        print sys.exc_info()
4506 phani.kuma 1327
        traceback.print_tb(sys.exc_info()[2])
2536 chandransh 1328
        return False
1329
    finally:
1330
        if os.path.exists(filename):
1331
            os.remove(filename)
1332
 
4815 phani.kuma 1333
def __generate_mail_body_for_authorize_pickup(order):
1334
    brand_msgbody_map = {'Nokia' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the all original accessories, original handset and the invoice.',
1335
                         'Micromax' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the all original accessories, original handset and the invoice.',
1336
                         'Karbonn' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the all original accessories, original handset and the invoice.',
1337
                         'Sony Ericsson' : 'we request you to kindly pack the original DOA certificate and the invoice.',
1338
                         'Others Handsets' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the original "DOA" certificate and the invoice. Please paste the original DOA on the sealed box. Kindly ensure that the product is properly sealed. If we receive open sealed products, we will not be able to accept.',
1339
                         'Handsets Return' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the all original accessories, original handset and the invoice.',
1340
                         'Accessories' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the original product and the invoice.'}
1341
    categories = ["Handsets", "Tablets", "Laptops"]
1342
    lineitem = order.lineitems[0]
1343
    brand = lineitem.brand
1344
    productGroup = lineitem.productGroup
1345
    searchkey = None
1346
    if productGroup not in categories:
1347
        searchkey = 'Accessories'
1348
    elif order.status == OrderStatus.RET_PICKUP_REQUEST_RAISED:
1349
        searchkey = 'Handsets Return'
1350
    elif brand == 'Nokia':
1351
        searchkey = 'Nokia'
1352
    elif brand == 'Micromax':
1353
        searchkey = 'Micromax'
1354
    elif brand == 'Karbonn':
1355
        searchkey = 'Karbonn'
1356
    elif brand == 'Sony Ericsson':
1357
        searchkey = 'Sony Ericsson'
1358
    else:
1359
        searchkey = 'Others Handsets'
1360
    return brand_msgbody_map.get(searchkey)
1361
 
2764 chandransh 1362
def mark_doas_as_picked_up(provider_id, pickup_details):
1363
    for pickupNo, doa_pickup_timestamp in pickup_details.iteritems():
4815 phani.kuma 1364
        order = Order.query.filter_by(pickupRequestNo=pickupNo, doa_logistics_provider_id = provider_id).first()
4452 rajveer 1365
        if order == None or order.status != OrderStatus.DOA_PICKUP_CONFIRMED:
2764 chandransh 1366
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1367
            continue
1368
        order.status = OrderStatus.DOA_RETURN_IN_TRANSIT
1369
        order.statusDescription = "DOA picked up by Courier Company"
1370
        order.doa_pickup_timestamp = doa_pickup_timestamp
1371
    session.commit()
1372
 
4910 phani.kuma 1373
def get_doas_not_picked_up(provider_id):
2764 chandransh 1374
    current_time = datetime.datetime.now()
1375
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4815 phani.kuma 1376
    orders_not_picked_up = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter_by(status=OrderStatus.DOA_PICKUP_CONFIRMED).filter(Order.doa_auth_timestamp <= to_datetime).all()
2764 chandransh 1377
    return orders_not_picked_up
1378
 
4741 phani.kuma 1379
def mark_return_orders_as_picked_up(provider_id, pickup_details):
1380
    for pickupNo, return_order_pickup_timestamp in pickup_details.iteritems():
4815 phani.kuma 1381
        order = Order.query.filter_by(pickupRequestNo=pickupNo, doa_logistics_provider_id = provider_id).first()
4741 phani.kuma 1382
        if order == None or order.status != OrderStatus.RET_PICKUP_CONFIRMED:
1383
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1384
            continue
1385
        order.status = OrderStatus.RET_RETURN_IN_TRANSIT
1386
        order.statusDescription = "Return order picked up by Courier Company"
1387
        order.doa_pickup_timestamp = return_order_pickup_timestamp
1388
    session.commit()
1389
 
4910 phani.kuma 1390
def get_return_orders_not_picked_up(provider_id):
4741 phani.kuma 1391
    current_time = datetime.datetime.now()
1392
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4815 phani.kuma 1393
    orders_not_picked_up = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter_by(status=OrderStatus.RET_PICKUP_CONFIRMED).filter(Order.doa_auth_timestamp <= to_datetime).all()
4741 phani.kuma 1394
    return orders_not_picked_up
1395
 
4479 rajveer 1396
def receive_return(order_id, receiveCondition):
2591 chandransh 1397
    order = get_order(order_id)
4365 mandeep.dh 1398
 
4452 rajveer 1399
    if order.status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
4479 rajveer 1400
        if receiveCondition == 0:
1401
            order.status = OrderStatus.DOA_RECEIVED_PRESTINE
1402
            order.statusDescription = "DOA package received"
1403
        elif receiveCondition == 1:
1404
            order.status = OrderStatus.DOA_RECEIVED_DAMAGED
1405
            order.statusDescription = "DOA received damaged"
1406
        elif receiveCondition == 2:
1407
            order.status = OrderStatus.DOA_LOST_IN_TRANSIT
1408
            order.statusDescription = "DOA lost in transit"
2764 chandransh 1409
        order.received_return_timestamp = datetime.datetime.now()
4495 rajveer 1410
    elif order.status in [OrderStatus.RET_PICKUP_CONFIRMED, OrderStatus.RET_RETURN_IN_TRANSIT]:
1411
        if receiveCondition == 0:
1412
            order.status = OrderStatus.RET_RECEIVED_PRESTINE
1413
            order.statusDescription = "RETURN package received"
1414
        elif receiveCondition == 1:
1415
            order.status = OrderStatus.RET_RECEIVED_DAMAGED
1416
            order.statusDescription = "RETURN received damaged"
1417
        elif receiveCondition == 2:
1418
            order.status = OrderStatus.RET_LOST_IN_TRANSIT
1419
            order.statusDescription = "RETURN lost in transit"
1420
        order.received_return_timestamp = datetime.datetime.now()
4484 rajveer 1421
    elif order.status == OrderStatus.RTO_IN_TRANSIT :
4486 rajveer 1422
        if receiveCondition == 0:
1423
            order.status = OrderStatus.RTO_RECEIVED_PRESTINE
4515 mandeep.dh 1424
            order.statusDescription = "Returned to origin"
4486 rajveer 1425
        elif receiveCondition == 1:
1426
            order.status = OrderStatus.RTO_RECEIVED_DAMAGED
1427
            order.statusDescription = "RTO received damaged"
1428
        elif receiveCondition == 2:
1429
            order.status = OrderStatus.RTO_LOST_IN_TRANSIT
1430
            order.statusDescription = "RTO lost in transit"
2764 chandransh 1431
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 1432
    else:
2591 chandransh 1433
        return False
5110 mandeep.dh 1434
 
1435
    # For OUR warehouses, we need to scan in items for every return
1436
    catalogClient = CatalogClient().get_client()
1437
    warehouse = catalogClient.getWarehouse(order.warehouse_id)
1438
    if warehouse.billingType == BillingType.OURS:
5361 mandeep.dh 1439
        scanMap = {
1440
            OrderStatus.RTO_RECEIVED_PRESTINE : ScanType.SALE_RET,
1441
            OrderStatus.RTO_RECEIVED_DAMAGED  : ScanType.SALE_RET_UNUSABLE,
1442
            OrderStatus.RTO_LOST_IN_TRANSIT   : ScanType.LOST_IN_TRANSIT,
1443
            OrderStatus.DOA_RECEIVED_PRESTINE : ScanType.DOA_IN,
1444
            OrderStatus.DOA_RECEIVED_DAMAGED  : ScanType.DOA_IN,
1445
            OrderStatus.DOA_LOST_IN_TRANSIT   : ScanType.LOST_IN_TRANSIT
1446
        }
5110 mandeep.dh 1447
 
5419 mandeep.dh 1448
        if scanMap.has_key(order.status):
1449
            scanType = scanMap[order.status]
5361 mandeep.dh 1450
            lineitem = order.lineitems[0]
1451
            item = catalogClient.getItem(lineitem.item_id)
1452
            warehouseClient = WarehouseClient().get_client()
1453
            if item.type == ItemType.SERIALIZED:
5110 mandeep.dh 1454
                warehouseClient.scanSerializedItemForOrder(lineitem.serial_number, scanType, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
5361 mandeep.dh 1455
            else:
1456
                warehouseClient.scanForOrder(None, scanType, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
5110 mandeep.dh 1457
 
5558 mandeep.dh 1458
    session.commit()
2591 chandransh 1459
    return True
1460
 
1461
def validate_doa(order_id, is_valid):
1462
    order = get_order(order_id)
4452 rajveer 1463
    if order.status != OrderStatus.DOA_RECEIVED_PRESTINE:
2591 chandransh 1464
        return False
1465
    if is_valid:
2609 chandransh 1466
        order.status = OrderStatus.DOA_CERT_VALID
1467
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 1468
    else:
1469
        order.status = OrderStatus.DOA_CERT_INVALID
1470
        order.statusDescription = "DOA Certificate Invalid"
3578 mandeep.dh 1471
        update_trust_level(order)
2591 chandransh 1472
    session.commit()
1473
    return True
1474
 
4495 rajveer 1475
def validate_return_product(order_id, is_usable):
1476
    order = get_order(order_id)
1477
    if order.status != OrderStatus.RET_RECEIVED_PRESTINE:
1478
        return False
5110 mandeep.dh 1479
 
1480
    scanType = ScanType.SALE_RET_UNUSABLE
4495 rajveer 1481
    if is_usable:
1482
        order.status = OrderStatus.RET_PRODUCT_USABLE
1483
        order.statusDescription = "Return product usable"
5110 mandeep.dh 1484
        scanType = ScanType.SALE_RET
4495 rajveer 1485
    else:
1486
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE
1487
        order.statusDescription = "Return product unusable"
1488
        update_trust_level(order)
1489
    session.commit()
5110 mandeep.dh 1490
 
1491
    # For OUR warehouses, we need to scan in items for every return
1492
    catalogClient = CatalogClient().get_client()
1493
    warehouse = catalogClient.getWarehouse(order.warehouse_id)
1494
    if warehouse.billingType == BillingType.OURS:
1495
        lineitem = order.lineitems[0]
5361 mandeep.dh 1496
        item = catalogClient.getItem(lineitem.item_id)
5110 mandeep.dh 1497
        warehouse_client = WarehouseClient().get_client()
5361 mandeep.dh 1498
        if item.type == ItemType.SERIALIZED:
1499
            warehouse_client.scanSerializedItemForOrder(lineitem.serial_number, scanType, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
1500
        else:
1501
            warehouse_client.scanForOrder(None, scanType, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
4495 rajveer 1502
    return True
1503
 
2628 chandransh 1504
def reship_order(order_id):
1505
    """
4484 rajveer 1506
    If the order is in RTO_RECEIVED_PRESTINE or DOA_CERT_INVALID state, it does the following:
2628 chandransh 1507
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
4484 rajveer 1508
        2. Marks the current order as one of the final states RTO_RESHIPPED and DOA_INVALID_RESHIPPED depending on what state the order started in.
2628 chandransh 1509
 
1510
    If the order is in DOA_CERT_VALID state, it does the following:
1511
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
1512
        2. Creates a return order for the warehouse executive to return the DOA material.
4452 rajveer 1513
        3. Marks the current order as the final DOA_VALID_RESHIPPED state.
2628 chandransh 1514
 
1515
    Returns the id of the newly created order.
1516
 
1517
    Throws an exception if the order with the given id couldn't be found.
1518
 
1519
    Parameters:
1520
     - orderId
1521
    """
1522
    order = get_order(order_id)
4484 rajveer 1523
    if order.status == OrderStatus.RTO_RECEIVED_PRESTINE:
4220 rajveer 1524
        new_order = __clone_order(order, True, order.cod)
4484 rajveer 1525
        order.status = OrderStatus.RTO_RESHIPPED
2628 chandransh 1526
        order.statusDescription = "Order Reshipped"
1527
        session.commit()
3578 mandeep.dh 1528
        update_trust_level(order)
4486 rajveer 1529
    elif order.status == OrderStatus.RTO_RECEIVED_DAMAGED:
1530
        new_order = __clone_order(order, False, order.cod)
1531
        ret_order = __create_return_order(order)
1532
        order.status = OrderStatus.RTO_DAMAGED_RESHIPPED
1533
        order.statusDescription = "Order Reshipped Received Damaged"
1534
        session.commit()
1535
    elif order.status == OrderStatus.RTO_LOST_IN_TRANSIT:
1536
        new_order = __clone_order(order, False, order.cod)
1537
        order.status = OrderStatus.RTO_LOST_IN_TRANSIT_RESHIPPED
1538
        order.statusDescription = "Order Reshipped Lost In Transit"
1539
        session.commit()
4662 rajveer 1540
    elif order.status == OrderStatus.LOST_IN_TRANSIT:
1541
        new_order = __clone_order(order, False, order.cod)
1542
        order.status = OrderStatus.LOST_IN_TRANSIT_RESHIPPED
1543
        order.statusDescription = "Order Reshipped Lost In Transit"
1544
        session.commit()
2628 chandransh 1545
    elif order.status == OrderStatus.DOA_CERT_INVALID:
4220 rajveer 1546
        new_order = __clone_order(order, True, False)
2628 chandransh 1547
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
1548
        order.statusDescription = "Order Reshipped"
1549
        session.commit()
5620 mandeep.dh 1550
        warehouseClient = WarehouseClient().get_client()
1551
        inventoryItem = warehouseClient.getInventoryItemFromOrder(order_id)
1552
        warehouseClient.scanForOrder(inventoryItem, ScanType.SALE, new_order.lineitems[0].quantity, new_order.id, new_order.fulfilmentWarehouseId, new_order.warehouse_id)
2628 chandransh 1553
    elif order.status == OrderStatus.DOA_CERT_VALID:
4220 rajveer 1554
        new_order = __clone_order(order, False, False)
2628 chandransh 1555
        ret_order = __create_return_order(order)
4452 rajveer 1556
        order.status = OrderStatus.DOA_VALID_RESHIPPED
2628 chandransh 1557
        order.statusDescription = "Order Reshipped"
1558
        session.commit()
4479 rajveer 1559
    elif order.status == OrderStatus.DOA_RECEIVED_DAMAGED:
1560
        new_order = __clone_order(order, False, False)
1561
        ret_order = __create_return_order(order)
1562
        order.status = OrderStatus.DOA_RESHIPPED_RCVD_DAMAGED
1563
        order.statusDescription = "Order Reshipped Received Damaged"
1564
        session.commit()
1565
    elif order.status == OrderStatus.DOA_LOST_IN_TRANSIT:
1566
        new_order = __clone_order(order, False, False)
1567
        order.status = OrderStatus.DOA_RESHIPPED_LOST_IN_TRANSIT
1568
        order.statusDescription = "Order Reshipped Lost In Transit"
1569
        session.commit()
4614 rajveer 1570
    elif order.status == OrderStatus.RET_PRODUCT_USABLE:
5620 mandeep.dh 1571
        new_order = __clone_order(order, False, False)
4614 rajveer 1572
        order.status = OrderStatus.RET_PRODUCT_USABLE_RESHIPPED
4495 rajveer 1573
        order.statusDescription = "Order Reshipped"
1574
        session.commit()
4614 rajveer 1575
    elif order.status == OrderStatus.RET_PRODUCT_UNUSABLE:
4495 rajveer 1576
        new_order = __clone_order(order, False, False)
1577
        ret_order = __create_return_order(order)
4614 rajveer 1578
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE_RESHIPPED
4495 rajveer 1579
        order.statusDescription = "Order Reshipped"
1580
        session.commit()
1581
    elif order.status == OrderStatus.RET_RECEIVED_DAMAGED:
1582
        new_order = __clone_order(order, False, False)
1583
        ret_order = __create_return_order(order)
1584
        order.status = OrderStatus.RET_RESHIPPED_RCVD_DAMAGED
1585
        order.statusDescription = "Order Reshipped Received Damaged"
1586
        session.commit()
1587
    elif order.status == OrderStatus.RET_LOST_IN_TRANSIT:
1588
        new_order = __clone_order(order, False, False)
1589
        order.status = OrderStatus.RET_RESHIPPED_LOST_IN_TRANSIT
1590
        order.statusDescription = "Order Reshipped Lost In Transit"
1591
        session.commit()
2628 chandransh 1592
    else:
1593
        raise TransactionServiceException(112, "This order can't be reshipped")
1594
 
2764 chandransh 1595
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 1596
    order.new_order_id = new_order.id
1597
    session.commit()
1598
 
1599
    return new_order.id
1600
 
3226 chandransh 1601
def refund_order(order_id, refunded_by, reason):
2628 chandransh 1602
    """
4484 rajveer 1603
    If the order is in RTO_RECEIVED_PRESTINE, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
2628 chandransh 1604
        1. Creates a refund request for batch processing.
1605
        2. Creates a return order for the warehouse executive to return the shipped material.
4484 rajveer 1606
        3. Marks the current order as RTO_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
2628 chandransh 1607
 
1608
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
1609
        1. Creates a refund request for batch processing.
3226 chandransh 1610
        2. Cancels the reservation of the item in the warehouse.
1611
        3. Marks the current order as the REFUNDED final state.
2628 chandransh 1612
 
3226 chandransh 1613
    For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
1614
        1. Cancels the reservation of the item in the warehouse.
1615
        2. Marks the current order as CANCELED.
1616
 
1617
    In all cases, it updates the reason for cancellation or refund and the person who performed the action.
1618
 
1619
    Returns True if it is successful, False otherwise.
2628 chandransh 1620
 
1621
    Throws an exception if the order with the given id couldn't be found.
1622
 
1623
    Parameters:
3226 chandransh 1624
     - order_id
1625
     - refunded_by
1626
     - reason
2628 chandransh 1627
    """
3414 chandransh 1628
    logging.info("Refunding order id: " + str(order_id))
2628 chandransh 1629
    order = get_order(order_id)
3186 chandransh 1630
 
3226 chandransh 1631
    if order.cod:
3414 chandransh 1632
        logging.info("Refunding COD order with status " + str(order.status))
4662 rajveer 1633
        status_transition = { OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
1634
                     OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 1635
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
1636
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 1637
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
1638
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 1639
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
1640
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 1641
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
1642
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
1643
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
1644
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
4682 rajveer 1645
                     OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.COD_VERIFICATION_FAILED,
1646
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1647
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1648
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1649
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1650
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1651
                     OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1652
                     OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
4247 rajveer 1653
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST
3366 chandransh 1654
                     }
1655
        if order.status not in status_transition.keys():
1656
            raise TransactionServiceException(114, "This order can't be refunded")
1657
 
5199 mandeep.dh 1658
        if order.status in [OrderStatus.COD_VERIFICATION_PENDING, 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, OrderStatus.ACCEPTED]:
3226 chandransh 1659
            __update_inventory_reservation(order)
1660
            order.statusDescription = "Order Cancelled"
3415 chandransh 1661
        elif order.status == OrderStatus.BILLED:
3413 chandransh 1662
            __create_return_order(order)
1663
            order.statusDescription = "Order Cancelled"
4486 rajveer 1664
        elif order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT]:
5386 phani.kuma 1665
            if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
1666
                __create_return_order(order)
4486 rajveer 1667
            order.statusDescription = "RTO Refunded"
4662 rajveer 1668
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
5386 phani.kuma 1669
            #__create_return_order(order)
4662 rajveer 1670
            order.statusDescription = "Lost in Transit Refunded"
4479 rajveer 1671
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
5386 phani.kuma 1672
            if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
1673
                __create_return_order(order)
3226 chandransh 1674
            __create_refund(order)
4495 rajveer 1675
            order.statusDescription = "DOA Refunded"
1676
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
5386 phani.kuma 1677
            if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
1678
                __create_return_order(order)
4495 rajveer 1679
            __create_refund(order)
1680
            order.statusDescription = "Return Refunded"
4247 rajveer 1681
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
5199 mandeep.dh 1682
            if order.previousStatus in [OrderStatus.COD_VERIFICATION_PENDING, 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, OrderStatus.ACCEPTED]:
4247 rajveer 1683
                __update_inventory_reservation(order)
1684
                order.statusDescription = "Order Cancelled on customer request"
1685
            elif order.previousStatus == OrderStatus.BILLED:
1686
                __create_return_order(order)
1687
                order.statusDescription = "Order Cancelled on customer request"
3226 chandransh 1688
    else:
4662 rajveer 1689
        status_transition = {OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
1690
                     OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 1691
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
1692
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 1693
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
1694
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 1695
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
1696
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 1697
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
1698
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
1699
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
1700
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
4682 rajveer 1701
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1702
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1703
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1704
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1705
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1706
                     OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
1707
                     OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
4247 rajveer 1708
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST,
1709
                     OrderStatus.PAYMENT_FLAGGED : OrderStatus.PAYMENT_FLAGGED_DENIED
3366 chandransh 1710
                     }
1711
        if order.status not in status_transition.keys():
1712
            raise TransactionServiceException(114, "This order can't be refunded")
1713
 
4495 rajveer 1714
        if order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT] :
5386 phani.kuma 1715
            if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
1716
                __create_return_order(order)
3226 chandransh 1717
            __create_refund(order)
4495 rajveer 1718
            order.statusDescription = "RTO Refunded"
4662 rajveer 1719
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
5386 phani.kuma 1720
            #__create_return_order(order)
4662 rajveer 1721
            __create_refund(order)
1722
            order.statusDescription = "Lost in Transit Refunded"
4495 rajveer 1723
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
5386 phani.kuma 1724
            if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
1725
                __create_return_order(order)
4495 rajveer 1726
            __create_refund(order)
1727
            order.statusDescription = "DOA Refunded"
1728
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
5386 phani.kuma 1729
            if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
1730
                __create_return_order(order)
4495 rajveer 1731
            __create_refund(order)
1732
            order.statusDescription = "Return Refunded"
5199 mandeep.dh 1733
        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, OrderStatus.ACCEPTED]:
3226 chandransh 1734
            __update_inventory_reservation(order)
1735
            order.statusDescription = "Order Refunded"
4247 rajveer 1736
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
5272 mandeep.dh 1737
            if order.previousStatus 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, OrderStatus.PAYMENT_FLAGGED, OrderStatus.ACCEPTED]:
4672 rajveer 1738
                if order.previousStatus == OrderStatus.ACCEPTED:
1739
                    __create_refund(order)
4247 rajveer 1740
                __update_inventory_reservation(order)
1741
                order.statusDescription = "Order Cancelled on customer request"
1742
            elif order.previousStatus == OrderStatus.BILLED:
1743
                __create_return_order(order)
1744
                __create_refund(order)
1745
                order.statusDescription = "Order Cancelled on customer request"
1746
        elif order.status == OrderStatus.PAYMENT_FLAGGED:
1747
            __update_inventory_reservation(order)
1748
            order.statusDescription = "Order Cancelled due to payment flagged"
3195 chandransh 1749
 
4873 mandeep.dh 1750
    # For orders that are cancelled after being billed, we need to scan in the scanned out
1751
    # inventory item and change availability accordingly
5110 mandeep.dh 1752
    catalogClient = CatalogClient().get_client()
1753
    warehouse = catalogClient.getWarehouse(order.warehouse_id)
1754
    if warehouse.billingType == BillingType.OURS:
4873 mandeep.dh 1755
        if order.status in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH] or (order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED and order.previousStatus in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH]):
1756
            lineitem = order.lineitems[0]
5177 mandeep.dh 1757
            item = catalogClient.getItem(lineitem.item_id)
5361 mandeep.dh 1758
            warehouseClient = WarehouseClient().get_client()
5177 mandeep.dh 1759
            if ItemType.SERIALIZED == item.type:
1760
                warehouseClient.scanSerializedItemForOrder(lineitem.serial_number, ScanType.SALE_RET, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
5361 mandeep.dh 1761
            else:
1762
                warehouseClient.scanForOrder(None, ScanType.SALE_RET, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
4873 mandeep.dh 1763
 
3195 chandransh 1764
    order.status = status_transition[order.status]
1765
    order.refund_timestamp = datetime.datetime.now()
3226 chandransh 1766
    order.refunded_by = refunded_by
1767
    order.refund_reason = reason
4873 mandeep.dh 1768
 
2628 chandransh 1769
    session.commit()
1770
    return True
1771
 
3186 chandransh 1772
def __update_inventory_reservation(order):
3191 chandransh 1773
    '''
1774
    Reduce the reservation count for all line items of the given order.
1775
    '''
3186 chandransh 1776
    try:
1777
        catalog_client = CatalogClient().get_client()
1778
        for lineitem in order.lineitems:
5530 mandeep.dh 1779
            catalog_client.reduceReservationCount(lineitem.item_id, order.fulfilmentWarehouseId, lineitem.quantity)
3186 chandransh 1780
    except:
1781
        print "Unable to reduce reservation count"
1782
 
4220 rajveer 1783
def __clone_order(order, should_copy_billing_info, is_cod):
2628 chandransh 1784
    current_time = datetime.datetime.now()
1785
    new_order = Order()
1786
    new_order.customer_id = order.customer_id
1787
    new_order.customer_name = order.customer_name
1788
    new_order.customer_city = order.customer_city
1789
    new_order.customer_state = order.customer_state
1790
    new_order.customer_mobilenumber = order.customer_mobilenumber
1791
    new_order.customer_pincode = order.customer_pincode
1792
    new_order.customer_address1 = order.customer_address1
1793
    new_order.customer_address2 = order.customer_address2
1794
    new_order.customer_email = order.customer_email
1795
    new_order.total_amount = order.total_amount
1796
    new_order.total_weight = order.total_weight
1797
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1798
    new_order.statusDescription = 'Submitted for Processing'
1799
    new_order.created_timestamp = current_time
5062 varun.gupt 1800
    new_order.originalOrderId = order.originalOrderId if order.originalOrderId is not None else order.id 
2628 chandransh 1801
 
1802
    new_order.transaction = order.transaction
4220 rajveer 1803
    new_order.cod = is_cod
5527 anupam.sin 1804
    new_order.orderType = order.orderType
2628 chandransh 1805
 
1806
    for line_item in order.lineitems:
1807
        litem = LineItem()
1808
        litem.item_id = line_item.item_id
1809
        litem.productGroup = line_item.productGroup
1810
        litem.brand = line_item.brand
1811
        if line_item.model_number:
1812
            litem.model_number = line_item.model_number
1813
        if line_item.model_name:    
1814
            litem.model_name = line_item.model_name
1815
        if line_item.color:
1816
            litem.color = line_item.color
1817
        if line_item.extra_info:
1818
            litem.extra_info = line_item.extra_info
1819
        litem.quantity = line_item.quantity
1820
        litem.unit_price = line_item.unit_price
1821
        litem.unit_weight = line_item.unit_weight
1822
        litem.total_price = line_item.total_price
1823
        litem.total_weight = line_item.total_weight
1824
        litem.transfer_price = line_item.transfer_price
4840 mandeep.dh 1825
        litem.dealText = line_item.dealText
2628 chandransh 1826
        litem.order = new_order
1827
 
1828
    logistics_client = LogisticsClient().get_client()
1829
    item_id = new_order.lineitems[0].item_id
4479 rajveer 1830
    logistics_info = logistics_client.getLogisticsInfo(new_order.customer_pincode, item_id, is_cod) #TODO: We should be able to pass another flag to suggest ignoring the inventory situation.
2628 chandransh 1831
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
1832
    new_order.warehouse_id = logistics_info.warehouseId
5110 mandeep.dh 1833
    new_order.fulfilmentWarehouseId = logistics_info.fulfilmentWarehouseId
2628 chandransh 1834
    new_order.logistics_provider_id = logistics_info.providerId
1835
    new_order.airwaybill_no = logistics_info.airway_billno
1836
    new_order.tracking_id = new_order.airwaybill_no
1837
    new_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 1838
    new_order.promised_delivery_time = new_order.expected_delivery_time
4299 rajveer 1839
 
2628 chandransh 1840
    if should_copy_billing_info:
5388 phani.kuma 1841
        new_order.vendorId = order.vendorId
2628 chandransh 1842
        new_order.invoice_number = order.invoice_number
1843
        new_order.billed_by = order.billed_by
1844
        new_order.warehouse_id = order.warehouse_id
5110 mandeep.dh 1845
        new_order.fulfilmentWarehouseId = order.fulfilmentWarehouseId
5620 mandeep.dh 1846
        new_order.jacket_number = order.jacket_number
1847
        new_order.lineitems[0].serial_number = order.lineitems[0].serial_number
1848
        new_order.lineitems[0].item_number   = order.lineitems[0].item_number
2628 chandransh 1849
        new_order.accepted_timestamp = current_time
1850
        new_order.billing_timestamp = current_time    
1851
        new_order.status = OrderStatus.BILLED
1852
        new_order.statusDescription = 'Order Billed'
1853
    else:       
3133 rajveer 1854
        catalog_client = CatalogClient().get_client()
5110 mandeep.dh 1855
        catalog_client.reserveItemInWarehouse(item_id, logistics_info.fulfilmentWarehouseId, new_order.lineitems[0].quantity)
2628 chandransh 1856
 
1857
    return new_order
1858
 
1859
def __create_return_order(order):
2687 chandransh 1860
    ret_order = ReturnOrder(order)
2628 chandransh 1861
    return ret_order
1862
 
1863
def __create_refund(order):
4078 chandransh 1864
    payment_client = PaymentClient().get_client()
1865
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
2747 chandransh 1866
    return
2628 chandransh 1867
 
2536 chandransh 1868
def __get_order_address(order):
1869
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
1870
    if order.customer_address2:
1871
        address = address + order.customer_address2 + "\n"
1872
    address = address + order.customer_city + "\n"
1873
    address = address + order.customer_state + "\n"
1874
    address = address + "PIN " + order.customer_pincode + "\n"
1875
    address = address + "Phone: " + order.customer_mobilenumber
1876
    return address
1877
 
4815 phani.kuma 1878
def __generate_return_advice(order, warehouse, provider, filename):
1879
    if warehouse.id == 7:
1880
        executive = 'Amit Kumar'
1881
    else:
4966 phani.kuma 1882
        executive = 'Dinesh Kumar'
2536 chandransh 1883
    pdf = Canvas(filename)
1884
    pdf.setFont('Times-Bold',16)
1885
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
1886
    address_text.textLine("To")
4815 phani.kuma 1887
    address_text.textLine(executive)
2536 chandransh 1888
    for line in warehouse.location.split("\n"):
1889
        address_text.textLine(line)
1890
    address_text.textLine("PIN " + warehouse.pincode)
1891
    pdf.drawText(address_text)
1892
 
1893
    pdf.setFont('Times-Roman',12)
1894
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
3051 chandransh 1895
    order_text.textLine("Pickup CODE: " + provider.details[DeliveryType.PREPAID].accountNo)
2536 chandransh 1896
    lineitem = order.lineitems[0] 
4234 rajveer 1897
    order_text.textLine("Content : " + lineitem.brand + " " + str(lineitem.model_number) + " " + str(lineitem.color))
2536 chandransh 1898
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
1899
    order_text.textLine("Order ID : " + str(order.id))
1900
    pdf.drawText(order_text)
1901
    pdf.showPage()
1902
    pdf.save()
1903
    return filename
1904
 
2697 chandransh 1905
def get_return_orders(warehouse_id, from_date, to_date):
1906
    query = ReturnOrder.query.filter_by(processedStatus = False)
1907
    if warehouse_id != -1:
1908
        query = query.filter_by(warehouseId = warehouse_id)
1909
    if from_date:
4118 chandransh 1910
        query = query.filter(ReturnOrder.createdAt >from_date)
2697 chandransh 1911
    if to_date:
4118 chandransh 1912
        query = query.filter(ReturnOrder.createdAt < to_date)
2697 chandransh 1913
    return [return_order.to_thrift_object() for return_order in query.all()]
1914
 
5481 phani.kuma 1915
def get_all_return_orders(onlyNotProcessed, from_date, to_date):
1916
    query = ReturnOrder.query
1917
    if onlyNotProcessed:
1918
        query = query.filter_by(processedStatus = False)
1919
    if from_date:
1920
        query = query.filter(ReturnOrder.createdAt >= from_date)
1921
    if to_date:
1922
        query = query.filter(ReturnOrder.createdAt <= to_date)
1923
    return [return_order.to_thrift_object() for return_order in query.all()]
1924
 
2700 chandransh 1925
def get_return_order(id):
1926
    ret_order = ReturnOrder.get_by(orderId = id)
1927
    if ret_order is None:
1928
        raise TransactionServiceException(116, "No return order found for the given order id")
1929
    return ret_order.to_thrift_object()
1930
 
2697 chandransh 1931
def process_return(ret_order_id):
1932
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
1933
    if ret_order is None:
1934
        raise TransactionServiceException(116, "No return order found for the given order id")
1935
    ret_order.processedStatus = True
2701 chandransh 1936
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 1937
    session.commit()
1938
 
4757 mandeep.dh 1939
def update_orders_as_PORaised(itemIdQuantityMap, purchaseOrderId, warehouseId):
1940
    """
1941
    Updates orders as PO raised. Also updates purchase order id in orders. Pass a map of items mapped to
1942
    the quantities for which the PO is raised.
1943
 
1944
    Parameters:
1945
     - itemIdQuantityMap
1946
     - purchaseOrderId
1947
     - warehouseId
1948
    """
3451 chandransh 1949
    query = Order.query.with_lockmode("update").filter_by(warehouse_id=warehouseId)
4757 mandeep.dh 1950
    query = query.filter(or_(Order.status == OrderStatus.SUBMITTED_FOR_PROCESSING, Order.status == OrderStatus.INVENTORY_LOW))
2819 chandransh 1951
    query = query.filter_by(purchase_order_id=None)
1952
    query = query.order_by(Order.created_timestamp)
1953
    pending_orders = query.all()
4586 mandeep.dh 1954
 
1955
    for order in pending_orders:
4757 mandeep.dh 1956
        lineitem = order.lineitems[0]
1957
        if itemIdQuantityMap.has_key(lineitem.item_id):
1958
            if itemIdQuantityMap[lineitem.item_id] >= lineitem.quantity:
1959
                order.status = OrderStatus.LOW_INV_PO_RAISED
1960
                order.statusDescription = 'In Process'
1961
                order.purchase_order_id = purchaseOrderId
1962
                itemIdQuantityMap[lineitem.item_id] -= lineitem.quantity
4434 mandeep.dh 1963
 
2819 chandransh 1964
    session.commit()
1965
 
3451 chandransh 1966
def update_weight(order_id, weight):
3469 chandransh 1967
    '''
1968
    Update the weight of order
1969
    '''
3451 chandransh 1970
    order = get_order(order_id)
1971
    order.total_weight = weight
3469 chandransh 1972
    lineitem = order.lineitems[0]
1973
    lineitem.total_weight = weight
1974
    lineitem.unit_weight = weight
3451 chandransh 1975
 
3469 chandransh 1976
    session.commit()
1977
    return order
1978
 
1979
def change_product(order_id, item_id):
1980
    '''
1981
    Ship a product of a different color to the customer.
1982
    '''
1983
    order = get_order(order_id)
4662 rajveer 1984
    if order.status not in [OrderStatus.COD_VERIFICATION_PENDING, 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 1985
        raise TransactionServiceException(120, "This order has already been processed. Please seek help from engineering.")
1986
 
1987
    lineitem = order.lineitems[0]
3451 chandransh 1988
 
3469 chandransh 1989
    catalog_client = CatalogClient().get_client()
1990
 
1991
    old_item = catalog_client.getItem(lineitem.item_id)
1992
    item = catalog_client.getItem(item_id)
1993
    if old_item.catalogItemId != item.catalogItemId:
1994
        raise TransactionServiceException(121, "You can't ship a different item. You can only ship the same item in a different color.")
1995
 
5110 mandeep.dh 1996
    catalog_client.reserveItemInWarehouse(item_id, order.fulfilmentWarehouseId, lineitem.quantity)
1997
    __update_inventory_reservation(order)
3469 chandransh 1998
    #TODO: Check that this new item has the same price
1999
 
2000
    lineitem.item_id = item_id
2001
    lineitem.color = item.color
2002
 
3451 chandransh 2003
    session.commit()
3469 chandransh 2004
 
2005
    order = get_order(order_id)
3451 chandransh 2006
    return order
3469 chandransh 2007
 
2008
def change_warehouse(order_id, warehouse_id):
2009
    '''
2010
    Update the warehouse which will be used to fulfil this order.
2011
    '''
2012
    order = get_order(order_id)
4662 rajveer 2013
    if order.status not in [OrderStatus.COD_VERIFICATION_PENDING, 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 2014
        raise TransactionServiceException(117, "This order has already been processed. Please seek help from engineering.")
2015
 
2016
    if warehouse_id == order.warehouse_id:
2017
        raise TransactionServiceException(118, "You have selected the current warehouse again. Nothing to do")
2018
 
2019
    lineitem = order.lineitems[0]
2020
    catalog_client = CatalogClient().get_client()
2021
    try:
2022
        warehouse = catalog_client.getWarehouse(warehouse_id)
2023
    except:
2024
        raise TransactionServiceException(119, "No warehouse with id" + str(warehouse_id))
5110 mandeep.dh 2025
 
5147 mandeep.dh 2026
    if warehouse.billingWarehouseId is None:
2027
        raise TransactionServiceException(119, "Shifting of warehouse allowed to warehouse with billing support only")
5110 mandeep.dh 2028
 
5620 mandeep.dh 2029
    # If One gives a billing warehouse for warehouse shift, we should assign order to the GOOD warehouse
2030
    # present within it with maximum availability
2031
    if warehouse.id == warehouse.billingWarehouseId:
5147 mandeep.dh 2032
        warehouses = catalog_client.getWarehouses(None, InventoryType.GOOD, 0, 0, warehouse.id)
2033
        if warehouses:
2034
            itemInventory = catalog_client.getItemInventoryByItemId(lineitem.item_id)
2035
            warehouse = warehouses[0]
2036
            maxAvailability = 0
2037
            for goodWarehouse in warehouses:
2038
                if itemInventory.availability.has_key(goodWarehouse.id) and maxAvailability < itemInventory.availability[goodWarehouse.id]:
2039
                    warehouse = goodWarehouse
2040
                    maxAvailability = itemInventory.availability[goodWarehouse.id]
2041
 
2042
            # Use preferred vendor's warehouse if not available anywhere
2043
            if not maxAvailability:
2044
                item = catalog_client.getItem(lineitem.item_id)
2045
                if item.preferredVendor:
2046
                    for goodWarehouse in warehouses:
2047
                        if goodWarehouse.vendor.id == item.preferredVendor:
2048
                            warehouse = goodWarehouse
2049
        else:
2050
            raise TransactionServiceException(119, "Shifting of warehouse allowed to GOOD inventory type warehouse with billing support")
2051
 
5199 mandeep.dh 2052
    catalog_client.reserveItemInWarehouse(lineitem.item_id, warehouse.id, lineitem.quantity)
5110 mandeep.dh 2053
    __update_inventory_reservation(order)
2054
 
2055
    order.warehouse_id = warehouse.billingWarehouseId
5147 mandeep.dh 2056
    order.fulfilmentWarehouseId = warehouse.id
3469 chandransh 2057
    session.commit()
2058
    return order
3553 chandransh 2059
 
4647 rajveer 2060
def add_delay_reason(order_id, reason, further_delay, delayReasonText):
3553 chandransh 2061
    '''
3994 chandransh 2062
    Adds a delay reason to the order and updates the expected delivery time.
3553 chandransh 2063
    '''
2064
    order = get_order(order_id)
2065
    try:
3581 chandransh 2066
        order.delay_reason = DelayReason._VALUES_TO_NAMES[reason]
4647 rajveer 2067
        order.delayReasonText = delayReasonText
4009 chandransh 2068
        actual_delivery_delay = adjust_delivery_time(order.expected_delivery_time, further_delay)
2069
        order.expected_delivery_time = order.expected_delivery_time + datetime.timedelta(days=actual_delivery_delay)
4102 chandransh 2070
 
4842 rajveer 2071
        actual_shipping_delay = adjust_delivery_time(order.expected_shipping_time, further_delay)
2072
        order.expected_shipping_time = order.expected_shipping_time + datetime.timedelta(days=actual_shipping_delay)
4102 chandransh 2073
 
3553 chandransh 2074
        session.commit()
4008 mandeep.dh 2075
 
2076
        try:
2077
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
2078
            transaction_requiring_extra_processing.category = 'DELAYED_DELIVERY'
2079
            transaction_requiring_extra_processing.transaction_id = order.transaction_id
2080
            session.commit()
2081
        except Exception as e:
4065 mandeep.dh 2082
            print 'Could not persist transaction id: ' + str(order.transaction_id) + ' for further processing due to: ' + str(e)
4008 mandeep.dh 2083
 
3553 chandransh 2084
        return True
2085
    except:
3994 chandransh 2086
        print sys.exc_info()[0]
3553 chandransh 2087
        return False
3956 chandransh 2088
 
2089
def reconcile_cod_collection(collected_amount_map, xferBy, xferTxnId, xferDate):
2090
    unprocessed_awbs = {}
2091
    for awb, amount in collected_amount_map.iteritems():
2092
        try:
2093
            order = Order.query.filter_by(airwaybill_no=awb).one()
2094
        except NoResultFound:
2095
            unprocessed_awbs[awb] = "No order was found for the given AWB: " + awb
2096
            continue
2097
        except MultipleResultsFound:
2098
            unprocessed_awbs[awb] = "Multiple orders were found for the given AWB:" + awb
2099
            continue
2100
 
2101
        if order.cod_reconciliation_timestamp:
2102
            #This order has been processed already! This may be a re-run. Let's allow other orders to be processed.
2103
            continue
2104
 
2105
        if order.status < OrderStatus.DELIVERY_SUCCESS:
2106
            #Order has not been delivered yet. No way we can receive the payment.
2107
            unprocessed_awbs[awb] = "Payment has been received for order: " + str(order.id) + " before delivery reconciliation"
2108
            continue
2109
 
4252 rajveer 2110
        ##As per ticket #743 if amount difference less than 0.5 we should reconcile
2111
        if abs(amount - order.total_amount) > 0.5:
3956 chandransh 2112
            #Received amount is less than or more than the order amount. Mustn't let the user proceed.
2113
            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)
2114
            continue
2115
 
2116
        try:
2117
            payment_client = PaymentClient().get_client()
2118
            payment_client.partiallyCapturePayment(order.transaction.id, amount, xferBy, xferTxnId, xferDate)
2119
        except Exception:
2120
            unprocessed_awbs[awb] = "We were unable to partially capture payment for order id " + str(order.id) + ", AWB: " + awb
2121
            continue
2122
 
2123
        #Payment has been recorded now. We can update the order peacefully.
2124
        order.cod_reconciliation_timestamp = datetime.datetime.now()
2125
        session.commit()
3469 chandransh 2126
 
3956 chandransh 2127
    return unprocessed_awbs
4008 mandeep.dh 2128
 
2129
def get_transactions_requiring_extra_processing(category):
4065 mandeep.dh 2130
    """
2131
    Returns the list of transaction ids that require some extra processing and
2132
    which belong to a particular category. This is currently used by CRM
2133
    application. If no such transaction ids are present, it returns an empty list.
2134
    """
2135
    query = TransactionRequiringExtraProcessing.query
4008 mandeep.dh 2136
 
4065 mandeep.dh 2137
    if category is not None:
2138
        query = query.filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category))
4008 mandeep.dh 2139
 
4065 mandeep.dh 2140
    return [a.transaction_id for a in query.all()]
4008 mandeep.dh 2141
 
2142
def mark_transaction_as_processed(transactionId, category):
4065 mandeep.dh 2143
    """
2144
    Marks a particular transaction as processed for a particular cateogory.
2145
    It essentially deletes the transaction id record for a particular
2146
    processing type category (if present) from DB.
2147
    This is currently used by CRM application.
2148
    """
4008 mandeep.dh 2149
    TransactionRequiringExtraProcessing.query.filter_by(transaction_id = transactionId).filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category)).delete()
2150
    session.commit()
2151
 
4018 chandransh 2152
def get_item_wise_risky_orders_count():
2153
    """
2154
    Returns a map containing the number of risky orders keyed by item id. A risky order
2155
    is defined as one whose shipping date is about to expire.
2156
    """
2157
    item_wise_risky_orders_count = {}
4019 chandransh 2158
    shipping_cutoff_time = (datetime.datetime.now() + datetime.timedelta(days = 1)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4018 chandransh 2159
    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()
2160
    for order in orders:
2161
        for lineitem in order.lineitems:
2162
            quantity = lineitem.quantity
2163
            if item_wise_risky_orders_count.has_key(lineitem.item_id):
2164
                quantity = quantity + item_wise_risky_orders_count[lineitem.item_id]
2165
 
2166
            item_wise_risky_orders_count[lineitem.item_id] = quantity
2167
    return item_wise_risky_orders_count
2168
 
4324 mandeep.dh 2169
def update_shipment_address(order_id, address_id):
2170
    """
2171
    Updates shipment address of an order. Delivery and shipping date estimates
2172
    etc. are also updated here.
2173
 
2174
    Throws TransactionServiceException in case address change is not
2175
    possible due to certain reasons such as new pincode in address is
2176
    not serviceable etc.
2177
 
2178
    Parameters:
2179
     - orderId
2180
     - addressId
2181
    """
2182
    user_client = UserClient().get_client()
2183
    address     = user_client.getAddressById(address_id)
2184
    order       = get_order(order_id)
2185
 
4630 mandeep.dh 2186
    type = DeliveryType.PREPAID
2187
    if order.cod:
2188
        type = DeliveryType.COD
2189
 
4324 mandeep.dh 2190
    logistics_client = LogisticsClient().get_client()
4630 mandeep.dh 2191
    logistics_info = logistics_client.getLogisticsEstimation(order.lineitems[0].item_id, address.pin, type)
4324 mandeep.dh 2192
 
2193
    # Check for new estimate. Raise exception if new address is not serviceable
2194
    if logistics_info.deliveryTime == -1:
2195
        raise TransactionServiceException(1, 'Location not serviceable')
2196
 
2197
    # COD services are not available everywhere
2198
    if order.cod:
4868 rajveer 2199
        if not logistics_info.codAllowed:
4324 mandeep.dh 2200
            raise TransactionServiceException(2, 'COD service not available')
2201
 
5593 mandeep.dh 2202
    if logistics_info.providerId != order.logistics_provider_id:
2203
        logistics_info = logistics_client.getLogisticsInfo(address.pin, order.lineitems[0].item_id, type)
2204
        order.tracking_id = logistics_info.airway_billno
2205
        order.airwaybill_no = logistics_info.airway_billno
2206
        order.logistics_provider_id = logistics_info.providerId
2207
 
4324 mandeep.dh 2208
    current_time = datetime.datetime.now()
2209
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
2210
    logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
2211
 
2212
    order.customer_name         = address.name
2213
    order.customer_pincode      = address.pin
2214
    order.customer_address1     = address.line1
2215
    order.customer_address2     = address.line2
2216
    order.customer_city         = address.city
2217
    order.customer_state        = address.state
2218
    order.customer_mobilenumber = address.phone
2219
 
2220
    if order.cod:
2221
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
2222
    else:
2223
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
2224
 
2225
    order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
2226
    order.promised_shipping_time = order.expected_shipping_time
2227
    order.promised_delivery_time = order.expected_delivery_time 
2228
 
2229
    session.commit()
2230
 
4247 rajveer 2231
def mark_order_cancellation_request_received(orderId):
2232
    """
2233
    Mark order as cancellation request received. If customer sends request of cancellation of
2234
    a particular order, this method will be called. It will just change status of the order
2235
    depending on its current status. It also records the previous status, so that we can move
2236
    back to that status if cancellation request is denied.
2237
 
2238
    Parameters:
2239
     - orderId
2240
    """
4662 rajveer 2241
    status_transition = {OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 2242
             OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCEL_REQUEST_RECEIVED,
2243
             OrderStatus.INVENTORY_LOW : OrderStatus.CANCEL_REQUEST_RECEIVED,
4306 rajveer 2244
             OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2245
             OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCEL_REQUEST_RECEIVED,
2246
             OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 2247
             OrderStatus.ACCEPTED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2248
             OrderStatus.BILLED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2249
             OrderStatus.PAYMENT_FLAGGED : OrderStatus.CANCEL_REQUEST_RECEIVED
2250
             }
4662 rajveer 2251
 
2252
    order = get_order(orderId)
4247 rajveer 2253
    if order.status not in status_transition.keys():
2254
        raise TransactionServiceException(114, "This order can't be considered for cancellation")
2255
 
4662 rajveer 2256
 
4247 rajveer 2257
    order.previousStatus = order.status
2258
    order.status = OrderStatus.CANCEL_REQUEST_RECEIVED
2259
    order.statusDescription = "Cancellation request received from user"
2260
    session.commit()
2261
 
4662 rajveer 2262
def mark_order_as_lost_in_transit(orderId):
2263
    """
2264
    Parameters:
2265
     - orderId
2266
    """
2267
    order = get_order(orderId)
4910 phani.kuma 2268
    if order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
4662 rajveer 2269
        raise TransactionServiceException(115, "This order can't be marked as lost in transit")
2270
    order.status = OrderStatus.LOST_IN_TRANSIT
2271
    order.statusDescription = "Lost in Transit"
2272
    session.commit()
2273
 
4258 rajveer 2274
def mark_transaction_as_payment_flag_removed(transactionId):
4247 rajveer 2275
    """
4258 rajveer 2276
    If we and/or payment gateway has decided to accept the payment, this method needs to be called.
2277
    Changed transaction and all orders status to payment accepted.
4247 rajveer 2278
 
2279
    Parameters:
4258 rajveer 2280
     - transactionId
4247 rajveer 2281
    """
4258 rajveer 2282
    transaction = get_transaction(transactionId)
2283
    transaction.status = TransactionStatus.AUTHORIZED
2284
    for order in transaction.orders:
2285
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
2286
        order.statusDescription = "Submitted to warehouse"
4247 rajveer 2287
    session.commit()
2288
 
4259 anupam.sin 2289
def refund_transaction(transactionId, refundedBy, reason):
2290
    """
2291
    This method is called when a flagged payment is deemed unserviceable and the corresponding orders
2292
    need to be cancelled
2293
 
2294
    Parameters:
2295
     - transactionId
2296
    """
2297
    transaction = get_transaction(transactionId)
2298
    transaction.status = TransactionStatus.FAILED
2299
    for order in transaction.orders:
2300
        refund_order(order.id, refundedBy, reason)
2301
    session.commit()
2302
 
4247 rajveer 2303
def mark_order_cancellation_request_denied(orderId):
2304
    """
4283 anupam.sin 2305
    If we decide to not to cancel order, we will move the order to previous status.
4247 rajveer 2306
 
2307
    Parameters:
2308
     - orderId
2309
    """
2310
    order = get_order(orderId)
2311
    order.status = order.previousStatus
2312
    order.previousStatus = None
2313
    order.statusDescription = "Cancellation request denied"
2314
    session.commit()
2315
 
2316
def mark_order_cancellation_request_confirmed(orderId):
2317
    """
2318
    If we decide to to cancel order, CRM will call this method to move the status of order to
2319
    cancellation request confirmed. After this OM will be able to cancel the order.
2320
 
2321
    Parameters:
2322
     - orderId
2323
    """
2324
    order = get_order(orderId)
2325
    order.status = OrderStatus.CANCEL_REQUEST_CONFIRMED
2326
    order.statusDescription = "Cancellation request confirmed"
2327
    session.commit()
2328
 
4285 rajveer 2329
def accept_orders_for_item_id(itemId, inventory):
2330
    """
2331
    Marks the orders as ACCEPTED for the given itemId and inventory. It also updates the accepted timestamp. If the
2332
    given order is not a COD order, it also captures the payment if the same has not been captured.
2333
 
2334
    Parameters:
2335
     - itemId
2336
     - inventory
2337
    """
4938 rajveer 2338
    orders = Order.query.filter(Order.warehouse_id == 5).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 2339
    for order in orders:
4301 rajveer 2340
        if inventory > 0:
2341
            lineitem = order.lineitems[0]
2342
            if itemId == lineitem.item_id:
2343
                try:
2344
                    accept_order(order.id)
2345
                    inventory = inventory - lineitem.quantity
2346
                except:
2347
                    logging.info("Unable to accept the order")
2348
        else:
2349
            order_outofstock(order.id)
4285 rajveer 2350
    return
2351
 
4607 rajveer 2352
def get_slipped_sipping_date_orders():
4662 rajveer 2353
    return Order.query.filter(Order.status.in_(tuple([OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.ACCEPTED, OrderStatus.BILLED]))).filter(Order.promised_shipping_time <= datetime.datetime.now()).order_by(Order.promised_shipping_time).all()
4709 rajveer 2354
 
2355
def get_cancelled_orders(cancelDateFrom, cancelDateTo):
2356
    return Order.query.filter(Order.status == OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY).filter(Order.refund_timestamp >= cancelDateFrom).filter(Order.refund_timestamp <= cancelDateTo).all()
4607 rajveer 2357
 
4369 rajveer 2358
def mark_orders_as_po_raised(vendorId, itemId, quantity, estimate, isReminder):
2359
    if isReminder:
2360
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2361
    else:
2362
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2363
 
2364
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2365
    for order in orders:
2366
        lineitem = order.lineitems[0]
2367
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2368
            if estimate > 0:
2369
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
2370
            order.status = OrderStatus.LOW_INV_PO_RAISED
4362 rajveer 2371
            order.statusDescription = "PO Raised"
4303 rajveer 2372
            quantity = quantity - lineitem.quantity
2373
            store_inventory_action(order, itemId, HotspotAction.PO_RAISED, estimate, lineitem.quantity)
2374
            session.commit()
2375
 
4369 rajveer 2376
def mark_orders_as_reversal_initiated(vendorId, itemId, quantity, estimate, isReminder):
2377
    if isReminder:
2378
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2379
    else:
2380
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2381
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2382
    for order in orders:
2383
        lineitem = order.lineitems[0]
2384
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2385
            if estimate > 0:
2386
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
2387
            order.status = OrderStatus.LOW_INV_REVERSAL_IN_PROCESS
4362 rajveer 2388
            order.statusDescription = "Reversal Initiated"
4303 rajveer 2389
            quantity = quantity - lineitem.quantity
2390
            store_inventory_action(order, itemId, HotspotAction.REVERSAL_INITIATED, estimate, lineitem.quantity)
2391
            session.commit()
2392
 
4369 rajveer 2393
def mark_orders_as_not_available(vendorId, itemId, quantity, estimate, isReminder):
2394
    if isReminder:
2395
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2396
    else:
2397
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2398
 
2399
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2400
    for order in orders:
2401
        lineitem = order.lineitems[0]
2402
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2403
            order.status = OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT
4362 rajveer 2404
            order.statusDescription = "Not Available"
4303 rajveer 2405
            quantity = quantity - lineitem.quantity
2406
            store_inventory_action(order, itemId, HotspotAction.NOT_AVAILABLE, estimate, lineitem.quantity)
2407
            session.commit()
2408
 
2409
def store_inventory_action(order, itemId, hotspotAction, estimate, quantity):
4369 rajveer 2410
    orderInv = OrderInventory.get_by(order_id=order.id)
2411
    if not orderInv:
2412
        orderInv = OrderInventory()
2413
        orderInv.order = order
4303 rajveer 2414
    orderInv.hotspotAction = hotspotAction  
2415
    orderInv.estimate = estimate
2416
    orderInv.itemId = itemId
2417
    orderInv.timestamp = datetime.datetime.now()
2418
    orderInv.quantity = quantity
2419
 
4556 mandeep.dh 2420
'''    
4369 rajveer 2421
def mark_orders_as_timeout(vendorId):
2422
    ret_timeouts = {}
2423
    orderInvs = OrderInventory.query.all()
2424
    for orderInv in orderInvs:
2425
        if orderInv.timestamp +  timedelta(days=orderInv.estimate) < datetime.datetime.now():
2426
            if not ret_timeouts.has_key(orderInv.itemId):
2427
                timeout = TimeoutSummary()
2428
                ret_timeouts[orderInv.itemId] = timeout
2429
            else:
2430
                timeout = ret_timeouts.get(orderInv.itemId)
2431
            if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
2432
                if timeout.poRaised:
2433
                    timeout.poRaised += 1
2434
                else:
2435
                    timeout.poRaised = 1
2436
 
2437
                if timeout.poEstimate:
2438
                    timeout.poEstimate += orderInv.estimate
2439
                else:
2440
                    timeout.poEstimate = orderInv.estimate
2441
                orderInv.order.status = OrderStatus.LOW_INV_PO_RAISED_TIMEOUT
2442
                orderInv.order.statusDescription = "PO Raised Timeout"
2443
            elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
2444
                if timeout.reversalInitiated:
2445
                    timeout.reversalInitiated += 1
2446
                else:
2447
                    timeout.reversalInitiated = 1
2448
 
2449
                if timeout.reversalEstimate:
2450
                    timeout.reversalEstimate += orderInv.estimate
2451
                else:
2452
                    timeout.reversalEstimate = orderInv.estimate
2453
                orderInv.order.status = OrderStatus.LOW_INV_REVERSAL_TIMEOUT
2454
                orderInv.order.statusDescription = "Reversal Initiated Timeout"
2455
            else:
2456
                orderInv.delete()
2457
    session.commit()
2458
    return ret_timeouts
4556 mandeep.dh 2459
'''
2460
 
2461
 
2462
def mark_orders_as_timeout(vendorId):
2463
    ret_timeouts = {}
2464
    orderInvs = OrderInventory.query.all()
2465
    for orderInv in orderInvs:
2466
        if not ret_timeouts.has_key(orderInv.itemId):
2467
            timeout = TimeoutSummary()
2468
            ret_timeouts[orderInv.itemId] = timeout
2469
        else:
2470
            timeout = ret_timeouts.get(orderInv.itemId)
2471
        if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
2472
            if timeout.poRaised:
2473
                timeout.poRaised += 1
2474
            else:
2475
                timeout.poRaised = 1
2476
 
2477
            if timeout.poEstimate:
2478
                timeout.poEstimate = max(orderInv.estimate, timeout.poEstimate)
2479
            else:
2480
                timeout.poEstimate = orderInv.estimate
2481
        elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
2482
            if timeout.reversalInitiated:
2483
                timeout.reversalInitiated += 1
2484
            else:
2485
                timeout.reversalInitiated = 1
2486
 
2487
            if timeout.reversalEstimate:
2488
                timeout.reversalEstimate = max(orderInv.estimate, timeout.reversalEstimate)
2489
            else:
2490
                timeout.reversalEstimate = orderInv.estimate
2491
        orderInv.order.status = OrderStatus.INVENTORY_LOW
2492
        orderInv.order.statusDescription = "Low Inventory"
2493
        orderInv.delete()
2494
    session.commit()
2495
    return ret_timeouts
2496
 
4386 anupam.sin 2497
def get_order_for_awb(awb):
2498
    order = Order.get_by(airwaybill_no=awb)
2499
    if not order:
2500
        raise TransactionServiceException(108, "no such order")
2501
 
2502
    return order
4369 rajveer 2503
 
4910 phani.kuma 2504
def get_orders_for_provider_for_status(provider_id, order_status_list):
2505
    if not provider_id or not order_status_list:
4506 phani.kuma 2506
        raise TransactionServiceException(101, "bad provider id or order status")
4910 phani.kuma 2507
    doa_provider = False
2508
    for order_status in order_status_list:
2509
        if order_status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.RET_PICKUP_CONFIRMED]:
2510
            doa_provider = True
2511
    if doa_provider:
2512
        query = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4815 phani.kuma 2513
    else:
4910 phani.kuma 2514
        query = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4506 phani.kuma 2515
    return query.all()
4386 anupam.sin 2516
 
4600 varun.gupt 2517
def get_billed_orders_for_vendor(vendor_id, billing_date_from, billing_date_to):
5368 mandeep.dh 2518
    query = Order.query.filter(Order.status != OrderStatus.PAYMENT_PENDING)
2519
 
2520
    if vendor_id:
2521
        query = query.filter_by(vendorId = vendor_id)
2522
 
4600 varun.gupt 2523
    if billing_date_from:
2524
        query = query.filter(Order.billing_timestamp >= billing_date_from)
5368 mandeep.dh 2525
 
4600 varun.gupt 2526
    if billing_date_to:
2527
        query = query.filter(Order.billing_timestamp <= billing_date_to)
5368 mandeep.dh 2528
 
4600 varun.gupt 2529
    return query.all()
2530
 
5481 phani.kuma 2531
def get_billed_orders(vendor_id, onlyVendorNotPaid, billing_date_from, billing_date_to):
5386 phani.kuma 2532
    query = Order.query.filter(Order.billing_timestamp != None)
5481 phani.kuma 2533
 
2534
    if onlyVendorNotPaid:
5488 phani.kuma 2535
        query = query.filter_by(vendor_paid = False)
5481 phani.kuma 2536
 
5386 phani.kuma 2537
    if vendor_id != -1:
2538
        query = query.filter_by(vendorId = vendor_id)
2539
 
5481 phani.kuma 2540
    if billing_date_from:
2541
        query = query.filter(Order.billing_timestamp >= billing_date_from)
2542
 
2543
    if billing_date_to:
2544
        query = query.filter(Order.billing_timestamp <= billing_date_to)
2545
 
4885 varun.gupt 2546
    return query.all()
4875 varun.gupt 2547
 
4600 varun.gupt 2548
def save_bluedart_settlements(map_awb_and_amount):
2549
    payment_client = PaymentClient().get_client()
2550
 
2551
    for awb, amount in map_awb_and_amount.iteritems():
2552
        order = Order.get_by(airwaybill_no = awb)
2553
 
2554
        payment = payment_client.getSuccessfulPaymentForTxnId(order.transaction_id)
2555
        settlement = PaymentSettlement()
2556
        settlement.paymentId = payment.paymentId
2557
        settlement.paymentGatewayId = payment.gatewayId
2558
        settlement.netCollection = amount
2559
        session.commit()
2560
 
4905 varun.gupt 2561
def save_payment_settlements(settlementDate, paymentGatewayId, referenceId, serviceTax, otherCharges, netCollection):
5386 phani.kuma 2562
    originalOrderId = None
2563
    if paymentGatewayId == 4:
2564
        cod_order = Order.get_by(id = referenceId)
2565
        if cod_order.originalOrderId:
2566
            originalOrderId = cod_order.originalOrderId
2567
        else:
2568
            originalOrderId = referenceId
4600 varun.gupt 2569
    settlement = PaymentSettlement()
2570
    settlement.settlementDate = settlementDate
2571
    settlement.paymentGatewayId = paymentGatewayId
5386 phani.kuma 2572
    if originalOrderId is not None:
2573
        settlement.originalOrderId = originalOrderId
4905 varun.gupt 2574
    settlement.referenceId = referenceId
4600 varun.gupt 2575
    settlement.serviceTax = serviceTax
2576
    settlement.otherCharges = otherCharges
2577
    settlement.netCollection = netCollection
2578
    session.commit()
2579
 
5386 phani.kuma 2580
def get_settlement_for_Prepaid(reference_id, is_refund = False):
2581
    query = PaymentSettlement.query.filter_by(referenceId = reference_id).filter(PaymentSettlement.paymentGatewayId != 4)
4600 varun.gupt 2582
 
5189 varun.gupt 2583
    if is_refund:
2584
        query = query.filter(PaymentSettlement.netCollection < 0)
2585
    else:
2586
        query = query.filter(PaymentSettlement.netCollection > 0)
2587
 
5386 phani.kuma 2588
    return query.first()
2589
 
2590
def get_settlement_for_Cod(orderId, is_refund = False):
2591
    query = PaymentSettlement.query.filter_by(originalOrderId = orderId)
5382 varun.gupt 2592
 
5386 phani.kuma 2593
    if is_refund:
2594
        query = query.filter(PaymentSettlement.netCollection < 0)
2595
    else:
2596
        query = query.filter(PaymentSettlement.netCollection > 0)
2597
 
5189 varun.gupt 2598
    return query.first()
4600 varun.gupt 2599
 
2600
def save_ebs_settlement_summary(settlement_id, settlement_date, transaction_date_from, transaction_date_to, amount):
5551 phani.kuma 2601
    summary = EBSSettlementSummary.query.filter_by(settlementId = settlement_id).first()
5481 phani.kuma 2602
    if summary is None:
2603
        summary = EBSSettlementSummary()
2604
        summary.settlementId = settlement_id
2605
        summary.settlementDate = settlement_date
2606
        summary.transactionDateFrom = transaction_date_from
2607
        summary.transactionDateTo = transaction_date_to
2608
        summary.amount = amount
2609
        summary.detailsUploaded = False
2610
        session.commit()
4600 varun.gupt 2611
 
2612
def get_ebs_settlement_summaries():
2613
    summaries = EBSSettlementSummary.query.filter_by(detailsUploaded = False).order_by(EBSSettlementSummary.transactionDateFrom).all()
2614
    summary_map = {}
2615
 
2616
    for summary in summaries:
2617
        transactionDateFrom = str(summary.transactionDateFrom.year) + '-' + str(summary.transactionDateFrom.month) + '-' + str(summary.transactionDateFrom.day)
2618
        transactionDateTo = str(summary.transactionDateTo.year) + '-' + str(summary.transactionDateTo.month) + '-' + str(summary.transactionDateTo.day)
2619
 
2620
        summary_map[summary.settlementId] = "%s to %s" %(transactionDateFrom, transactionDateTo)
2621
 
2622
    return summary_map
2623
 
2624
def get_ebs_settlement_date(settlement_id):
2625
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
2626
 
2627
    if summary:
2628
        return summary.settlementDate
2629
 
2630
def mark_ebs_settlement_uploaded(settlement_id):
2631
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
2632
 
2633
    if summary:
2634
        summary.detailsUploaded = True
2635
        session.commit()
4715 varun.gupt 2636
 
2637
def get_settlements_by_date(settlement_date_from, settlement_date_to, is_refund):
2638
    query = PaymentSettlement.query
4600 varun.gupt 2639
 
4715 varun.gupt 2640
    if settlement_date_from:
2641
        query = query.filter(PaymentSettlement.settlementDate >= settlement_date_from)
2642
 
2643
    if settlement_date_to:
2644
        query = query.filter(PaymentSettlement.settlementDate <= settlement_date_to)
2645
 
4749 varun.gupt 2646
    if is_refund is True:
2647
        query = query.filter(PaymentSettlement.netCollection < 0.0)
2648
    else:
2649
        query = query.filter(PaymentSettlement.netCollection > 0.0)
4715 varun.gupt 2650
 
4749 varun.gupt 2651
    return query.all()
4715 varun.gupt 2652
 
2653
def get_reshipped_order_ids(order_ids):
2654
    reshipped_order_ids = []
2655
    return [order.new_order_id for order in Order.query.filter(Order.new_order_id.in_(order_ids)).all()]
2656
 
4749 varun.gupt 2657
def get_shipping_confirmation_email_body(order):
2658
 
2659
    html = """
2660
<html>
2661
<body>
2662
<div>
2663
    <p>Dear Customer,</p>
2664
    <p>
4885 varun.gupt 2665
        We are pleased to inform that we have shipped the order: $order_id for your product $product_name on $shipping_datetime. 
5139 varun.gupt 2666
        The shipment will be delivered to you via $courier_name Courier Service vide AWB# $awb.
4749 varun.gupt 2667
    </p>
2668
    <p>
2669
        Expected delivery date for your order is $expected_delivery_date. 
2670
        The product can be delivered to you between business hours of 10am to 6pm. 
2671
        You can login to your account on our site and under "Open Orders", please click the AWB and check the current shipment updates for your product.
2672
    </p>
2673
    <p>
5573 amit.gupta 2674
        For scheduling the delivery of your product at some specific timings, we recommend you to contact the helpline for $courier_name with your complete AWB#.
4749 varun.gupt 2675
    </p>
5139 varun.gupt 2676
    <p>$courier_name: $courier_phone</p>
4749 varun.gupt 2677
    <p>
2678
        Warm Regards,<br />
2679
        Saholic Team
2680
    </p>
4750 varun.gupt 2681
</div>
4749 varun.gupt 2682
</body>
2683
</html>
2684
    """
5573 amit.gupta 2685
    logistics_providers = {1: {'name': 'BlueDart', 'phone': '011-66111234'}, 2: {'name': 'Aramex', 'phone': '0124- 39419900'}, 3: {'name': 'Delhivery', 'phone' : '0124- 4212200'}}
5139 varun.gupt 2686
    provider_name = logistics_providers[order.logistics_provider_id]['name']
2687
    provider_phone = logistics_providers[order.logistics_provider_id]['phone']
2688
 
4749 varun.gupt 2689
    dt = datetime.datetime.strptime(str(order.shipping_timestamp), "%Y-%m-%d %H:%M:%S")
4885 varun.gupt 2690
    shipping_date = dt.strftime("%A, %d %B %Y %I:%M%p")
4749 varun.gupt 2691
    product = "%s %s %s" % (order.lineitems[0].brand, order.lineitems[0].model_name, order.lineitems[0].model_number)
4885 varun.gupt 2692
    new_expected_delivery_timestamp = datetime.datetime.now() + timedelta(adjust_delivery_time(datetime.datetime.now(), (order.promised_delivery_time - order.promised_shipping_time).days))
2693
    new_expected_delivery_date = new_expected_delivery_timestamp.strftime("%A, %d %B %Y")
5139 varun.gupt 2694
    info = dict(order_id = order.id, product_name = product, shipping_datetime = shipping_date, awb = order.airwaybill_no, expected_delivery_date = new_expected_delivery_date, courier_name = provider_name, courier_phone = provider_phone)
4885 varun.gupt 2695
    return Template(html).substitute(info)
4749 varun.gupt 2696
 
2697
def enqueue_shipping_confirmation_email(orders):
4915 varun.gupt 2698
    # Calling helper service on production
2699
    helperClient = HelperClient(host_key = "helper_service_server_host_prod").get_client()
5139 varun.gupt 2700
 
4749 varun.gupt 2701
    for order in orders:
2702
        try:
2703
            emailSubject = 'Shipping Details for Order ID: ' + str(order.id)
2704
            emailBody = get_shipping_confirmation_email_body(order)
4885 varun.gupt 2705
            helperClient.saveUserEmailForSending(order.customer_email, None, emailSubject, emailBody, '', 'ShippingConfirmation')
4749 varun.gupt 2706
        except Exception as e:
2707
            print e
2708
 
4915 varun.gupt 2709
def get_order_distribution_by_status(start_date, end_date):
5067 varun.gupt 2710
    query = session.query(Order.status, func.count(Order.id)).group_by(Order.status)
2711
    query = query.filter(Order.created_timestamp >= start_date)
2712
    query = query.filter(Order.created_timestamp <= end_date)
2713
    return query.all()
4915 varun.gupt 2714
 
5067 varun.gupt 2715
def get_order_ids_for_status(status, start_datetime, end_datetime):
2716
    query = Order.query.filter(Order.status == status)
2717
    query = query.filter(Order.created_timestamp >= start_datetime)
2718
    query = query.filter(Order.created_timestamp <= end_datetime)
2719
    return query.all()
2720
 
5099 varun.gupt 2721
def update_orders_as_paid_to_vendor(order_id):
5139 varun.gupt 2722
    paid_order = Order.get_by(id = order_id)
5099 varun.gupt 2723
 
5139 varun.gupt 2724
    if paid_order.originalOrderId is None:
2725
        paid_order.vendor_paid = True
5099 varun.gupt 2726
        session.commit()
5139 varun.gupt 2727
 
2728
        for order in Order.query.filter(Order.originalOrderId == order_id).all():
2729
            order.vendor_paid = True
2730
            session.commit()
2731
    else:
5208 varun.gupt 2732
        original_order_id = paid_order.originalOrderId
5139 varun.gupt 2733
 
5208 varun.gupt 2734
        for order in Order.query.filter(Order.originalOrderId == original_order_id).all():
5139 varun.gupt 2735
            order.vendor_paid = True
2736
            session.commit()
2737
 
2738
        original_order = Order.get_by(id = original_order_id)
2739
        if original_order:  original_order.vendor_paid = True
2740
        session.commit()
5348 anupam.sin 2741
 
2742
def update_COD_agent(agentEmailId, orderId):
2743
    order = Order.get_by(id=orderId)
2744
    if not order:
2745
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
2746
    agent = CodVerificationAgent()
2747
    agent.orderId = orderId
2748
    agent.verificationAgent = agentEmailId
2749
    session.commit()
2750
 
5099 varun.gupt 2751
 
5386 phani.kuma 2752
def update_order_only_as_paid_to_vendor(order_id):
2753
    paid_order = Order.get_by(id = order_id)
2754
    if paid_order is None:
2755
        raise TransactionServiceException(116, "No order found for the given order id")
2756
    paid_order.vendor_paid = True
2757
    session.commit()
2758
 
5208 varun.gupt 2759
def get_refunded_orders_marked_paid():
2760
    orderStatusGroup = OrderStatusGroups()
2761
    return Order.query.filter(Order.vendor_paid == 1).filter(Order.status.in_(orderStatusGroup.refundedOrders)).all()
2762
 
5447 anupam.sin 2763
def get_all_verification_agents(minOrderId, maxOrderId):
2764
    return CodVerificationAgent.query.filter(CodVerificationAgent.orderId >= minOrderId).filter(CodVerificationAgent.orderId <= maxOrderId).all()
2765
 
5527 anupam.sin 2766
def get_all_attributes_for_order_id(orderId):
2767
    return Attribute.query.filter(Attribute.orderId == orderId).all()
2768
 
2769
def set_order_attribute_for_transaction(transactionId, t_attribute):
2770
    for order in Order.query.filter_by(transaction_id = transactionId).all():
2771
        attribute = Attribute()
2772
        attribute.orderId = order.id
2773
        attribute.name = t_attribute.name
2774
        attribute.value = t_attribute.value
2775
        session.commit()
5593 mandeep.dh 2776
 
5558 mandeep.dh 2777
def accept_order_for_item(itemId, quantity, fulfilmentWarehouseId, billingWarehouseId):
2778
    catalogClient = CatalogClient().get_client()
2779
    inventory = catalogClient.getItemInventoryByItemId(itemId)
2780
    orders = Order.query.filter(Order.warehouse_id == billingWarehouseId).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()
2781
    for order in orders:
5593 mandeep.dh 2782
        lineitem = order.lineitems[0]
5558 mandeep.dh 2783
        if lineitem.item_id == itemId and lineitem.quantity <= quantity:
2784
            warehouse = catalogClient.getWarehouse(order.fulfilmentWarehouseId)
2785
            if not warehouse.billingWarehouseId and warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.THIRD_PARTY]:
5593 mandeep.dh 2786
                if inventory.availability.has_key(fulfilmentWarehouseId) and inventory.availability[fulfilmentWarehouseId] >= inventory.reserved[fulfilmentWarehouseId] + lineitem.quantity:
5558 mandeep.dh 2787
                    accept_order(order.id)
2788
                    quantity -= lineitem.quantity
5593 mandeep.dh 2789
                    if not quantity:
2790
                        break
5558 mandeep.dh 2791
 
766 rajveer 2792
def close_session():
2793
    if session.is_active:
2794
        print "session is active. closing it."
2783 chandransh 2795
        session.close()
3376 rajveer 2796
 
2797
def is_alive():
2798
    try:
2799
        session.query(Transaction.id).limit(1).one()
2800
        return True
2801
    except:
4343 varun.gupt 2802
        return False