Subversion Repositories SmartDukaan

Rev

Rev 4599 | Rev 4602 | 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
4501 mandeep.dh 16
from shop2020.clients.PurchaseClient import PurchaseClient
3499 mandeep.dh 17
from shop2020.clients.UserClient import UserClient
18
from shop2020.clients.WarehouseClient import WarehouseClient
4421 mandeep.dh 19
from shop2020.config.client.ConfigClient import ConfigClient
3499 mandeep.dh 20
from shop2020.model.v1 import order
21
from shop2020.model.v1.order.impl.DataService import Transaction, LineItem, \
4435 mandeep.dh 22
    Order, BatchNoGenerator, InvoiceIDGenerator, TransactionRequiringExtraProcessing, \
4600 varun.gupt 23
    OrderInventory, Alert, PaymentSettlement, EBSSettlementSummary
2687 chandransh 24
from shop2020.model.v1.order.impl.model.ReturnOrder import ReturnOrder
4541 mandeep.dh 25
from shop2020.thriftpy.generic.ttypes import ExceptionType
3499 mandeep.dh 26
from shop2020.thriftpy.logistics.ttypes import DeliveryType
4435 mandeep.dh 27
from shop2020.thriftpy.model.v1.catalog.ttypes import BillingType, \
28
    InventoryServiceException
29
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, \
30
    TransactionStatus, OrderStatus, DelayReason, ExtraTransactionProcessingType, \
31
    HotspotAction, TimeoutSummary
4421 mandeep.dh 32
from shop2020.thriftpy.payments.ttypes import PaymentException
4600 varun.gupt 33
from shop2020.thriftpy.purchase.ttypes import PurchaseOrder, LineItem as POLineItem
34
from shop2020.thriftpy.warehouse.ttypes import ScanType, WarehouseServiceException
3499 mandeep.dh 35
from shop2020.utils.EmailAttachmentSender import mail, get_attachment_part
855 rajveer 36
from shop2020.utils.Utils import to_py_date, to_java_date
4008 mandeep.dh 37
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
3499 mandeep.dh 38
from sqlalchemy.sql import func
39
from sqlalchemy.sql.expression import and_, or_, desc, not_, distinct
40
from string import Template
41
from textwrap import dedent
42
import datetime
43
import logging
44
import os
4421 mandeep.dh 45
import sys
4435 mandeep.dh 46
import time
4421 mandeep.dh 47
import traceback
3499 mandeep.dh 48
logging.basicConfig(level=logging.DEBUG)
104 ashish 49
 
3499 mandeep.dh 50
 
4019 chandransh 51
try:
52
    config_client = ConfigClient()
53
    PREPAID_SHIPPING_CUTOFF_TIME = int(config_client.get_property('delivery_cutoff_time'))
54
except Exception as ex:
55
    print "[ERROR] Unexpected config error:", sys.exc_info()[0]
56
    PREPAID_SHIPPING_CUTOFF_TIME = 15
3499 mandeep.dh 57
 
4019 chandransh 58
COD_SHIPPING_CUTOFF_TIME = 12
3499 mandeep.dh 59
 
2819 chandransh 60
PAGE_HEIGHT=defaultPageSize[1]
61
PAGE_WIDTH=defaultPageSize[0]
62
 
3499 mandeep.dh 63
ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT = {
4484 rajveer 64
        OrderStatus.RTO_RESHIPPED     :  3,
65
        OrderStatus.RTO_IN_TRANSIT : -5,
3499 mandeep.dh 66
        OrderStatus.DELIVERY_SUCCESS        :  1,
3578 mandeep.dh 67
        OrderStatus.DOA_CERT_INVALID        : -5
3499 mandeep.dh 68
}
69
 
104 ashish 70
def get_new_transaction():
71
    transaction = Transaction()
72
    transaction.createdOn = datetime.datetime.now()
738 chandransh 73
    transaction.status = TransactionStatus.INIT
104 ashish 74
    transaction.status_message = "New transaction"
483 rajveer 75
    return transaction
76
 
77
def create_order(t_order):
78
    order = Order()
79
    if t_order.warehouse_id:
80
        order.warehouse_id = t_order.warehouse_id
509 rajveer 81
    if t_order.logistics_provider_id:    
483 rajveer 82
        order.logistics_provider_id = t_order.logistics_provider_id
83
        order.airwaybill_no = t_order.airwaybill_no
84
        order.tracking_id = t_order.tracking_id
4009 chandransh 85
    if t_order.expected_shipping_time:
4019 chandransh 86
        order.expected_shipping_time = to_py_date(t_order.expected_shipping_time).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 87
        order.promised_shipping_time = order.expected_shipping_time
4009 chandransh 88
    if t_order.expected_delivery_time:
483 rajveer 89
        order.expected_delivery_time = to_py_date(t_order.expected_delivery_time)
4102 chandransh 90
        order.promised_delivery_time = order.expected_delivery_time
483 rajveer 91
    if t_order.customer_id:    
92
        order.customer_id = t_order.customer_id
93
        order.customer_name = t_order.customer_name
860 rajveer 94
        order.customer_city = t_order.customer_city
95
        order.customer_state = t_order.customer_state
483 rajveer 96
        order.customer_mobilenumber = t_order.customer_mobilenumber
97
        order.customer_pincode = t_order.customer_pincode
738 chandransh 98
        order.customer_address1 = t_order.customer_address1
99
        order.customer_address2 = t_order.customer_address2
483 rajveer 100
        order.customer_email = t_order.customer_email
101
    #new status and status description to be added    
716 rajveer 102
    order.status = t_order.status  
483 rajveer 103
    order.statusDescription = t_order.statusDescription
104
    order.total_amount = t_order.total_amount
105
    order.total_weight = t_order.total_weight
106
    if t_order.created_timestamp:
107
        order.created_timestamp = to_py_date(t_order.created_timestamp)
108
    else:
685 chandransh 109
        order.created_timestamp = datetime.datetime.now()
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
 
191
def change_transaction_status(transaction_id, new_status, description):
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
743 rajveer 208
            #After we got payment success, we will set logistics info also 
209
            logistics_client = LogisticsClient().get_client()
210
            #FIXME line item is only one now. If multiple will come, need to fix.
871 chandransh 211
            item_id = order.lineitems[0].item_id
3044 chandransh 212
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.PREPAID)
743 rajveer 213
 
1730 ankur.sing 214
            current_time = datetime.datetime.now()
215
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4009 chandransh 216
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
1730 ankur.sing 217
 
743 rajveer 218
            order.warehouse_id = logistics_info.warehouseId
219
            order.logistics_provider_id = logistics_info.providerId
220
            order.airwaybill_no = logistics_info.airway_billno
221
            order.tracking_id = order.airwaybill_no
4019 chandransh 222
            order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 223
            order.promised_shipping_time = order.expected_shipping_time
1730 ankur.sing 224
            order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 225
            order.promised_delivery_time = order.expected_delivery_time 
871 chandransh 226
 
3133 rajveer 227
            catalog_client = CatalogClient().get_client()
871 chandransh 228
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)
1351 varun.gupt 229
 
4316 anupam.sin 230
            try:
231
                item_pricing = catalog_client.getItemPricing(item_id, -1)
232
                order.lineitems[0].transfer_price = item_pricing.transferPrice
233
            except:
234
                print "Not able to get transfer price. Skipping"
3064 chandransh 235
    elif new_status == TransactionStatus.COD_IN_PROCESS:
236
        for order in transaction.orders:
237
            order.status = OrderStatus.INIT
238
            order.statusDescription = "Verification Pending"
239
            order.cod = True
240
            #After we got payment success, we will set logistics info also 
241
            logistics_client = LogisticsClient().get_client()
242
            #FIXME line item is only one now. If multiple will come, need to fix.
243
            item_id = order.lineitems[0].item_id
244
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.COD)
245
 
246
            current_time = datetime.datetime.now()
247
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4009 chandransh 248
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
3064 chandransh 249
 
250
            order.warehouse_id = logistics_info.warehouseId
251
            order.logistics_provider_id = logistics_info.providerId
252
            order.airwaybill_no = logistics_info.airway_billno
253
            order.tracking_id = order.airwaybill_no
4019 chandransh 254
            order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 255
            order.promised_shipping_time = order.expected_shipping_time
3064 chandransh 256
            order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 257
            order.promised_delivery_time = order.expected_delivery_time
3064 chandransh 258
 
3133 rajveer 259
            catalog_client = CatalogClient().get_client()
3064 chandransh 260
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)
261
 
4316 anupam.sin 262
            try:
263
                item_pricing = catalog_client.getItemPricing(item_id, -1)
264
                order.lineitems[0].transfer_price = item_pricing.transferPrice        
265
            except:
266
                print "Not able to get transfer price. Skipping"
483 rajveer 267
    session.commit()
3499 mandeep.dh 268
 
3530 mandeep.dh 269
    try:
270
        if new_status == TransactionStatus.COD_IN_PROCESS:
4008 mandeep.dh 271
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
272
            transaction_requiring_extra_processing.category = 'COD_VERIFICATION'
273
            transaction_requiring_extra_processing.transaction_id = transaction_id
274
            session.commit()
4247 rajveer 275
        elif new_status == TransactionStatus.FLAGGED:
276
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
277
            transaction_requiring_extra_processing.category = 'PAYMENT_FLAGGED'
278
            transaction_requiring_extra_processing.transaction_id = transaction_id
279
            session.commit()
3530 mandeep.dh 280
    except Exception as e:
4065 mandeep.dh 281
        print "Error inserting transaction Id: " + str(transaction_id) + " due to " + str(e)
3499 mandeep.dh 282
 
483 rajveer 283
    return True
284
 
3994 chandransh 285
def __get_holidays(start_time=0L, to_time=-1L):
286
    '''
287
    Get the list of all public holidays since start time including the
288
    day of start time if it's a holiday
289
    '''
290
    midnightTime = start_time.replace(hour=0, minute=0, second=0, microsecond=0)
1730 ankur.sing 291
    fromDate = to_java_date(midnightTime)
292
    logistics_client = LogisticsClient().get_client()
3994 chandransh 293
    #TODO: This list should be cached after the first call.
294
    #Calling logistics server is also unnecessary.
295
    holidays = logistics_client.getHolidays(fromDate, to_time)
296
    holidays = [to_py_date(holiday).date() for holiday in holidays]
297
    return holidays
298
 
299
 
300
def adjust_delivery_time(start_time, delivery_days):
301
    '''
302
    Returns the actual no. of days which will pass while 'delivery_days'
303
    no. of business days will pass since 'order_time'. 
304
    '''
305
    start_date = start_time.date()
306
    end_date = start_date + datetime.timedelta(days = delivery_days)
307
    holidays = __get_holidays(start_time)
1730 ankur.sing 308
 
3994 chandransh 309
    while start_date <= end_date:
310
        if start_date.weekday() == 6 or start_date in holidays:
1730 ankur.sing 311
            delivery_days = delivery_days + 1
3994 chandransh 312
            end_date = end_date + datetime.timedelta(days = 1)
4088 chandransh 313
        start_date = start_date + datetime.timedelta(days = 1)
3994 chandransh 314
 
1730 ankur.sing 315
    return delivery_days
316
 
1398 varun.gupt 317
def enqueue_transaction_info_email(transaction_id):
1262 varun.gupt 318
    transaction = get_transaction(transaction_id)
319
 
320
    html_header = """
321
<html>
322
<body>
323
<div>
324
    <p>
325
        Hello,<br /><br />
1742 rajveer 326
        Thanks for placing order with us. Following are the details of your order:
1262 varun.gupt 327
    </p>
328
    <div>
329
        Order Date: $order_date
1569 varun.gupt 330
    </div>
1262 varun.gupt 331
    <div>
332
        <table>
1569 varun.gupt 333
        <tr><td colspan="5"><hr /></td></tr>
334
        <tr><td colspan="5" align="left"><b>Order Details</b></td></tr>
335
        <tr><td colspan="5"><hr /></td></tr>
1262 varun.gupt 336
        <tr>
2050 varun.gupt 337
            <th width="100">Order No.</th>
338
            <th>Product</th>
339
            <th width="100">Quantity</th>
340
            <th width="100">Unit Price</th>
341
            <th width="100">Amount</th>
1262 varun.gupt 342
        </tr>
343
    """
1398 varun.gupt 344
    user_email = ""
1262 varun.gupt 345
    total_amount = 0.0
346
    html_table = ""
1569 varun.gupt 347
    order_date = datetime.datetime.now()
1262 varun.gupt 348
 
349
    for order in transaction.orders:
350
        order_date = order.created_timestamp
1398 varun.gupt 351
        user_email = order.customer_email
1569 varun.gupt 352
        html_tr = "<tr><td align='center'>" + str(order.id) + "</td>"
