Subversion Repositories SmartDukaan

Rev

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