Subversion Repositories SmartDukaan

Rev

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