Subversion Repositories SmartDukaan

Rev

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