1262 varun.gupt 353
 
354
        for lineitem in order.lineitems:
2050 varun.gupt 355
            lineitem_total_price = round(lineitem.total_price, 2)
356
 
1276 chandransh 357
            html_tr += "<td>" + str(lineitem) + "</td>"
2050 varun.gupt 358
            html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"
359
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"
360
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"
361
            total_amount += lineitem_total_price
1262 varun.gupt 362
            html_table += html_tr
2050 varun.gupt 363
 
1262 varun.gupt 364
    html_footer = """
365
        <tr><td colspan=5>&nbsp;</td></tr>
1565 varun.gupt 366
        <tr><td colspan=5><hr /></td></tr>
1262 varun.gupt 367
        <tr>
368
            <td colspan=4>Total Amount</td>
2050 varun.gupt 369
            <td> Rs. $total_amount</td>
1262 varun.gupt 370
        </tr>
371
        </table>
1569 varun.gupt 372
    </div>
1262 varun.gupt 373
    <p>
374
        Best Wishes,<br />
375
        Saholic Team
376
    </p>
377
</div>
378
</body>
379
</html>
380
    """
1398 varun.gupt 381
 
1569 varun.gupt 382
    dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")
1565 varun.gupt 383
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
384
 
1262 varun.gupt 385
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date))
2050 varun.gupt 386
    email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount))
1262 varun.gupt 387
 
1351 varun.gupt 388
    try:
389
        helper_client = HelperClient().get_client()
1398 varun.gupt 390
        helper_client.saveUserEmailForSending(user_email, "", "Saholic - Order Details", email_header + html_table + email_footer, str(transaction_id), "TransactionInfo")
1351 varun.gupt 391
        return True
392
    except Exception as e:
393
        print e
394
        return False
1262 varun.gupt 395
 
483 rajveer 396
def get_order(order_id):
397
    order = Order.get_by(id=order_id)
398
    if not order:
399
        raise TransactionServiceException(108, "no such order")
400
 
401
    return order
402
 
3014 chandransh 403
def get_orders_for_customer(customer_id, from_date, to_date, statuses):
483 rajveer 404
    if not customer_id:
405
        raise TransactionServiceException(101, "bad customer id")
406
    query = Order.query.filter(Order.customer_id == customer_id)
3014 chandransh 407
    if statuses:
408
        query = query.filter(Order.status.in_(tuple(statuses)))
483 rajveer 409
    if from_date:
410
        query = query.filter(Order.created_timestamp >from_date)
411
    if to_date:
412
        query = query.filter(Order.created_timestamp < to_date)
413
    return query.all()
414
 
1528 ankur.sing 415
def get_order_for_customer(order_id, customer_id):
416
    if not customer_id:
417
        raise TransactionServiceException(101, "bad customer id")
418
    order = get_order(order_id)
419
    if order.customer_id != customer_id:
420
        raise TransactionServiceException(108, "order: " + str(order_id) + " does not belong to customer: " + str(customer_id))
421
    return order
422
 
483 rajveer 423
def get_all_orders(status, from_date, to_date, warehouse_id):
424
    if not warehouse_id:
425
        raise TransactionServiceException(101, "bad warehouse id")
426
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
427
    if status:
428
        query = query.filter(Order.status == status)
429
    if from_date:
430
        query = query.filter(Order.created_timestamp >from_date)
431
    if to_date:
432
        query = query.filter(Order.created_timestamp < to_date)
433
    return query.all()
434
 
4133 chandransh 435
def get_orders_in_batch(statuses=[], offset=0, limit=0, warehouse_id=None):
4296 rajveer 436
    query = Order.query
437
    if warehouse_id:
438
        query = query.filter(Order.warehouse_id == warehouse_id)
4133 chandransh 439
    if statuses:
440
        query = query.filter(Order.status.in_(statuses))
441
    query = query.offset(offset)
442
    if limit:
443
        query = query.limit(limit)
444
    return query.all()
445
 
446
def get_order_count(statuses=[], warehouse_id=None):
447
    if not warehouse_id:
448
        raise TransactionServiceException(101, "bad warehouse id")
449
    query = session.query(func.count(Order.id)).filter(Order.warehouse_id == warehouse_id)
450
    if statuses:
451
        query = query.filter(Order.status.in_(statuses))
452
    return query.scalar()
453
 
1382 varun.gupt 454
def get_returnable_orders_for_customer(customer_id, limit = None):
455
    if not customer_id:
456
        raise TransactionServiceException(101, "bad customer id")
457
 
458
    query = Order.query.filter(Order.customer_id == customer_id)
459
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
460
    query = query.filter(Order.status != OrderStatus.REJECTED)
461
    query = query.filter(Order.status > OrderStatus.SHIPPED_FROM_WH)
462
    query = query.filter(or_(Order.status < OrderStatus.DELIVERY_SUCCESS, Order.delivery_timestamp < datetime.datetime.now() + datetime.timedelta(hours = 48)))
463
    orders = query.all()
464
    order_ids = [order.id for order in orders]
465
    return order_ids
466
 
467
def get_cancellable_orders_for_customer(customer_id, limit = None):
468
    if not customer_id:
469
        raise TransactionServiceException(101, "bad customer id")
470
 
471
    query = Order.query.filter(Order.customer_id == customer_id)
4343 varun.gupt 472
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
1382 varun.gupt 473
    query = query.filter(Order.status != OrderStatus.REJECTED)
4288 anupam.sin 474
    query = query.filter(Order.status <= OrderStatus.BILLED)
1382 varun.gupt 475
    orders = query.all()
476
    return [order.id for order in orders]
477
 
995 varun.gupt 478
def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):
479
    if not warehouse_id:
480
        raise TransactionServiceException(101, "bad warehouse id")
481
 
482
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
483
 
484
    if status:
485
        query = query.filter(Order.status == status)
486
 
487
    if start_billing_date:
488
        query = query.filter(Order.billing_timestamp >= start_billing_date)
489
 
490
    if end_billing_date:
491
        query = query.filter(Order.billing_timestamp <= end_billing_date)
492
 
493
    return query.all()
494
 
3451 chandransh 495
def get_orders_by_shipping_date(from_shipping_date, to_shipping_date, provider_id, warehouse_id, cod):
496
    query = Order.query.filter(Order.cod == cod)
3427 chandransh 497
 
498
    if warehouse_id and warehouse_id != -1:
499
        query = query.filter(Order.warehouse_id == warehouse_id)
500
 
501
    if provider_id and provider_id != -1:
502
        query = query.filter(Order.logistics_provider_id == provider_id)
503
 
504
    if from_shipping_date:
505
        query = query.filter(Order.shipping_timestamp >= from_shipping_date)
506
 
507
    if to_shipping_date:
508
        query = query.filter(Order.shipping_timestamp <= to_shipping_date)
509
 
510
    query = query.order_by(Order.airwaybill_no)
511
 
512
    return query.all()
513
 
1528 ankur.sing 514
def get_orders_for_transaction(transaction_id, customer_id):
515
    orders = Order.query.filter_by(transaction_id=transaction_id, customer_id=customer_id).all()
516
 
1208 chandransh 517
    if not orders:
518
        raise TransactionServiceException(101, "No order for the transaction")
519
    return orders
520
 
1405 ankur.sing 521
def get_undelivered_orders(provider_id, warehouse_id):
522
    query = Order.query
523
    if provider_id != -1:
524
        query = query.filter_by(Order.logistics_provider_id == provider_id)
525
    if warehouse_id != -1:
526
        query = query.filter(Order.warehouse_id == warehouse_id)
527
    query = query.filter(and_(Order.status != OrderStatus.DELIVERY_SUCCESS, Order.status != OrderStatus.FAILED, \
528
                              Order.status > OrderStatus.SHIPPED_FROM_WH))
1479 ankur.sing 529
    #Get last midnight time instead of current time as courier company would have sent the 
530
    #delivery records updated at least till midnight and not by the current time.
531
    time_format = "%Y-%m-%d %H:%M:%S.%f"
532
    t = time.strptime(str(datetime.datetime.now()), time_format)
533
    midnightTime = datetime.datetime(*t[:3])
534
    query = query.filter(Order.expected_delivery_time < midnightTime)
1405 ankur.sing 535
    orders = query.all()
536
    return orders
537
 
1208 chandransh 538
def get_line_items_for_order(order_id):
539
    query = LineItem.query.filter(LineItem.order_id == order_id)
540
    return query.all()
541
 
483 rajveer 542
def change_order_status(self, orderId, status, description):
543
    order = get_order(orderId)
544
    order.status = status
545
    order.statusDescription = description
546
    session.commit()
3578 mandeep.dh 547
    update_trust_level(order)
548
    return True
3499 mandeep.dh 549
 
3578 mandeep.dh 550
def update_trust_level(order):
3530 mandeep.dh 551
    try:
3578 mandeep.dh 552
        trust_level_delta = 0
553
        if order.cod == True:
554
            trust_level_delta = ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT.get(order.status, 0)
555
 
3530 mandeep.dh 556
        if (trust_level_delta != 0):
557
            user_client = UserClient().get_client()
558
            user_client.increaseTrustLevel(order.customer_id, trust_level_delta)
559
    except Exception as e:
560
        print e
3499 mandeep.dh 561
 
483 rajveer 562
    return True
3064 chandransh 563
 
564
def verify_order(self, orderId):
565
    logging.info("Verifying order no: " + str(orderId))
566
    order = get_order(orderId)
567
    if order.status == OrderStatus.INIT:
568
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
569
        order.statusDescription = "Submitted for processing"
570
        order.verification_timestamp = datetime.datetime.now()
571
        session.commit()
572
        logging.info("Successfully verified order no: " + str(orderId))
573
        return True
574
    else:
575
        logging.warning("Verify called for order no." + str(orderId) +" which is not in verification pending state");
576
        return False
577
 
4285 rajveer 578
def accept_order(orderId):
3064 chandransh 579
    logging.info("Accepting order no: " + str(orderId))
921 rajveer 580
    order = get_order(orderId)
4306 rajveer 581
    if order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3064 chandransh 582
        if not order.cod:
583
            if order.transaction.status == TransactionStatus.AUTHORIZED:
4421 mandeep.dh 584
                __capture_txn(order)
3010 chandransh 585
        order.status = OrderStatus.ACCEPTED
586
        order.statusDescription = "Order Accepted"
587
        order.accepted_timestamp = datetime.datetime.now()
588
        session.commit()
3064 chandransh 589
        logging.info("Successfully accepted the order no.:" + str(orderId))
3010 chandransh 590
        return True
591
    else:
3064 chandransh 592
        logging.warning("Accept called for the unacceptable order: " + str(orderId))
3010 chandransh 593
        return False
921 rajveer 594
 
4421 mandeep.dh 595
def __capture_txn(order):
596
    txnId = order.transaction_id
3010 chandransh 597
    logging.info("Capturing payment for merchant txn:" + str(txnId))
4421 mandeep.dh 598
    try:
599
        payment_client = PaymentClient().get_client()
600
        capture_result = payment_client.capturePayment(txnId)
601
        if capture_result:
602
            logging.info("Successfully captured payment for merchant txn:" + str(txnId))
603
            change_transaction_status(txnId, TransactionStatus.IN_PROCESS, "Payment received")
604
        else:
605
            raise TransactionServiceException(115, "Payment capture failed.")
606
    except PaymentException as e:
607
        if e.error_code == 106:
608
            order.status = OrderStatus.CAPTURE_IN_PROCESS
609
            session.commit()
610
            raise TransactionServiceException(122, "Unable to capture payment due to connection issue.")
611
        else:
612
            raise TransactionServiceException(115, "Payment capture failed.")
3010 chandransh 613
 
4285 rajveer 614
def add_billing_details(orderId, invoice_number, imeiNumber, itemNumber, billedBy, jacketNumber, billingType, vendorId):
615
    if jacketNumber is None or jacketNumber <= 0:
2783 chandransh 616
        raise TransactionServiceException(110, "Invalid jacket number")
617
 
4285 rajveer 618
    if billedBy is None or billedBy.strip() == "":
2783 chandransh 619
        raise TransactionServiceException(110, "Invalid Biller")
620
 
1149 chandransh 621
    order = Order.get_by(id=orderId)
622
    if not order:
2783 chandransh 623
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
624
 
4283 anupam.sin 625
    if order.status == OrderStatus.ACCEPTED:
4285 rajveer 626
        order.jacket_number = jacketNumber
627
        if billingType == BillingType.OURS:
628
            if itemNumber is None or itemNumber.strip() == "":
4283 anupam.sin 629
                raise TransactionServiceException(110, "Invalid item number")
630
 
631
            order.invoice_number = get_next_invoice_number()
