Subversion Repositories SmartDukaan

Rev

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