Subversion Repositories SmartDukaan

Rev

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

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