Subversion Repositories SmartDukaan

Rev

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

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