Subversion Repositories SmartDukaan

Rev

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