Subversion Repositories SmartDukaan

Rev

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