Subversion Repositories SmartDukaan

Rev

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