632
            lineitem = order.lineitems[0]
4285 rajveer 633
            if lineitem.productGroup == "Handsets" and imeiNumber <= 0:
4283 anupam.sin 634
                raise TransactionServiceException(110, "No IMEI number supplied for a handset.")
4285 rajveer 635
            lineitem.item_number = itemNumber
636
            if imeiNumber > 0:
637
                lineitem.imei_number = str(imeiNumber)
4283 anupam.sin 638
        else:
639
            order.invoice_number = invoice_number
640
 
2842 chandransh 641
        order.status = OrderStatus.BILLED
642
        order.statusDescription = "Order Billed"
643
        order.billing_timestamp = datetime.datetime.now()
4285 rajveer 644
        order.billed_by = billedBy
2842 chandransh 645
        lineitem = order.lineitems[0]
4283 anupam.sin 646
        item_id = lineitem.item_id
4435 mandeep.dh 647
 
648
        # Not letting the billing process fail in cases where we are unable to 
649
        # fill in transfer price
650
        item_pricing = None
651
        try:
652
            catalog_client = CatalogClient().get_client()
653
            item_pricing = catalog_client.getItemPricing(item_id, vendorId)
654
        except InventoryServiceException as e:
655
            print sys.exc_info()[0]
656
            print e.message
657
 
4285 rajveer 658
        order.vendorId = vendorId
4283 anupam.sin 659
        lineitems = order.lineitems
660
        for lineitem in lineitems:
661
            catalog_client.reduceReservationCount(item_id, order.warehouse_id, lineitem.quantity)
4435 mandeep.dh 662
 
663
        # Putting NULL as transfer price for cases where its missing
4541 mandeep.dh 664
        if item_pricing is not None:
4435 mandeep.dh 665
            order.lineitems[0].transfer_price = item_pricing.transferPrice
4365 mandeep.dh 666
 
667
        # For Mahipal warehouse, we need to scan out items for every billed order
4576 mandeep.dh 668
        if order.warehouse_id == 7:
4365 mandeep.dh 669
            try:
670
                warehouse_client = WarehouseClient().get_client()
4599 mandeep.dh 671
                inventoryItem = warehouse_client.getInventoryItem(str(imeiNumber))
4541 mandeep.dh 672
                if (inventoryItem.itemId != item_id):
673
                    item = catalog_client.getItem(inventoryItem.itemId)
674
                    lineitem = order.lineitems[0]
675
                    scanItemString = " ".join([item.brand, item.modelName, item.modelNumber, item.color])
676
                    lineItemString = " ".join([lineitem.brand, lineitem.model_name, lineitem.model_number, lineitem.color])
677
                    raise TransactionServiceException(110, 'Trying to scan ' + scanItemString + ' instead of ' + lineItemString)
4599 mandeep.dh 678
                inventoryItem = warehouse_client.scanSerializedItemForOrder(str(imeiNumber), ScanType.SALE, orderId, order.warehouse_id)
4554 mandeep.dh 679
                lineitem.transfer_price = inventoryItem.unitPrice
680
                order.vendorId = inventoryItem.supplierId
4541 mandeep.dh 681
            except WarehouseServiceException as e:
4365 mandeep.dh 682
                print sys.exc_info()[0]
4541 mandeep.dh 683
                print 'Could not scan out orders due to: ' + e.message
684
                if e.exceptionType == ExceptionType.ILLEGAL_ARGUMENTS:
685
                    raise TransactionServiceException(110, e.message)
4365 mandeep.dh 686
 
4541 mandeep.dh 687
        session.commit()
4283 anupam.sin 688
        return True
689
    else:
690
        return False
1149 chandransh 691
 
4579 rajveer 692
def add_invoice_number(orderId, invoiceNumber):
693
    order = Order.get_by(id=orderId)
694
    if not order:
695
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
696
 
697
    if order.status == OrderStatus.ACCEPTED:
698
        order.invoice_number = invoiceNumber
699
    session.commit()
700
 
1220 chandransh 701
def batch_orders(warehouseId):
702
    if not warehouseId:
703
        raise TransactionServiceException(101, "bad warehouse id")
1225 chandransh 704
 
705
    batchno_generator = BatchNoGenerator()
706
    session.commit()
1220 chandransh 707
    query = Order.query.filter_by(warehouse_id=warehouseId)
4592 mandeep.dh 708
    query = query.filter(Order.status == OrderStatus.LOW_INV_PO_RAISED)
1220 chandransh 709
    query = query.order_by(Order.created_timestamp)
710
    pending_orders = query.all()
1225 chandransh 711
 
1220 chandransh 712
    serial_no = 1
713
    for order in pending_orders:
1276 chandransh 714
        order.batchNo = batchno_generator.id
1220 chandransh 715
        order.serialNo = serial_no
716
        serial_no += 1
717
    session.commit() 
718
    pending_orders = query.all()
719
    return pending_orders
720
 
721
def order_outofstock(orderId):
1911 chandransh 722
    '''
723
    Mark order as out of stock
724
    '''
1220 chandransh 725
    order = get_order(orderId)
726
    order.status = OrderStatus.INVENTORY_LOW
727
    order.statusDescription = "Low Inventory"
728
    order.outofstock_timestamp = datetime.datetime.now()
729
    session.commit()
730
    return True
731
 
3064 chandransh 732
def mark_orders_as_manifested(warehouse_id, provider_id, cod):
759 chandransh 733
    try:
3064 chandransh 734
        orders = Order.query.filter_by(warehouse_id = warehouse_id, logistics_provider_id = provider_id, status = OrderStatus.BILLED, cod = cod).all()
759 chandransh 735
        for order in orders:
4410 rajveer 736
            order.status = OrderStatus.MANIFESTED
737
            order.statusDescription = "Order manifested"
738
        session.commit()
739
        return True
740
    except:
741
        return False
742
 
743
def mark_orders_as_shipped_from_warehouse(warehouse_id, provider_id, cod):
744
    try:
745
        current_timestamp = datetime.datetime.now()
746
        orders = Order.query.filter_by(warehouse_id = warehouse_id, logistics_provider_id = provider_id, status = OrderStatus.MANIFESTED, cod = cod).all()
747
        for order in orders:
759 chandransh 748
            order.status = OrderStatus.SHIPPED_FROM_WH
987 chandransh 749
            order.statusDescription = "Order shipped from warehouse"
986 chandransh 750
            order.shipping_timestamp = current_timestamp
759 chandransh 751
        session.commit()
752
        return True
753
    except:
754
        return False
4410 rajveer 755
 
1113 chandransh 756
def mark_orders_as_picked_up(provider_id, pickup_details):
757
    for awb, pickup_timestamp in pickup_details.iteritems():
1135 chandransh 758
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 759
        if order == None or order.status != OrderStatus.SHIPPED_FROM_WH:
2220 chandransh 760
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
761
            continue
1113 chandransh 762
        order.status = OrderStatus.SHIPPED_TO_LOGST
763
        order.statusDescription = "Order picked up by Courier Company"
1246 chandransh 764
        order.pickup_timestamp = pickup_timestamp
1113 chandransh 765
    session.commit()
1217 chandransh 766
 
1132 chandransh 767
    current_time = datetime.datetime.now()
768
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1246 chandransh 769
    from_datetime = to_datetime - datetime.timedelta(2)
1132 chandransh 770
    orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.SHIPPED_FROM_WH).filter(Order.shipping_timestamp >= from_datetime).filter(Order.shipping_timestamp <= to_datetime).all()
1113 chandransh 771
    return orders_not_picked_up
772
 
1132 chandransh 773
def mark_orders_as_delivered(provider_id, delivered_orders):
774
    for awb, detail in delivered_orders.iteritems():
1135 chandransh 775
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 776
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
1911 chandransh 777
            continue
778
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1132 chandransh 779
        order.status = OrderStatus.DELIVERY_SUCCESS
780
        order.statusDescription = "Order delivered"
781
        order.delivery_timestamp, order.receiver = detail.split('|')
3578 mandeep.dh 782
        update_trust_level(order)
1132 chandransh 783
    session.commit()
784
 
1135 chandransh 785
def mark_orders_as_failed(provider_id, returned_orders):
786
    for awb, detail in returned_orders.iteritems():
787
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 788
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
789
            continue
790
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
4484 rajveer 791
        order.status = OrderStatus.RTO_IN_TRANSIT
1135 chandransh 792
        order.delivery_timestamp, reason = detail.split('|')
793
        order.statusDescription = "Order Returned to Origin:" + reason
3578 mandeep.dh 794
        update_trust_level(order)
1911 chandransh 795
    session.commit()
1135 chandransh 796
 
1246 chandransh 797
def update_non_delivery_reason(provider_id, undelivered_orders):
798
    for awb, reason in undelivered_orders.iteritems():
799
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
800
        if order == None:
2684 chandransh 801
            continue
802
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1246 chandransh 803
        order.statusDescription = reason
804
    session.commit()
4581 phani.kuma 805
 
806
    current_time = datetime.datetime.now()
807
    today_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
808
    upto_datetime = today_datetime - datetime.timedelta(4)
809
    orders_not_delivered = 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 <= upto_datetime, Order.pickup_timestamp <= upto_datetime)).all()
810
    return orders_not_delivered
1246 chandransh 811
 
4444 rajveer 812
def get_alerts(type, warehouseId, status, timestamp):
813
    query = Alert.query.filter(Alert.warehouseId == warehouseId)
814
    if type != -1 :
815
        query = query.filter(Alert.type == type)
816
    if status != -1 :
817
        query = query.filter(Alert.status == status)
4394 rajveer 818
    if timestamp:
819
        query = query.filter(Alert.timestamp >= to_py_date(timestamp))
4412 rajveer 820
    query = query.order_by(desc(Alert.timestamp))
483 rajveer 821
    return query.all()
822
 
4447 rajveer 823
def add_alert(type, warehouseId, description):
4394 rajveer 824
    alert = Alert()
825
    alert.type = type
826
    alert.status = 1
827
    alert.description = description
828
    alert.timestamp = datetime.datetime.now()
4447 rajveer 829
    alert.warehouseId = warehouseId
4444 rajveer 830
    session.commit()
766 rajveer 831
 
4444 rajveer 832
def mark_alerts_as_seen(warehouseId):
833
    query = Alert.query.filter(Alert.warehouseId == warehouseId).filter(Alert.status == 1)
834
    alerts = query.all()
835
    for alert in alerts:
836
        alert.status = 0    
837
    session.commit()
838
 
1596 ankur.sing 839
def get_valid_order_count():
2851 chandransh 840
    '''
841
    Returns the number of orders which we processed. The reshipped orders are not
842
    counted since there'll always be a new compensating order present.
843
    '''
4484 rajveer 844
    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.CANCELED)))).count()
1596 ankur.sing 845
 
1627 ankur.sing 846
def get_cust_count_with_successful_txn():
2851 chandransh 847
    '''
848
    Returns the number of distinct customers who have done successful transactions.
849
    It uses the sqlalchemy func module to construct an efficient query.
850
    '''
851
    return session.query(func.count(distinct(Order.customer_id))).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).scalar()
1627 ankur.sing 852
 
1730 ankur.sing 853
def get_valid_orders_amount_range():
2851 chandransh 854
    '''
855
    Returns a list containing the minimum and maximum amount across all
856
    orders placed with us. No need to consider reshippped orders for min/max
857
    amount of orders.
858
    '''
859
    return session.query(func.min(Order.total_amount), func.max(Order.total_amount)).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).one()
1627 ankur.sing 860
 
1886 ankur.sing 861
def get_valid_orders(limit):
2851 chandransh 862
    '''
863
    Returns the last limit number of valid orders placed with us. Ignored the
864
    limit if it's passed as 0. Raises an excpetion if the supplied limit is 
865
    less than 0. 
866
    '''
867
    if limit < 0:
868
        raise TransactionServiceException(101, "Invalid argument limit " + limit)
3072 chandransh 869
    query = Order.query.filter(Order.status >= OrderStatus.INIT)
1886 ankur.sing 870
    query = query.order_by(desc(Order.created_timestamp))
2851 chandransh 871
    if limit != 0:
1886 ankur.sing 872
        query = query.limit(limit)
873
    return query.all()
874
 
2783 chandransh 875
def get_next_invoice_number():
876
    entity_id = InvoiceIDGenerator.query.with_lockmode("update").one()
877
    invoice_number = entity_id.id + 1
878
    entity_id.id = invoice_number
879
    return invoice_number
880
 
2536 chandransh 881
def toggle_doa_flag(order_id):
882
    order = get_order(order_id)
883
    if(order.doaFlag):
884
        order.doaFlag = False
885
    else:
886
        order.doaFlag = True
887
    session.commit()
888
    return order.doaFlag
