Subversion Repositories SmartDukaan

Rev

Rev 6418 | Rev 6423 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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