Subversion Repositories SmartDukaan

Rev

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