889
 
4454 rajveer 890
def mark_order_doa_request_received(orderId):
891
    order = get_order(orderId)
892
    if order.status != OrderStatus.DELIVERY_SUCCESS:
893
        return False
894
    order.status = OrderStatus.DOA_REQUEST_RECEIVED
4459 rajveer 895
    order.statusDescription = "DOA Request Received"
4454 rajveer 896
    session.commit()
897
    return True
898
 
899
def mark_order_doa_request_authorized(orderId, isAuthorized):
900
    order = get_order(orderId)
901
    if order.status != OrderStatus.DOA_REQUEST_RECEIVED:
902
        return False
903
    if isAuthorized:
904
        order.status = OrderStatus.DOA_REQUEST_AUTHORIZED
4459 rajveer 905
        order.statusDescription = "DOA Request Authorized"
4454 rajveer 906
    else:
907
        order.status = OrderStatus.DELIVERY_SUCCESS
4459 rajveer 908
        order.statusDescription = "Order delivered"
4454 rajveer 909
    session.commit()
910
    return True
911
 
4488 rajveer 912
def mark_order_return_request_received(orderId):
913
    order = get_order(orderId)
914
    if order.status != OrderStatus.DELIVERY_SUCCESS:
915
        return False
916
    order.status = OrderStatus.RET_REQUEST_RECEIVED
917
    order.statusDescription = "Return Request Received"
918
    session.commit()
919
    return True
920
 
921
def mark_order_return_request_authorized(orderId, isAuthorized):
922
    order = get_order(orderId)
923
    if order.status != OrderStatus.RET_REQUEST_RECEIVED:
924
        return False
925
    if isAuthorized:
926
        order.status = OrderStatus.RET_REQUEST_AUTHORIZED
927
        order.statusDescription = "Return Request Authorized"
928
    else:
929
        order.status = OrderStatus.DELIVERY_SUCCESS
930
        order.statusDescription = "Order delivered"
931
    session.commit()
932
    return True
933
 
4579 rajveer 934
def request_pickup_number(order_id, providerId):
2536 chandransh 935
    order = get_order(order_id)
4495 rajveer 936
    if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_REQUEST_AUTHORIZED and order.status != OrderStatus.RET_REQUEST_AUTHORIZED:
2536 chandransh 937
        return False
938
    from_user = 'cnc.center@shop2020.in'
939
    from_pwd = '5h0p2o2o'
940
 
4227 rajveer 941
    subject = "Pickup request from " + order.customer_city
2536 chandransh 942
    try:
3133 rajveer 943
        catalog_client = CatalogClient().get_client()
2536 chandransh 944
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
945
 
946
        logistics_client = LogisticsClient().get_client()
4579 rajveer 947
        provider = logistics_client.getProvider(providerId)
3051 chandransh 948
        to_addr = provider.details[DeliveryType.PREPAID].email
2536 chandransh 949
        raw_message = '''
950
        Dear Sir/Madam,
951
 
2559 chandransh 952
        Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.
2536 chandransh 953
 
954
        Pickup CODE: %(provider_code)s
955
        Total Weight: %(order_weight)s kg
956
 
2559 chandransh 957
        Pickup Address:
2536 chandransh 958
 
959
        %(customer_address)s
960
 
961
        Delivery Address:
962
 
963
        %(warehouse_executive)s
964
        %(warehouse_address)s
965
        PIN %(warehouse_pin)s
966
        Phone: %(warehouse_phone)s
967
 
968
        Thanks and Regards
4227 rajveer 969
        Sandeep Sachdeva
2536 chandransh 970
        '''
4579 rajveer 971
 
972
        if warehouse.id == 7:
973
            executive = 'Amit Kumar'
974
            executive_phone = '9911122634'
975
        else:
976
            executive = 'Prashant Sharma'
977
            executive_phone = '8826894193'
978
 
979
 
2559 chandransh 980
        message = dedent(raw_message) % { 'customer_city' : order.customer_city,
3051 chandransh 981
                                          'provider_code' : provider.details[DeliveryType.PREPAID].accountNo,
2536 chandransh 982
                                          'order_weight' : str(order.total_weight),
983
                                          'customer_address' : __get_order_address(order),
4579 rajveer 984
                                          'warehouse_executive' : executive,
2536 chandransh 985
                                          'warehouse_address' : warehouse.location,
986
                                          'warehouse_pin' : warehouse.pincode,
4579 rajveer 987
                                          'warehouse_phone': executive_phone}
4227 rajveer 988
        #FIXME Email is hardcoded for bluedart
989
        mail(from_user, from_pwd, [to_addr, 'sonikap@bluedart.com'], subject, message)
4495 rajveer 990
        if order.status == OrderStatus.RET_REQUEST_AUTHORIZED:
991
            order.status = OrderStatus.RET_PICKUP_REQUEST_RAISED
992
            order.statusDescription = "Pick up requested for RETURN"
993
        else:
994
            order.status = OrderStatus.DOA_PICKUP_REQUEST_RAISED
995
            order.statusDescription = "Pick up requested for DOA"
2536 chandransh 996
        session.commit()
997
        return True
998
    except Exception as e:
999
        print sys.exc_info()[0]
1000
        return False
1001
 
1002
def authorize_pickup(order_id, pickup_number):
1003
    order = get_order(order_id)
4495 rajveer 1004
    if order.status not in [OrderStatus.DOA_PICKUP_REQUEST_RAISED, OrderStatus.RET_PICKUP_REQUEST_RAISED]:
2536 chandransh 1005
        return False
1006
    from_user = 'help@shop2020.in'
1007
    from_pwd = '5h0p2o2o'
1008
    subject = 'Pickup details'
1009
    filename = "/tmp/" +  str(order.id) +".pdf" 
1010
    try:
3133 rajveer 1011
        catalog_client = CatalogClient().get_client()
2536 chandransh 1012
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
1013
 
1014
        logistics_client = LogisticsClient().get_client()
1015
        provider = logistics_client.getProvider(order.logistics_provider_id)
1016
        provider_name = provider.name
1017
 
1018
        to_addr = order.customer_email
1019
        today = date.today().strftime("%d-%B-%Y (%A)")
1020
 
1021
        raw_message = '''
1022
        Dear Mr. %(customer_name)s,
1023
 
4495 rajveer 1024
        In reference to the return of order ID %(order_id)d. We request you to kindly pack the box properly with bubble wrap, and send it along with the original "DOA" certificate (in case of DOA) and the invoice.
2536 chandransh 1025
        Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.
1026
        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.
1027
 
1028
        Pickup will happen from the below mentioned address:-
1029
 
1030
        %(customer_address)s
1031
 
1032
        Do let us know in case of any concerns
1033
 
1034
        Thanks & Regards
1035
        Saholic Team
1036
        '''
1037
        message = dedent(raw_message) % {'customer_name' : order.customer_name,
1038
                                         'order_id' : order_id,
1039
                                         'provider_name' : provider_name,
1040
                                         'date': today,
1041
                                         'pickup_request_no' : pickup_number,
1042
                                         'customer_address' : __get_order_address(order)}
1043
        print message
1044
        __generate_return_advice(order, warehouse, provider, filename)
3527 chandransh 1045
        mail(from_user, from_pwd, [to_addr], subject, message, [get_attachment_part(filename)])
2536 chandransh 1046
        order.pickupRequestNo = pickup_number
4495 rajveer 1047
        if order.status == OrderStatus.RET_PICKUP_REQUEST_RAISED:
1048
            order.status = OrderStatus.RET_PICKUP_CONFIRMED
1049
            order.statusDescription = "RETURN pick up confirmed"
1050
        else:
1051
            order.status = OrderStatus.DOA_PICKUP_CONFIRMED
1052
            order.statusDescription = "DOA pick up confirmed"
2764 chandransh 1053
        order.doa_auth_timestamp = datetime.datetime.now()
2536 chandransh 1054
        session.commit()
1055
        return True
1056
    except Exception as e:
4234 rajveer 1057
        print sys.exc_info()
4506 phani.kuma 1058
        traceback.print_tb(sys.exc_info()[2])
2536 chandransh 1059
        return False
1060
    finally:
1061
        if os.path.exists(filename):
1062
            os.remove(filename)
1063
 
2764 chandransh 1064
def mark_doas_as_picked_up(provider_id, pickup_details):
1065
    for pickupNo, doa_pickup_timestamp in pickup_details.iteritems():
1066
        order = Order.query.filter_by(pickupRequestNo=pickupNo, logistics_provider_id = provider_id).first()
4452 rajveer 1067
        if order == None or order.status != OrderStatus.DOA_PICKUP_CONFIRMED:
2764 chandransh 1068
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1069
            continue
1070
        order.status = OrderStatus.DOA_RETURN_IN_TRANSIT
1071
        order.statusDescription = "DOA picked up by Courier Company"
1072
        order.doa_pickup_timestamp = doa_pickup_timestamp
1073
    session.commit()
1074
 
1075
    current_time = datetime.datetime.now()
1076
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1077
    from_datetime = to_datetime - datetime.timedelta(2)
4452 rajveer 1078
    orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.DOA_PICKUP_CONFIRMED).filter(Order.doa_auth_timestamp >= from_datetime).filter(Order.doa_auth_timestamp <= to_datetime).all()
2764 chandransh 1079
    return orders_not_picked_up
1080
 
4479 rajveer 1081
def receive_return(order_id, receiveCondition):
2591 chandransh 1082
    order = get_order(order_id)
4365 mandeep.dh 1083
 
1084
    # FIXME: For Mahipal warehouse, we need to scan in items for every sales return
4576 mandeep.dh 1085
    if order.warehouse_id == 7:
4365 mandeep.dh 1086
        try:
1087
            warehouse_client = WarehouseClient().get_client()
1088
            lineitem = order.lineitems[0]
1089
 
1090
            # Inventory should not be updated for DOA returns 
4484 rajveer 1091
            if order.status == OrderStatus.RTO_IN_TRANSIT:
4555 mandeep.dh 1092
                warehouse_client.scanSerializedItemForOrder(str(lineitem.imei_number), ScanType.SALE_RET, order.id, order.warehouse_id)
1093
                # In case of RTOs increasing availibility only if we receive item in prestine state
1094
                if not receiveCondition:
1095
                    catalog_client = CatalogClient().get_client()
1096
                    catalog_client.addInventory(lineitem.item_id, order.warehouse_id, lineitem.quantity)
4452 rajveer 1097
            elif order.status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
4555 mandeep.dh 1098
                warehouse_client.scanSerializedItemForOrder(str(lineitem.imei_number), ScanType.DOA_IN, order.id, order.warehouse_id)
4365 mandeep.dh 1099
        except:
1100
            print sys.exc_info()[0]
1101
            print 'Could not scan in sales return orders'
1102
 
4452 rajveer 1103
    if order.status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
4479 rajveer 1104
        if receiveCondition == 0:
1105
            order.status = OrderStatus.DOA_RECEIVED_PRESTINE
1106
            order.statusDescription = "DOA package received"
1107
        elif receiveCondition == 1:
1108
            order.status = OrderStatus.DOA_RECEIVED_DAMAGED
1109
            order.statusDescription = "DOA received damaged"
1110
        elif receiveCondition == 2:
1111
            order.status = OrderStatus.DOA_LOST_IN_TRANSIT
1112
            order.statusDescription = "DOA lost in transit"
2764 chandransh 1113
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 1114
        session.commit()
4495 rajveer 1115
    elif order.status in [OrderStatus.RET_PICKUP_CONFIRMED, OrderStatus.RET_RETURN_IN_TRANSIT]:
1116
        if receiveCondition == 0:
1117
            order.status = OrderStatus.RET_RECEIVED_PRESTINE
1118
            order.statusDescription = "RETURN package received"
1119
        elif receiveCondition == 1:
1120
            order.status = OrderStatus.RET_RECEIVED_DAMAGED
1121
            order.statusDescription = "RETURN received damaged"
1122
        elif receiveCondition == 2:
1123
            order.status = OrderStatus.RET_LOST_IN_TRANSIT
1124
            order.statusDescription = "RETURN lost in transit"
1125
        order.received_return_timestamp = datetime.datetime.now()
1126
        session.commit()
4484 rajveer 1127
    elif order.status == OrderStatus.RTO_IN_TRANSIT :
4486 rajveer 1128
        if receiveCondition == 0:
1129
            order.status = OrderStatus.RTO_RECEIVED_PRESTINE
4515 mandeep.dh 1130
            order.statusDescription = "Returned to origin"
4486 rajveer 1131
        elif receiveCondition == 1:
1132
            order.status = OrderStatus.RTO_RECEIVED_DAMAGED
1133
            order.statusDescription = "RTO received damaged"
1134
        elif receiveCondition == 2:
