Subversion Repositories SmartDukaan

Rev

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