Subversion Repositories SmartDukaan

Rev

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

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