Subversion Repositories SmartDukaan

Rev

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