Subversion Repositories SmartDukaan

Rev

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