Subversion Repositories SmartDukaan

Rev

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