Subversion Repositories SmartDukaan

Rev

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