1135
            order.status = OrderStatus.RTO_LOST_IN_TRANSIT
1136
            order.statusDescription = "RTO lost in transit"
2764 chandransh 1137
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 1138
        session.commit()
1139
    else:
2591 chandransh 1140
        return False
1141
    return True
1142
 
1143
def validate_doa(order_id, is_valid):
1144
    order = get_order(order_id)
4452 rajveer 1145
    if order.status != OrderStatus.DOA_RECEIVED_PRESTINE:
2591 chandransh 1146
        return False
1147
    if is_valid:
2609 chandransh 1148
        order.status = OrderStatus.DOA_CERT_VALID
1149
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 1150
    else:
1151
        order.status = OrderStatus.DOA_CERT_INVALID
1152
        order.statusDescription = "DOA Certificate Invalid"
3578 mandeep.dh 1153
        update_trust_level(order)
2591 chandransh 1154
    session.commit()
1155
    return True
1156
 
4495 rajveer 1157
def validate_return_product(order_id, is_usable):
1158
    order = get_order(order_id)
1159
    if order.status != OrderStatus.RET_RECEIVED_PRESTINE:
1160
        return False
1161
    if is_usable:
1162
        order.status = OrderStatus.RET_PRODUCT_USABLE
1163
        order.statusDescription = "Return product usable"
4555 mandeep.dh 1164
        lineitem = order.lineitems[0]
4576 mandeep.dh 1165
        if order.warehouse_id == 7:
4555 mandeep.dh 1166
            catalog_client = CatalogClient().get_client()
1167
            catalog_client.addInventory(lineitem.item_id, order.warehouse_id, lineitem.quantity)
4495 rajveer 1168
    else:
1169
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE
1170
        order.statusDescription = "Return product unusable"
1171
        update_trust_level(order)
1172
    session.commit()
1173
    return True
1174
 
2628 chandransh 1175
def reship_order(order_id):
1176
    """
4484 rajveer 1177
    If the order is in RTO_RECEIVED_PRESTINE or DOA_CERT_INVALID state, it does the following:
2628 chandransh 1178
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
4484 rajveer 1179
        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 1180
 
1181
    If the order is in DOA_CERT_VALID state, it does the following:
1182
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
1183
        2. Creates a return order for the warehouse executive to return the DOA material.
4452 rajveer 1184
        3. Marks the current order as the final DOA_VALID_RESHIPPED state.
2628 chandransh 1185
 
1186
    Returns the id of the newly created order.
1187
 
1188
    Throws an exception if the order with the given id couldn't be found.
1189
 
1190
    Parameters:
1191
     - orderId
1192
    """
1193
    order = get_order(order_id)
4484 rajveer 1194
    if order.status == OrderStatus.RTO_RECEIVED_PRESTINE:
4220 rajveer 1195
        new_order = __clone_order(order, True, order.cod)
4484 rajveer 1196
        order.status = OrderStatus.RTO_RESHIPPED
2628 chandransh 1197
        order.statusDescription = "Order Reshipped"
1198
        session.commit()
3578 mandeep.dh 1199
        update_trust_level(order)
4486 rajveer 1200
    elif order.status == OrderStatus.RTO_RECEIVED_DAMAGED:
1201
        new_order = __clone_order(order, False, order.cod)
1202
        ret_order = __create_return_order(order)
1203
        order.status = OrderStatus.RTO_DAMAGED_RESHIPPED
1204
        order.statusDescription = "Order Reshipped Received Damaged"
1205
        session.commit()
1206
    elif order.status == OrderStatus.RTO_LOST_IN_TRANSIT:
1207
        new_order = __clone_order(order, False, order.cod)
1208
        order.status = OrderStatus.RTO_LOST_IN_TRANSIT_RESHIPPED
1209
        order.statusDescription = "Order Reshipped Lost In Transit"
1210
        session.commit()
2628 chandransh 1211
    elif order.status == OrderStatus.DOA_CERT_INVALID:
4220 rajveer 1212
        new_order = __clone_order(order, True, False)
2628 chandransh 1213
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
1214
        order.statusDescription = "Order Reshipped"
1215
        session.commit()
1216
    elif order.status == OrderStatus.DOA_CERT_VALID:
4220 rajveer 1217
        new_order = __clone_order(order, False, False)
2628 chandransh 1218
        ret_order = __create_return_order(order)
4452 rajveer 1219
        order.status = OrderStatus.DOA_VALID_RESHIPPED
2628 chandransh 1220
        order.statusDescription = "Order Reshipped"
1221
        session.commit()
4479 rajveer 1222
    elif order.status == OrderStatus.DOA_RECEIVED_DAMAGED:
1223
        new_order = __clone_order(order, False, False)
1224
        ret_order = __create_return_order(order)
1225
        order.status = OrderStatus.DOA_RESHIPPED_RCVD_DAMAGED
1226
        order.statusDescription = "Order Reshipped Received Damaged"
1227
        session.commit()
1228
    elif order.status == OrderStatus.DOA_LOST_IN_TRANSIT:
1229
        new_order = __clone_order(order, False, False)
1230
        order.status = OrderStatus.DOA_RESHIPPED_LOST_IN_TRANSIT
1231
        order.statusDescription = "Order Reshipped Lost In Transit"
1232
        session.commit()
4495 rajveer 1233
    elif order.status == OrderStatus.RET_PRODUCT_UNUSABLE:
1234
        new_order = __clone_order(order, True, False)
1235
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE_RESHIPPED
1236
        order.statusDescription = "Order Reshipped"
1237
        session.commit()
1238
    elif order.status == OrderStatus.RET_PRODUCT_USABLE:
1239
        new_order = __clone_order(order, False, False)
1240
        ret_order = __create_return_order(order)
1241
        order.status = OrderStatus.RET_PRODUCT_USABLE_RESHIPPED
1242
        order.statusDescription = "Order Reshipped"
1243
        session.commit()
1244
    elif order.status == OrderStatus.RET_RECEIVED_DAMAGED:
1245
        new_order = __clone_order(order, False, False)
1246
        ret_order = __create_return_order(order)
1247
        order.status = OrderStatus.RET_RESHIPPED_RCVD_DAMAGED
1248
        order.statusDescription = "Order Reshipped Received Damaged"
1249
        session.commit()
1250
    elif order.status == OrderStatus.RET_LOST_IN_TRANSIT:
1251
        new_order = __clone_order(order, False, False)
1252
        order.status = OrderStatus.RET_RESHIPPED_LOST_IN_TRANSIT
1253
        order.statusDescription = "Order Reshipped Lost In Transit"
1254
        session.commit()
2628 chandransh 1255
    else:
1256
        raise TransactionServiceException(112, "This order can't be reshipped")
1257
 
2764 chandransh 1258
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 1259
    order.new_order_id = new_order.id
1260
    session.commit()
1261
 
1262
    return new_order.id
1263
 
3226 chandransh 1264
def refund_order(order_id, refunded_by, reason):
2628 chandransh 1265
    """
4484 rajveer 1266
    If the order is in RTO_RECEIVED_PRESTINE, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
2628 chandransh 1267
        1. Creates a refund request for batch processing.
1268
        2. Creates a return order for the warehouse executive to return the shipped material.
4484 rajveer 1269
        3. Marks the current order as RTO_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
2628 chandransh 1270
 
1271
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
1272
        1. Creates a refund request for batch processing.
3226 chandransh 1273
        2. Cancels the reservation of the item in the warehouse.
1274
        3. Marks the current order as the REFUNDED final state.
2628 chandransh 1275
 
3226 chandransh 1276
    For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
1277
        1. Cancels the reservation of the item in the warehouse.
1278
        2. Marks the current order as CANCELED.
1279
 
1280
    In all cases, it updates the reason for cancellation or refund and the person who performed the action.
1281
 
1282
    Returns True if it is successful, False otherwise.
2628 chandransh 1283
 
1284
    Throws an exception if the order with the given id couldn't be found.
1285
 
1286
    Parameters:
3226 chandransh 1287
     - order_id
1288
     - refunded_by
1289
     - reason
2628 chandransh 1290
    """
3414 chandransh 1291
    logging.info("Refunding order id: " + str(order_id))
2628 chandransh 1292
    order = get_order(order_id)
3186 chandransh 1293
 
1294
 
3366 chandransh 1295
 
3226 chandransh 1296
    if order.cod:
3414 chandransh 1297
        logging.info("Refunding COD order with status " + str(order.status))
4484 rajveer 1298
        status_transition = {OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 1299
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
1300
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 1301
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
1302
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 1303
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
1304
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 1305
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
1306
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
1307
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
1308
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
3366 chandransh 1309
                     OrderStatus.INIT : OrderStatus.CANCELED,
1310
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELED,
1311
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELED,
4306 rajveer 1312
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELED,
1313
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELED,
1314
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELED,
3366 chandransh 1315
                     OrderStatus.ACCEPTED : OrderStatus.CANCELED,
4247 rajveer 1316
                     OrderStatus.BILLED : OrderStatus.CANCELED,
1317
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST
3366 chandransh 1318
                     }
1319
        if order.status not in status_transition.keys():
1320
            raise TransactionServiceException(114, "This order can't be refunded")
1321
 
3413 chandransh 1322
        if order.status < OrderStatus.BILLED:
3226 chandransh 1323
            __update_inventory_reservation(order)
1324
            order.statusDescription = "Order Cancelled"
3415 chandransh 1325
        elif order.status == OrderStatus.BILLED:
3413 chandransh 1326
            __create_return_order(order)
1327
            order.statusDescription = "Order Cancelled"
4486 rajveer 1328
        elif order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT]:
3226 chandransh 1329
            __create_return_order(order)
4486 rajveer 1330
            order.statusDescription = "RTO Refunded"
4479 rajveer 1331
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
4078 chandransh 1332
            __create_return_order(order)
3226 chandransh 1333
            __create_refund(order)
4495 rajveer 1334
            order.statusDescription = "DOA Refunded"
1335
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
1336
            __create_return_order(order)
1337
            __create_refund(order)
1338
            order.statusDescription = "Return Refunded"
4247 rajveer 1339
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
1340
            if order.previousStatus  < OrderStatus.BILLED:
1341
                __update_inventory_reservation(order)
1342
                order.statusDescription = "Order Cancelled on customer request"
1343
            elif order.previousStatus == OrderStatus.BILLED:
1344
                __create_return_order(order)
1345
                order.statusDescription = "Order Cancelled on customer request"
3226 chandransh 1346
    else:
4484 rajveer 1347
        status_transition = {OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 1348
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
1349
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 1350
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
1351
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 1352
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
1353
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 1354
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
1355
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
1356
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
1357
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
3366 chandransh 1358
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.REFUNDED,
3731 chandransh 1359
                     OrderStatus.INVENTORY_LOW : OrderStatus.REFUNDED,
4306 rajveer 1360
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.REFUNDED,
1361
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.REFUNDED,
1362
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.REFUNDED,
3731 chandransh 1363
                     OrderStatus.ACCEPTED : OrderStatus.REFUNDED,
4247 rajveer 1364
                     OrderStatus.BILLED : OrderStatus.REFUNDED,
1365
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST,
1366
                     OrderStatus.PAYMENT_FLAGGED : OrderStatus.PAYMENT_FLAGGED_DENIED
3366 chandransh 1367
                     }
1368
        if order.status not in status_transition.keys():
1369
            raise TransactionServiceException(114, "This order can't be refunded")
1370
 
4495 rajveer 1371
        if order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT] :
3226 chandransh 1372
            __create_return_order(order)
1373
            __create_refund(order)
4495 rajveer 1374
            order.statusDescription = "RTO Refunded"
1375
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
1376
            __create_return_order(order)
1377
            __create_refund(order)
1378
            order.statusDescription = "DOA Refunded"
1379
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
1380
            __create_return_order(order)
1381
            __create_refund(order)
1382
            order.statusDescription = "Return Refunded"
4306 rajveer 1383
        elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3191 chandransh 1384
            __create_cancellation(order)
3226 chandransh 1385
            __update_inventory_reservation(order)
1386
            order.statusDescription = "Order Refunded"
4247 rajveer 1387
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
1388
            if order.previousStatus  < OrderStatus.BILLED:
1389
                __create_refund(order)
1390
                __update_inventory_reservation(order)
1391
                order.statusDescription = "Order Cancelled on customer request"
1392
            elif order.previousStatus == OrderStatus.BILLED:
1393
                __create_return_order(order)
1394
                __create_refund(order)
1395
                order.statusDescription = "Order Cancelled on customer request"
1396
        elif order.status == OrderStatus.PAYMENT_FLAGGED:
1397
            __update_inventory_reservation(order)
1398
            order.statusDescription = "Order Cancelled due to payment flagged"
