Subversion Repositories SmartDukaan

Rev

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