Subversion Repositories SmartDukaan

Rev

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