3195 chandransh 1399
 
1400
    order.status = status_transition[order.status]
1401
    order.refund_timestamp = datetime.datetime.now()
3226 chandransh 1402
    order.refunded_by = refunded_by
1403
    order.refund_reason = reason
2628 chandransh 1404
 
1405
    session.commit()
1406
    return True
1407
 
3186 chandransh 1408
def __update_inventory_reservation(order):
3191 chandransh 1409
    '''
1410
    Reduce the reservation count for all line items of the given order.
1411
    '''
3186 chandransh 1412
    try:
1413
        catalog_client = CatalogClient().get_client()
1414
        for lineitem in order.lineitems:
1415
            catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity);
1416
    except:
1417
        print "Unable to reduce reservation count"
1418
 
4220 rajveer 1419
def __clone_order(order, should_copy_billing_info, is_cod):
2628 chandransh 1420
    current_time = datetime.datetime.now()
1421
    new_order = Order()
1422
    new_order.customer_id = order.customer_id
1423
    new_order.customer_name = order.customer_name
1424
    new_order.customer_city = order.customer_city
1425
    new_order.customer_state = order.customer_state
1426
    new_order.customer_mobilenumber = order.customer_mobilenumber
1427
    new_order.customer_pincode = order.customer_pincode
1428
    new_order.customer_address1 = order.customer_address1
1429
    new_order.customer_address2 = order.customer_address2
1430
    new_order.customer_email = order.customer_email
1431
    new_order.total_amount = order.total_amount
1432
    new_order.total_weight = order.total_weight
1433
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1434
    new_order.statusDescription = 'Submitted for Processing'
1435
    new_order.created_timestamp = current_time
1436
 
1437
    new_order.transaction = order.transaction
4220 rajveer 1438
    new_order.cod = is_cod
2628 chandransh 1439
 
1440
    for line_item in order.lineitems:
1441
        litem = LineItem()
1442
        litem.item_id = line_item.item_id
1443
        litem.productGroup = line_item.productGroup
1444
        litem.brand = line_item.brand
1445
        if line_item.model_number:
1446
            litem.model_number = line_item.model_number
1447
        if line_item.model_name:    
1448
            litem.model_name = line_item.model_name
1449
        if line_item.color:
1450
            litem.color = line_item.color
1451
        if line_item.extra_info:
1452
            litem.extra_info = line_item.extra_info
1453
        litem.quantity = line_item.quantity
1454
        litem.unit_price = line_item.unit_price
1455
        litem.unit_weight = line_item.unit_weight
1456
        litem.total_price = line_item.total_price
1457
        litem.total_weight = line_item.total_weight
1458
        litem.transfer_price = line_item.transfer_price
1459
        litem.order = new_order
1460
 
1461
    logistics_client = LogisticsClient().get_client()
1462
    item_id = new_order.lineitems[0].item_id
4479 rajveer 1463
    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 1464
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
1465
 
1466
    new_order.warehouse_id = logistics_info.warehouseId
1467
    new_order.logistics_provider_id = logistics_info.providerId
1468
    new_order.airwaybill_no = logistics_info.airway_billno
1469
    new_order.tracking_id = new_order.airwaybill_no
1470
    new_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 1471
    new_order.promised_delivery_time = new_order.expected_delivery_time
4299 rajveer 1472
 
2628 chandransh 1473
    if should_copy_billing_info:
1474
        new_order.invoice_number = order.invoice_number
1475
        new_order.billed_by = order.billed_by
1476
        new_order.warehouse_id = order.warehouse_id
1477
        new_order.accepted_timestamp = current_time
1478
        new_order.billing_timestamp = current_time    
1479
        new_order.status = OrderStatus.BILLED
1480
        new_order.statusDescription = 'Order Billed'
1481
    else:       
3133 rajveer 1482
        catalog_client = CatalogClient().get_client()
2628 chandransh 1483
        catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, new_order.lineitems[0].quantity)
1484
 
1485
    return new_order
1486
 
1487
def __create_return_order(order):
2687 chandransh 1488
    ret_order = ReturnOrder(order)
2628 chandransh 1489
    return ret_order
1490
 
1491
def __create_refund(order):
4078 chandransh 1492
    payment_client = PaymentClient().get_client()
1493
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
2747 chandransh 1494
    return
2628 chandransh 1495
 
3035 chandransh 1496
def __create_cancellation(order):
1497
    return
1498
 
2536 chandransh 1499
def __get_order_address(order):
1500
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
1501
    if order.customer_address2:
1502
        address = address + order.customer_address2 + "\n"
1503
    address = address + order.customer_city + "\n"
1504
    address = address + order.customer_state + "\n"
1505
    address = address + "PIN " + order.customer_pincode + "\n"
1506
    address = address + "Phone: " + order.customer_mobilenumber
1507
    return address
1508
 
1509
def __generate_return_advice(order, warehouse, provider, filename):    
1510
    pdf = Canvas(filename)
1511
    pdf.setFont('Times-Bold',16)
1512
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
1513
    address_text.textLine("To")
1514
    address_text.textLine("Parmod Kumar")
1515
    for line in warehouse.location.split("\n"):
1516
        address_text.textLine(line)
1517
    address_text.textLine("PIN " + warehouse.pincode)
1518
    address_text.textLine("")
1519
    address_text.textLine("Phone: 9971573026")
1520
    pdf.drawText(address_text)
1521
 
1522
    pdf.setFont('Times-Roman',12)
1523
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
3051 chandransh 1524
    order_text.textLine("Pickup CODE: " + provider.details[DeliveryType.PREPAID].accountNo)
2536 chandransh 1525
    lineitem = order.lineitems[0] 
4234 rajveer 1526
    order_text.textLine("Content : " + lineitem.brand + " " + str(lineitem.model_number) + " " + str(lineitem.color))
2536 chandransh 1527
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
1528
    order_text.textLine("Order ID : " + str(order.id))
1529
    pdf.drawText(order_text)
1530
    pdf.showPage()
1531
    pdf.save()
1532
    return filename
1533
 
2697 chandransh 1534
def get_return_orders(warehouse_id, from_date, to_date):
1535
    query = ReturnOrder.query.filter_by(processedStatus = False)
1536
    if warehouse_id != -1:
1537
        query = query.filter_by(warehouseId = warehouse_id)
1538
    if from_date:
4118 chandransh 1539
        query = query.filter(ReturnOrder.createdAt >from_date)
2697 chandransh 1540
    if to_date:
4118 chandransh 1541
        query = query.filter(ReturnOrder.createdAt < to_date)
2697 chandransh 1542
    return [return_order.to_thrift_object() for return_order in query.all()]
1543
 
2700 chandransh 1544
def get_return_order(id):
1545
    ret_order = ReturnOrder.get_by(orderId = id)
1546
    if ret_order is None:
1547
        raise TransactionServiceException(116, "No return order found for the given order id")
1548
    return ret_order.to_thrift_object()
1549
 
2697 chandransh 1550
def process_return(ret_order_id):
1551
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
1552
    if ret_order is None:
1553
        raise TransactionServiceException(116, "No return order found for the given order id")
1554
    ret_order.processedStatus = True
2701 chandransh 1555
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 1556
    session.commit()
1557
 
2819 chandransh 1558
def create_purchase_order(warehouseId):
1559
    if not warehouseId:
1560
        raise TransactionServiceException(101, "bad warehouse id")
1561
 
3451 chandransh 1562
    query = Order.query.with_lockmode("update").filter_by(warehouse_id=warehouseId)
4586 mandeep.dh 1563
    query = query.filter(or_(Order.status == OrderStatus.SUBMITTED_FOR_PROCESSING, Order.status == OrderStatus.INVENTORY_LOW, Order.status == OrderStatus.ACCEPTED))
2819 chandransh 1564
    query = query.filter_by(purchase_order_id=None)
1565
    query = query.order_by(Order.created_timestamp)
1566
    pending_orders = query.all()
4586 mandeep.dh 1567
 
2819 chandransh 1568
    if not pending_orders:
4586 mandeep.dh 1569
        return None
4434 mandeep.dh 1570
 
1571
    catalog_client = CatalogClient().get_client()
1572
    availability = {}
1573
    for item in catalog_client.getAllItemsForWarehouse(warehouseId):
4586 mandeep.dh 1574
        availability[item.id] = [item.itemInventory.availability[warehouseId], item]
4434 mandeep.dh 1575
 
4586 mandeep.dh 1576
    requirements = {}
1577
    for order in pending_orders:
2819 chandransh 1578
        for lineitem in order.lineitems:
4586 mandeep.dh 1579
            if (requirements.has_key(lineitem.item_id)):
1580
                requirements[lineitem.item_id] += lineitem.quantity
2819 chandransh 1581
            else:
4586 mandeep.dh 1582
                requirements[lineitem.item_id] = lineitem.quantity
4434 mandeep.dh 1583
 
4586 mandeep.dh 1584
    net_requirements = {}
1585
    for itemId in requirements.keys():
1586
        requirementsCount = requirements.get(itemId)
1587
        if  availability.has_key(itemId):
1588
            availabilityCount = availability.get(itemId)[0]
1589
            item              = availability.get(itemId)[1]
1590
            if item.preferredVendor is None or item.preferredVendor == 1:
1591
                continue
1592
            if requirementsCount > availabilityCount:
1593
                if (net_requirements.has_key(item.preferredVendor)):
1594
                    net_requirements[item.preferredVendor].append([item, requirementsCount - availabilityCount])
1595
                else:
1596
                    net_requirements[item.preferredVendor] = [[item, requirementsCount - availabilityCount]];
1597
        else:
1598
            item = catalog_client.getItem(itemId);
1599
            if item.preferredVendor is None or item.preferredVendor == 1:
1600
                continue
1601
            if (net_requirements.has_key(item.preferredVendor)):
1602
                net_requirements[item.preferredVendor].append([item, requirementsCount])
1603
            else:
1604
                net_requirements[item.preferredVendor] = [[item, requirementsCount]];
4434 mandeep.dh 1605
 
4586 mandeep.dh 1606
    if not net_requirements:
1607
        return None
4434 mandeep.dh 1608
 
4586 mandeep.dh 1609
    purchaseOrderIds = []
1610
    for vendorId in net_requirements.keys():
1611
        t_purchase_order = PurchaseOrder()
1612
        t_purchase_order.supplierId = vendorId
1613
        t_purchase_order.warehouseId = warehouseId
1614
        t_purchase_order.lineitems = []
1615
        for key in net_requirements.get(vendorId):
1616
            item     = key[0]
1617
            quantity = key[1]
1618
            t_po_lineitem = POLineItem()
1619
            t_po_lineitem.productGroup = item.productGroup
1620
            t_po_lineitem.brand = item.brand
1621
            t_po_lineitem.modelNumber = item.modelNumber
1622
            t_po_lineitem.modelName = item.modelName
1623
            t_po_lineitem.color = item.color
1624
            t_po_lineitem.itemId = item.id
1625
            t_po_lineitem.quantity = quantity
1626
            try:
1627
                item_pricing = catalog_client.getItemPricing(item.id, vendorId)
1628
            except Exception as e:
1629
                purchase_client = PurchaseClient().get_client()
1630
                vendor = purchase_client.getSupplier(vendorId)
1631
                print 'Could not find transfer price for Item id: ' + str(item.id) + ' and vendor id: ' + str(vendorId)
1632
                print e
1633
                raise TransactionServiceException(101, 'Transfer price missing for ' + vendor.name + ' and ' + " ".join([item.brand, item.modelName, item.modelNumber, item.color]))
1634
            t_po_lineitem.unitPrice = item_pricing.transferPrice
1635
            t_purchase_order.lineitems.append(t_po_lineitem)
1636
        purchase_client = PurchaseClient().get_client()
1637
        poId = purchase_client.createPurchaseOrder(t_purchase_order)
1638
        purchaseOrderIds.append(poId)
1639
 
2819 chandransh 1640
    for order in pending_orders:
4586 mandeep.dh 1641
        order.purchase_order_id = purchaseOrderIds[len(purchaseOrderIds) - 1]
4434 mandeep.dh 1642
        order.status = OrderStatus.LOW_INV_PO_RAISED
1643
        order.statusDescription = 'In Process'
2819 chandransh 1644
    session.commit()
4586 mandeep.dh 1645
    return purchaseOrderIds
2819 chandransh 1646
 
3451 chandransh 1647
def update_weight(order_id, weight):
3469 chandransh 1648
    '''
1649
    Update the weight of order
1650
    '''
3451 chandransh 1651
    order = get_order(order_id)
1652
    order.total_weight = weight
3469 chandransh 1653
    lineitem = order.lineitems[0]
1654
    lineitem.total_weight = weight
1655
    lineitem.unit_weight = weight
