Subversion Repositories SmartDukaan

Rev

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