3451 chandransh 1656
 
3469 chandransh 1657
    session.commit()
1658
    return order
1659
 
1660
def change_product(order_id, item_id):
1661
    '''
1662
    Ship a product of a different color to the customer.
1663
    '''
1664
    order = get_order(order_id)
4306 rajveer 1665
    if order.status not in [OrderStatus.INIT, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3469 chandransh 1666
        raise TransactionServiceException(120, "This order has already been processed. Please seek help from engineering.")
1667
 
1668
    lineitem = order.lineitems[0]
3451 chandransh 1669
 
3469 chandransh 1670
    catalog_client = CatalogClient().get_client()
1671
 
1672
    old_item = catalog_client.getItem(lineitem.item_id)
1673
    item = catalog_client.getItem(item_id)
1674
    if old_item.catalogItemId != item.catalogItemId:
1675
        raise TransactionServiceException(121, "You can't ship a different item. You can only ship the same item in a different color.")
1676
 
1677
    catalog_client.reserveItemInWarehouse(item_id, order.warehouse_id, lineitem.quantity)
1678
    catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity)
1679
    #TODO: Check that this new item has the same price
1680
 
1681
    lineitem.item_id = item_id
1682
    lineitem.color = item.color
1683
 
3451 chandransh 1684
    session.commit()
3469 chandransh 1685
 
1686
    order = get_order(order_id)
3451 chandransh 1687
    return order
3469 chandransh 1688
 
1689
def change_warehouse(order_id, warehouse_id):
1690
    '''
1691
    Update the warehouse which will be used to fulfil this order.
1692
    '''
1693
    order = get_order(order_id)
4306 rajveer 1694
    if order.status not in [OrderStatus.INIT, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3469 chandransh 1695
        raise TransactionServiceException(117, "This order has already been processed. Please seek help from engineering.")
1696
 
1697
    if warehouse_id == order.warehouse_id:
1698
        raise TransactionServiceException(118, "You have selected the current warehouse again. Nothing to do")
1699
 
1700
    lineitem = order.lineitems[0]
1701
    catalog_client = CatalogClient().get_client()
1702
    try:
1703
        warehouse = catalog_client.getWarehouse(warehouse_id)
1704
    except:
1705
        raise TransactionServiceException(119, "No warehouse with id" + str(warehouse_id))
1706
 
1707
    catalog_client.reserveItemInWarehouse(lineitem.item_id, warehouse_id, lineitem.quantity)
1708
    catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity)
3451 chandransh 1709
 
3469 chandransh 1710
    order.warehouse_id = warehouse_id
1711
    session.commit()
1712
    return order
3553 chandransh 1713
 
3986 chandransh 1714
def add_delay_reason(order_id, reason, further_delay=0):
3553 chandransh 1715
    '''
3994 chandransh 1716
    Adds a delay reason to the order and updates the expected delivery time.
3553 chandransh 1717
    '''
1718
    order = get_order(order_id)
1719
    try:
3581 chandransh 1720
        order.delay_reason = DelayReason._VALUES_TO_NAMES[reason]
4009 chandransh 1721
        actual_delivery_delay = adjust_delivery_time(order.expected_delivery_time, further_delay)
1722
        order.expected_delivery_time = order.expected_delivery_time + datetime.timedelta(days=actual_delivery_delay)
4102 chandransh 1723
 
1724
        if order.status < OrderStatus.SHIPPED_FROM_WH:
1725
            actual_shipping_delay = adjust_delivery_time(order.expected_shipping_time, further_delay)
1726
            order.expected_shipping_time = order.expected_shipping_time + datetime.timedelta(days=actual_shipping_delay)
1727
 
3553 chandransh 1728
        session.commit()
4008 mandeep.dh 1729
 
1730
        try:
1731
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
1732
            transaction_requiring_extra_processing.category = 'DELAYED_DELIVERY'
1733
            transaction_requiring_extra_processing.transaction_id = order.transaction_id
1734
            session.commit()
1735
        except Exception as e:
4065 mandeep.dh 1736
            print 'Could not persist transaction id: ' + str(order.transaction_id) + ' for further processing due to: ' + str(e)
4008 mandeep.dh 1737
 
3553 chandransh 1738
        return True
1739
    except:
3994 chandransh 1740
        print sys.exc_info()[0]
3553 chandransh 1741
        return False
3956 chandransh 1742
 
1743
def reconcile_cod_collection(collected_amount_map, xferBy, xferTxnId, xferDate):
1744
    unprocessed_awbs = {}
1745
    for awb, amount in collected_amount_map.iteritems():
1746
        try:
1747
            order = Order.query.filter_by(airwaybill_no=awb).one()
1748
        except NoResultFound:
1749
            unprocessed_awbs[awb] = "No order was found for the given AWB: " + awb
1750
            continue
1751
        except MultipleResultsFound:
1752
            unprocessed_awbs[awb] = "Multiple orders were found for the given AWB:" + awb
1753
            continue
1754
 
1755
        if order.cod_reconciliation_timestamp:
1756
            #This order has been processed already! This may be a re-run. Let's allow other orders to be processed.
1757
            continue
1758
 
1759
        if order.status < OrderStatus.DELIVERY_SUCCESS:
1760
            #Order has not been delivered yet. No way we can receive the payment.
1761
            unprocessed_awbs[awb] = "Payment has been received for order: " + str(order.id) + " before delivery reconciliation"
1762
            continue
1763
 
4252 rajveer 1764
        ##As per ticket #743 if amount difference less than 0.5 we should reconcile
1765
        if abs(amount - order.total_amount) > 0.5:
3956 chandransh 1766
            #Received amount is less than or more than the order amount. Mustn't let the user proceed.
1767
            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)
1768
            continue
1769
 
1770
        try:
1771
            payment_client = PaymentClient().get_client()
1772
            payment_client.partiallyCapturePayment(order.transaction.id, amount, xferBy, xferTxnId, xferDate)
1773
        except Exception:
1774
            unprocessed_awbs[awb] = "We were unable to partially capture payment for order id " + str(order.id) + ", AWB: " + awb
1775
            continue
1776
 
1777
        #Payment has been recorded now. We can update the order peacefully.
1778
        order.cod_reconciliation_timestamp = datetime.datetime.now()
1779
        session.commit()
3469 chandransh 1780
 
3956 chandransh 1781
    return unprocessed_awbs
4008 mandeep.dh 1782
 
1783
def get_transactions_requiring_extra_processing(category):
4065 mandeep.dh 1784
    """
1785
    Returns the list of transaction ids that require some extra processing and
1786
    which belong to a particular category. This is currently used by CRM
1787
    application. If no such transaction ids are present, it returns an empty list.
1788
    """
1789
    query = TransactionRequiringExtraProcessing.query
4008 mandeep.dh 1790
 
4065 mandeep.dh 1791
    if category is not None:
1792
        query = query.filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category))
4008 mandeep.dh 1793
 
4065 mandeep.dh 1794
    return [a.transaction_id for a in query.all()]
4008 mandeep.dh 1795
 
1796
def mark_transaction_as_processed(transactionId, category):
4065 mandeep.dh 1797
    """
1798
    Marks a particular transaction as processed for a particular cateogory.
1799
    It essentially deletes the transaction id record for a particular
1800
    processing type category (if present) from DB.
1801
    This is currently used by CRM application.
1802
    """
4008 mandeep.dh 1803
    TransactionRequiringExtraProcessing.query.filter_by(transaction_id = transactionId).filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category)).delete()
1804
    session.commit()
1805
 
4018 chandransh 1806
def get_item_wise_risky_orders_count():
1807
    """
1808
    Returns a map containing the number of risky orders keyed by item id. A risky order
1809
    is defined as one whose shipping date is about to expire.
1810
    """
1811
    item_wise_risky_orders_count = {}
4019 chandransh 1812
    shipping_cutoff_time = (datetime.datetime.now() + datetime.timedelta(days = 1)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4018 chandransh 1813
    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()
1814
    for order in orders:
1815
        for lineitem in order.lineitems:
1816
            quantity = lineitem.quantity
1817
            if item_wise_risky_orders_count.has_key(lineitem.item_id):
1818
                quantity = quantity + item_wise_risky_orders_count[lineitem.item_id]
1819
 
1820
            item_wise_risky_orders_count[lineitem.item_id] = quantity
1821
    return item_wise_risky_orders_count
1822
 
4324 mandeep.dh 1823
def update_shipment_address(order_id, address_id):
1824
    """
1825
    Updates shipment address of an order. Delivery and shipping date estimates
1826
    etc. are also updated here.
1827
 
1828
    Throws TransactionServiceException in case address change is not
1829
    possible due to certain reasons such as new pincode in address is
1830
    not serviceable etc.
1831
 
1832
    Parameters:
1833
     - orderId
1834
     - addressId
1835
    """
1836
    user_client = UserClient().get_client()
1837
    address     = user_client.getAddressById(address_id)
1838
    order       = get_order(order_id)
1839
 
1840
    logistics_client = LogisticsClient().get_client()
1841
    logistics_info = logistics_client.getLogisticsEstimation(order.lineitems[0].item_id, address.pin)
1842
 
1843
    # Check for new estimate. Raise exception if new address is not serviceable
1844
    if logistics_info.deliveryTime == -1:
1845
        raise TransactionServiceException(1, 'Location not serviceable')
1846
 
1847
    # COD services are not available everywhere
1848
    if order.cod:
1849
        if not logistics_client.isCodAllowed(address.pin):
1850
            raise TransactionServiceException(2, 'COD service not available')
1851
 
1852
    current_time = datetime.datetime.now()
1853
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
1854
    logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
1855
 
1856
    order.customer_name         = address.name
1857
    order.customer_pincode      = address.pin
1858
    order.customer_address1     = address.line1
1859
    order.customer_address2     = address.line2
1860
    order.customer_city         = address.city
1861
    order.customer_state        = address.state
1862
    order.customer_mobilenumber = address.phone
1863
 
1864
    if order.cod:
1865
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
1866
    else:
1867
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
1868
 
1869
    order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
1870
    order.promised_shipping_time = order.expected_shipping_time
1871
    order.promised_delivery_time = order.expected_delivery_time 
1872
 
1873
    session.commit()
1874
 
4247 rajveer 1875
def mark_order_cancellation_request_received(orderId):
1876
    """
1877
    Mark order as cancellation request received. If customer sends request of cancellation of
1878
    a particular order, this method will be called. It will just change status of the order
1879
    depending on its current status. It also records the previous status, so that we can move
1880
    back to that status if cancellation request is denied.
1881
 
1882
    Parameters:
1883
     - orderId
1884
    """
1885
    status_transition = {OrderStatus.INIT : OrderStatus.CANCEL_REQUEST_RECEIVED,
1886
             OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCEL_REQUEST_RECEIVED,
1887
             OrderStatus.INVENTORY_LOW : OrderStatus.CANCEL_REQUEST_RECEIVED,
4306 rajveer 1888
             OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCEL_REQUEST_RECEIVED,
1889
             OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCEL_REQUEST_RECEIVED,
1890
             OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 1891
             OrderStatus.ACCEPTED : OrderStatus.CANCEL_REQUEST_RECEIVED,
1892
             OrderStatus.BILLED : OrderStatus.CANCEL_REQUEST_RECEIVED,
1893
             OrderStatus.PAYMENT_FLAGGED : OrderStatus.CANCEL_REQUEST_RECEIVED
1894
             }
1895
    if order.status not in status_transition.keys():
1896
        raise TransactionServiceException(114, "This order can't be considered for cancellation")
1897
 
1898
    order = get_order(orderId)
1899
    order.previousStatus = order.status
1900
    order.status = OrderStatus.CANCEL_REQUEST_RECEIVED
1901
    order.statusDescription = "Cancellation request received from user"
1902
    session.commit()
1903
 
4258 rajveer 1904
def mark_transaction_as_payment_flag_removed(transactionId):
4247 rajveer 1905
    """
4258 rajveer 1906
    If we and/or payment gateway has decided to accept the payment, this method needs to be called.
1907
    Changed transaction and all orders status to payment accepted.
4247 rajveer 1908
 
1909
    Parameters:
4258 rajveer 1910
     - transactionId
4247 rajveer 1911
    """
4258 rajveer 1912
    transaction = get_transaction(transactionId)
1913
    transaction.status = TransactionStatus.AUTHORIZED
1914
    for order in transaction.orders:
1915
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1916
        order.statusDescription = "Submitted to warehouse"
4247 rajveer 1917
    session.commit()
1918
 
4259 anupam.sin 1919
def refund_transaction(transactionId, refundedBy, reason):
1920
    """
1921
    This method is called when a flagged payment is deemed unserviceable and the corresponding orders
1922
    need to be cancelled
1923
 
1924
    Parameters:
1925
     - transactionId
1926
    """
1927
    transaction = get_transaction(transactionId)
1928
    transaction.status = TransactionStatus.FAILED
1929
    for order in transaction.orders:
1930
        refund_order(order.id, refundedBy, reason)
1931
    session.commit()
1932
 
4247 rajveer 1933
def mark_order_cancellation_request_denied(orderId):
1934
    """
4283 anupam.sin 1935
    If we decide to not to cancel order, we will move the order to previous status.
4247 rajveer 1936
 
1937
    Parameters:
1938
     - orderId
1939
    """
1940
    order = get_order(orderId)
1941
    order.status = order.previousStatus
1942
    order.previousStatus = None
1943
    order.statusDescription = "Cancellation request denied"
1944
    session.commit()
1945
 
1946
def mark_order_cancellation_request_confirmed(orderId):
1947
    """
1948
    If we decide to to cancel order, CRM will call this method to move the status of order to
1949
    cancellation request confirmed. After this OM will be able to cancel the order.
1950
 
1951
    Parameters:
1952
     - orderId
1953
    """
1954
    order = get_order(orderId)
1955
    order.status = OrderStatus.CANCEL_REQUEST_CONFIRMED
1956
    order.statusDescription = "Cancellation request confirmed"
1957
    session.commit()
1958
 
4285 rajveer 1959
def accept_orders_for_item_id(itemId, inventory):
1960
    """
1961
    Marks the orders as ACCEPTED for the given itemId and inventory. It also updates the accepted timestamp. If the
1962
    given order is not a COD order, it also captures the payment if the same has not been captured.
1963
 
1964
    Parameters:
1965
     - itemId
1966
     - inventory
1967
    """
4351 rajveer 1968
    orders = Order.query.filter(Order.status.in_(tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS]))).order_by(Order.expected_shipping_time).all()
4285 rajveer 1969
    for order in orders:
4301 rajveer 1970
        if inventory > 0:
1971
            lineitem = order.lineitems[0]
1972
            if itemId == lineitem.item_id:
1973
                try:
1974
                    accept_order(order.id)
1975
                    inventory = inventory - lineitem.quantity
1976
                except:
1977
                    logging.info("Unable to accept the order")
1978
        else:
1979
            order_outofstock(order.id)
4285 rajveer 1980
    return
1981
 
4369 rajveer 1982
def mark_orders_as_po_raised(vendorId, itemId, quantity, estimate, isReminder):
1983
    if isReminder:
1984
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
1985
    else:
1986
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
1987
 
1988
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 1989
    for order in orders:
1990
        lineitem = order.lineitems[0]
1991
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
1992
            if estimate > 0:
1993
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
1994
            order.status = OrderStatus.LOW_INV_PO_RAISED
4362 rajveer 1995
            order.statusDescription = "PO Raised"
4303 rajveer 1996
            quantity = quantity - lineitem.quantity
1997
            store_inventory_action(order, itemId, HotspotAction.PO_RAISED, estimate, lineitem.quantity)
1998
            session.commit()
1999
 
4369 rajveer 2000
def mark_orders_as_reversal_initiated(vendorId, itemId, quantity, estimate, isReminder):
2001
    if isReminder:
2002
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2003
    else:
2004
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2005
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2006
    for order in orders:
2007
        lineitem = order.lineitems[0]
2008
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2009
            if estimate > 0:
2010
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
2011
            order.status = OrderStatus.LOW_INV_REVERSAL_IN_PROCESS
4362 rajveer 2012
            order.statusDescription = "Reversal Initiated"
4303 rajveer 2013
            quantity = quantity - lineitem.quantity
2014
            store_inventory_action(order, itemId, HotspotAction.REVERSAL_INITIATED, estimate, lineitem.quantity)
2015
            session.commit()
2016
 
4369 rajveer 2017
def mark_orders_as_not_available(vendorId, itemId, quantity, estimate, isReminder):
2018
    if isReminder:
2019
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2020
    else:
2021
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2022
 
2023
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2024
    for order in orders:
2025
        lineitem = order.lineitems[0]
2026
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2027
            order.status = OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT
4362 rajveer 2028
            order.statusDescription = "Not Available"
4303 rajveer 2029
            quantity = quantity - lineitem.quantity
2030
            store_inventory_action(order, itemId, HotspotAction.NOT_AVAILABLE, estimate, lineitem.quantity)
2031
            session.commit()
2032
 
2033
def store_inventory_action(order, itemId, hotspotAction, estimate, quantity):
4369 rajveer 2034
    orderInv = OrderInventory.get_by(order_id=order.id)
2035
    if not orderInv:
2036
        orderInv = OrderInventory()
2037
        orderInv.order = order
4303 rajveer 2038
    orderInv.hotspotAction = hotspotAction  
2039
    orderInv.estimate = estimate
2040
    orderInv.itemId = itemId
2041
    orderInv.timestamp = datetime.datetime.now()
2042
    orderInv.quantity = quantity
2043
 
4556 mandeep.dh 2044
'''    
4369 rajveer 2045
def mark_orders_as_timeout(vendorId):
2046
    ret_timeouts = {}
2047
    orderInvs = OrderInventory.query.all()
2048
    for orderInv in orderInvs:
2049
        if orderInv.timestamp +  timedelta(days=orderInv.estimate) < datetime.datetime.now():
2050
            if not ret_timeouts.has_key(orderInv.itemId):
2051
                timeout = TimeoutSummary()
2052
                ret_timeouts[orderInv.itemId] = timeout
2053
            else:
2054
                timeout = ret_timeouts.get(orderInv.itemId)
2055
            if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
2056
                if timeout.poRaised:
2057
                    timeout.poRaised += 1
2058
                else:
2059
                    timeout.poRaised = 1
2060
 
2061
                if timeout.poEstimate:
2062
                    timeout.poEstimate += orderInv.estimate
2063
                else:
2064
                    timeout.poEstimate = orderInv.estimate
2065
                orderInv.order.status = OrderStatus.LOW_INV_PO_RAISED_TIMEOUT
2066
                orderInv.order.statusDescription = "PO Raised Timeout"
2067
            elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
2068
                if timeout.reversalInitiated:
2069
                    timeout.reversalInitiated += 1
2070
                else:
2071
                    timeout.reversalInitiated = 1
2072
 
2073
                if timeout.reversalEstimate:
2074
                    timeout.reversalEstimate += orderInv.estimate
2075
                else:
2076
                    timeout.reversalEstimate = orderInv.estimate
2077
                orderInv.order.status = OrderStatus.LOW_INV_REVERSAL_TIMEOUT
2078
                orderInv.order.statusDescription = "Reversal Initiated Timeout"
2079
            else:
2080
                orderInv.delete()
2081
    session.commit()
2082
    return ret_timeouts
4556 mandeep.dh 2083
'''
2084
 
2085
 
2086
def mark_orders_as_timeout(vendorId):
2087
    ret_timeouts = {}
2088
    orderInvs = OrderInventory.query.all()
2089
    for orderInv in orderInvs:
2090
        if not ret_timeouts.has_key(orderInv.itemId):
2091
            timeout = TimeoutSummary()
2092
            ret_timeouts[orderInv.itemId] = timeout
2093
        else:
2094
            timeout = ret_timeouts.get(orderInv.itemId)
2095
        if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
2096
            if timeout.poRaised:
2097
                timeout.poRaised += 1
2098
            else:
2099
                timeout.poRaised = 1
2100
 
2101
            if timeout.poEstimate:
2102
                timeout.poEstimate = max(orderInv.estimate, timeout.poEstimate)
2103
            else:
2104
                timeout.poEstimate = orderInv.estimate
2105
        elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
2106
            if timeout.reversalInitiated:
2107
                timeout.reversalInitiated += 1
2108
            else:
2109
                timeout.reversalInitiated = 1
2110
 
2111
            if timeout.reversalEstimate:
2112
                timeout.reversalEstimate = max(orderInv.estimate, timeout.reversalEstimate)
2113
            else:
2114
                timeout.reversalEstimate = orderInv.estimate
2115
        orderInv.order.status = OrderStatus.INVENTORY_LOW
2116
        orderInv.order.statusDescription = "Low Inventory"
2117
        orderInv.delete()
2118
    session.commit()
2119
    return ret_timeouts
2120
 
4386 anupam.sin 2121
def get_order_for_awb(awb):
2122
    order = Order.get_by(airwaybill_no=awb)
2123
    if not order:
2124
        raise TransactionServiceException(108, "no such order")
2125
 
2126
    return order
4369 rajveer 2127
 
4506 phani.kuma 2128
def get_orders_for_provider_for_status(provider_id, order_status):
2129
    if not provider_id or not order_status:
2130
        raise TransactionServiceException(101, "bad provider id or order status")
2131
    query = Order.query.filter_by(logistics_provider_id = provider_id, status = order_status)
2132
    return query.all()
4386 anupam.sin 2133
 
4600 varun.gupt 2134
def get_billed_orders_for_vendor(vendor_id, billing_date_from, billing_date_to):
2135
    query = Order.query.filter_by(vendorId = vendor_id)
2136
    query = query.filter(Order.status != OrderStatus.PAYMENT_PENDING)
2137
    if billing_date_from:
2138
        query = query.filter(Order.billing_timestamp >= billing_date_from)
2139
 
2140
    if billing_date_to:
2141
        query = query.filter(Order.billing_timestamp <= billing_date_to)
2142
 
2143
    return query.all()
2144
 
2145
def save_bluedart_settlements(map_awb_and_amount):
2146
    payment_client = PaymentClient().get_client()
2147
 
2148
    for awb, amount in map_awb_and_amount.iteritems():
2149
        order = Order.get_by(airwaybill_no = awb)
2150
 
2151
        payment = payment_client.getSuccessfulPaymentForTxnId(order.transaction_id)
2152
        settlement = PaymentSettlement()
2153
        settlement.paymentId = payment.paymentId
2154
        settlement.paymentGatewayId = payment.gatewayId
2155
        settlement.netCollection = amount
2156
        session.commit()
2157
 
2158
def save_payment_settlements(settlementDate, paymentGatewayId, paymentId, serviceTax, otherCharges, netCollection):
2159
 
2160
    settlement = PaymentSettlement()
2161
    settlement.settlementDate = settlementDate
2162
    settlement.paymentGatewayId = paymentGatewayId
2163
    settlement.paymentId = paymentId
2164
    settlement.serviceTax = serviceTax
2165
    settlement.otherCharges = otherCharges
2166
    settlement.netCollection = netCollection
2167
    session.commit()
2168
 
2169
def get_settlement_for_paymentId(payment_id):
2170
    payment_settlement = PaymentSettlement.get_by(paymentId = payment_id)
2171
 
2172
    return payment_settlement
2173
 
2174
def save_ebs_settlement_summary(settlement_id, settlement_date, transaction_date_from, transaction_date_to, amount):
2175
    summary = EBSSettlementSummary()
2176
    summary.settlementId = settlement_id
2177
    summary.settlementDate = settlement_date
2178
    summary.transactionDateFrom = transaction_date_from
2179
    summary.transactionDateTo = transaction_date_to
2180
    summary.amount = amount
2181
    summary.detailsUploaded = False
2182
    session.commit()
2183
 
2184
def get_ebs_settlement_summaries():
2185
    summaries = EBSSettlementSummary.query.filter_by(detailsUploaded = False).order_by(EBSSettlementSummary.transactionDateFrom).all()
2186
    summary_map = {}
2187
 
2188
    for summary in summaries:
2189
        transactionDateFrom = str(summary.transactionDateFrom.year) + '-' + str(summary.transactionDateFrom.month) + '-' + str(summary.transactionDateFrom.day)
2190
        transactionDateTo = str(summary.transactionDateTo.year) + '-' + str(summary.transactionDateTo.month) + '-' + str(summary.transactionDateTo.day)
2191
 
2192
        summary_map[summary.settlementId] = "%s to %s" %(transactionDateFrom, transactionDateTo)
2193
 
2194
    return summary_map
2195
 
2196
def get_ebs_settlement_date(settlement_id):
2197
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
2198
 
2199
    if summary:
2200
        return summary.settlementDate
2201
 
2202
def mark_ebs_settlement_uploaded(settlement_id):
2203
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
2204
 
2205
    if summary:
2206
        summary.detailsUploaded = True
2207
        session.commit()
2208
 
766 rajveer 2209
def close_session():
2210
    if session.is_active:
2211
        print "session is active. closing it."
2783 chandransh 2212
        session.close()
3376 rajveer 2213
 
2214
def is_alive():
2215
    try:
2216
        session.query(Transaction.id).limit(1).one()
2217
        return True
2218
    except:
4343 varun.gupt 2219
        return False