Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
4503 mandeep.dh 1
'''
2
Created on 29-Jul-2011
3
 
4
@author: Chandranshu
5
'''
6
from elixir import metadata, setup_all, session
4754 mandeep.dh 7
from shop2020.clients.CatalogClient import CatalogClient
5944 mandeep.dh 8
from shop2020.clients.InventoryClient import InventoryClient
4754 mandeep.dh 9
from shop2020.clients.TransactionClient import TransactionClient
5443 mandeep.dh 10
from shop2020.purchase.main.model.Invoice import Invoice
4503 mandeep.dh 11
from shop2020.purchase.main.model.LineItem import LineItem
12
from shop2020.purchase.main.model.Purchase import Purchase
21621 amit.gupta 13
from shop2020.purchase.main.model.PurchaseOrder import PurchaseOrder
6467 amar.kumar 14
from shop2020.purchase.main.model.PurchaseReturn import PurchaseReturn
21621 amit.gupta 15
from shop2020.purchase.main.model.PurchaseReturnSettlement import \
16
    PurchaseReturnSettlement
5110 mandeep.dh 17
from shop2020.purchase.main.model.RevisionedPurchaseOrder import \
18
    RevisionedPurchaseOrder
4503 mandeep.dh 19
from shop2020.purchase.main.model.Supplier import Supplier
5768 mandeep.dh 20
from shop2020.thriftpy.generic.ttypes import ExceptionType
5944 mandeep.dh 21
from shop2020.thriftpy.model.v1.inventory.ttypes import WarehouseType, \
6832 amar.kumar 22
    InventoryType, ItemStockPurchaseParams
4754 mandeep.dh 23
from shop2020.thriftpy.model.v1.order.ttypes import OrderStatus
24
from shop2020.thriftpy.purchase.ttypes import PurchaseServiceException, POStatus, \
21621 amit.gupta 25
    PurchaseOrder as TPurchaseOrder, LineItem as TLineItem, POType, \
10864 manish.sha 26
    PurchaseReturnType, PurchaseReturnInventoryType
5443 mandeep.dh 27
from shop2020.utils.Utils import to_py_date
4503 mandeep.dh 28
from sqlalchemy import create_engine
5238 mandeep.dh 29
from sqlalchemy.sql.expression import or_
4503 mandeep.dh 30
import datetime
31
import logging
4754 mandeep.dh 32
import sys
21621 amit.gupta 33
import traceback
4503 mandeep.dh 34
 
35
 
36
logging.basicConfig(level=logging.DEBUG)
37
 
38
class PurchaseServiceHandler:
39
    '''
40
    classdocs
41
    '''
42
 
43
    def __init__(self, dbname='warehouse', db_hostname='localhost',  echoOn=True):
44
        '''
45
        Constructor
46
        '''
47
        engine = create_engine('mysql://root:shop2020@' + db_hostname + '/' + dbname, pool_recycle=7200)
48
        metadata.bind = engine
49
        metadata.bind.echo = echoOn
50
        setup_all(True)
51
 
6762 amar.kumar 52
    def getPOforOurExternalBilling(self):
53
        todayDate = datetime.datetime.now()
54
        todayDate = todayDate.replace(hour=0) 
6821 amar.kumar 55
        purchaseOrder = PurchaseOrder.query.filter(PurchaseOrder.supplierId == 1).filter(PurchaseOrder.createdAt > todayDate).filter(PurchaseOrder.type == POType.VIRTUAL).first()
6762 amar.kumar 56
        if purchaseOrder is None:
57
            t_purchaseOrder = TPurchaseOrder()
58
            t_purchaseOrder.supplierId = 1
59
            t_purchaseOrder.createdAt = datetime.datetime.now()
60
            t_purchaseOrder.status = 0
61
            t_purchaseOrder.totalCost = 0
8716 amar.kumar 62
            t_purchaseOrder.warehouseId = 9
6762 amar.kumar 63
            t_purchaseOrder.poNumber = 'Ours-Ext-' + str(todayDate.year) + "-" + str(todayDate.month) + "-" + str(todayDate.day)
6821 amar.kumar 64
            t_purchaseOrder.type = POType.VIRTUAL
6762 amar.kumar 65
            purchaseOrder = PurchaseOrder(t_purchaseOrder)
66
            session.commit()
67
        return purchaseOrder.id    
68
 
7672 rajveer 69
    def updatelineItemforOursExternalBilling(self, poId, itemId, unitPrice, nlc):
6762 amar.kumar 70
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
71
        if lineItem is None:
72
            purchaseOrder = PurchaseOrder.get_by(id=poId)
73
            t_lineItem = TLineItem()
74
            t_lineItem.itemId = itemId
75
            t_lineItem.quantity = 1
76
            t_lineItem.unfulfilledQuantity = 1
77
            t_lineItem.createdAt = datetime.datetime.now()
78
            t_lineItem.unitPrice = unitPrice
7672 rajveer 79
            t_lineItem.nlc = nlc
6762 amar.kumar 80
            t_lineItem.fulfilled = False
81
            lineItem = LineItem(purchaseOrder, t_lineItem)
82
        else:
83
            lineItem.quantity = lineItem.quantity + 1
84
            lineItem.fulfilled = False
85
            lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity + 1
86
        session.commit()
87
 
88
    def receiveinvoiceforOursExternalBilling(self, invoiceNumber):
89
        invoice = Invoice()
90
        invoice.invoiceNumber = invoiceNumber
91
        invoice.date = datetime.datetime.now()
92
        invoice.numItems = 1
93
        invoice.receivedFrom = "Hotspot-Billing"
94
        invoice.supplierId = 1
11219 manish.sha 95
        invoice.invoiceDate = datetime.datetime.now()
6762 amar.kumar 96
        session.commit()
97
 
98
    def createPurchaseforOursExternalBilling(self, poId, invoiceNumber):
99
        purchaseOrder = PurchaseOrder.get_by(id=poId)
100
        purchase = Purchase(purchaseOrder, invoiceNumber, 0)
101
        session.commit()
102
        return purchase.id
103
 
4503 mandeep.dh 104
    def createPurchaseOrder(self, tPurchaseOrder):
105
        """
106
        Creates a purchase order based on the data in the given purchase order object.
107
        This method populates a number of missing fields
108
 
109
        Parameters:
110
         - purchaseOrder
111
        """
112
        try:
113
            purchaseOrder = PurchaseOrder(tPurchaseOrder)
114
            session.commit()
115
            purchaseOrder.set_po_number()
116
            session.commit()
117
            return purchaseOrder.id
118
        finally:
119
            self.close_session()
120
 
121
    def getAllPurchaseOrders(self, status):
122
        """
123
        Returns a list of all the purchase orders in the given state
124
 
125
        Parameters:
126
         - status
127
        """
128
        try:
6821 amar.kumar 129
            pos = PurchaseOrder.query.filter_by(status=status, type=POType.REAL).all()
4503 mandeep.dh 130
            return [po.to_thrift_object() for po in pos ]
131
        finally:
132
            self.close_session()
133
 
134
    def getPurchaseOrder(self, id):
135
        """
136
        Returns the purchase order with the given id. Throws an exception if there is no such purchase order.
137
 
138
        Parameters:
139
         - id
140
        """
141
        try:
142
            purchaseOrder = PurchaseOrder.get_by(id=id)
143
            if not purchaseOrder:
144
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id)) 
145
            return purchaseOrder.to_thrift_object()
146
        finally:
147
            self.close_session()
148
 
149
    def getSupplier(self, id):
150
        """
151
        Returns the supplier with the given order id. Throws an exception if there is no such supplier.
152
 
153
        Parameters:
154
         - id
155
        """
156
        try:
157
            return Supplier.get_by(id=id).to_thrift_object()
158
        finally:
159
            self.close_session()
160
 
11801 manish.sha 161
    def startPurchase(self, purchaseOrderId, invoiceNumber, freightCharges, purchaseComments):
4503 mandeep.dh 162
        """
163
        Creates a purchase for the given purchase order.
164
        Throws an exception if no more purchases are allowed against the given purchase order.
165
 
166
        Parameters:
167
         - purchaseOrderId
168
         - invoiceNumber
169
         - freightCharges
170
        """
171
        try:
6762 amar.kumar 172
            purchase_order = PurchaseOrder.get_by(id=purchaseOrderId)
11801 manish.sha 173
            purchase = Purchase(purchase_order, invoiceNumber, freightCharges, purchaseComments)
4503 mandeep.dh 174
            session.commit()
175
            return purchase.id
176
        finally:
177
            self.close_session()
178
 
179
    def closePurchase(self, purchaseId):
180
        """
181
        Marks a purchase as complete and updates the receivedOn time.
182
        Throws an exception if no such purchase exists.
183
 
184
        Parameters:
185
         - purchaseId
186
        """
187
        try:
188
            purchase = Purchase.get_by(id=purchaseId)
189
            purchase.receivedOn = datetime.datetime.now()
190
            session.commit()
191
        finally:
192
            self.close_session()
193
 
194
    def getAllPurchases(self, purchaseOrderId, open):
195
        """
196
        Returns all open or closed purchases for the given purchase order. Throws an exception if no such purchase order exists
197
 
198
        Parameters:
199
         - purchaseOrderId
200
         - open
201
        """
202
        try:
203
            if open:
6762 amar.kumar 204
                purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId, receivedOn=None).all()
4503 mandeep.dh 205
            else:
6762 amar.kumar 206
                purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId).filter(Purchase.receivedOn != None).all()
4503 mandeep.dh 207
 
208
            return [purchase.to_thrift_object() for purchase in purchases]
209
        finally:
210
            self.close_session()
6385 amar.kumar 211
 
212
    def getPurchasesForPO(self, purchaseOrderId):
213
        """
214
        Returns all purchases for the given purchase order. Throws an exception if no such purchase order exists
215
 
216
        Parameters:
217
         - purchaseOrderId
218
         - open
219
        """
220
        try:
6762 amar.kumar 221
            purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId).all()
6385 amar.kumar 222
            return [purchase.to_thrift_object() for purchase in purchases]
223
        finally:
224
            self.close_session()
4503 mandeep.dh 225
 
6385 amar.kumar 226
 
4555 mandeep.dh 227
    def getPurchaseOrderForPurchase(self, purchaseId):
4503 mandeep.dh 228
        """
4555 mandeep.dh 229
        Returns the purchase order for a given purchase
4503 mandeep.dh 230
 
231
        Parameters:
232
         - purchaseId
233
        """
4555 mandeep.dh 234
        try:
6762 amar.kumar 235
            return self.getPurchaseOrder(Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id)
4555 mandeep.dh 236
        finally:
237
            self.close_session()
4503 mandeep.dh 238
 
4754 mandeep.dh 239
    def getPendingPurchaseOrders(self, warehouseId):
240
        """
241
        Creates purchase order objects from pending orders
242
 
243
        Parameters:
244
         - warehouseId
245
        """
246
        try:
247
            purchaseOrders = []
248
            if not warehouseId:
249
                raise PurchaseServiceException(101, "bad warehouse id")
250
 
251
            transactionClient = TransactionClient().get_client()
18426 manish.sha 252
            pending_orders = transactionClient.getOrdersInBatch([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.ACCEPTED, OrderStatus.COD_VERIFICATION_PENDING], 0, 0, warehouseId, 0)
4754 mandeep.dh 253
 
254
            if not pending_orders:
255
                return purchaseOrders
256
 
5944 mandeep.dh 257
            inventory_client = InventoryClient().get_client()
4754 mandeep.dh 258
            availability = {}
5110 mandeep.dh 259
 
5944 mandeep.dh 260
            ourGoodWarehouseIds = [w.id for w in inventory_client.getWarehouses(WarehouseType.OURS, InventoryType.GOOD, 0, None, warehouseId)]
261
            itemInventorySnapshot = inventory_client.getInventorySnapshot(0)
262
            for itemId, itemInventory in itemInventorySnapshot.iteritems():
7105 amar.kumar 263
                '''item = self.__get_item_from_master(itemId)'''
5944 mandeep.dh 264
                for warehouseId, quantity in itemInventory.availability.iteritems():
265
                    if warehouseId in ourGoodWarehouseIds:
7105 amar.kumar 266
                        if availability.has_key(itemId):
267
                            availability[itemId] = [availability[itemId][0] + quantity]
5944 mandeep.dh 268
                        else:
7105 amar.kumar 269
                            availability[itemId] = [quantity]
4754 mandeep.dh 270
 
6880 amar.kumar 271
            previouslyOrderedQty = {}
6821 amar.kumar 272
            unfulfilledPurchaseOrders = PurchaseOrder.query.filter(or_(PurchaseOrder.status == POStatus.PARTIALLY_FULFILLED, PurchaseOrder.status == POStatus.READY)).filter(PurchaseOrder.type == POType.REAL).all()
5238 mandeep.dh 273
            for purchaseOrder in unfulfilledPurchaseOrders:
274
                for lineitem in purchaseOrder.lineitems:
6880 amar.kumar 275
                    if previouslyOrderedQty.has_key(lineitem.itemId):
276
                        previouslyOrderedQty[lineitem.itemId] = previouslyOrderedQty[lineitem.itemId] + lineitem.unfulfilledQuantity
277
                    else:
278
                        previouslyOrderedQty[lineitem.itemId] = lineitem.unfulfilledQuantity
279
 
5238 mandeep.dh 280
                    if availability.has_key(lineitem.itemId):
7105 amar.kumar 281
                        availability[lineitem.itemId] = [availability[lineitem.itemId][0] + lineitem.unfulfilledQuantity]
5238 mandeep.dh 282
                    else:
7105 amar.kumar 283
                        '''item = self.__get_item_from_master(lineitem.itemId)'''
7106 amar.kumar 284
                        availability[lineitem.itemId] = [lineitem.unfulfilledQuantity]
5238 mandeep.dh 285
 
4754 mandeep.dh 286
            codRequirements = {}
287
            requirements = {}
288
            for order in pending_orders:
4758 mandeep.dh 289
                if order.purchaseOrderId:
4757 mandeep.dh 290
                    continue
4754 mandeep.dh 291
                for lineitem in order.lineitems:
292
                    if (requirements.has_key(lineitem.item_id)):
293
                        requirements[lineitem.item_id] += lineitem.quantity
294
                    else:
295
                        requirements[lineitem.item_id] = lineitem.quantity
296
 
297
                    if order.cod:
298
                        if (codRequirements.has_key(lineitem.item_id)):
299
                            codRequirements[lineitem.item_id] += lineitem.quantity
300
                        else:
301
                            codRequirements[lineitem.item_id] = lineitem.quantity
6821 amar.kumar 302
 
303
            advancedPOParameters = {}
6857 amar.kumar 304
            SKUListForPO = []
305
            inventory_client = InventoryClient().get_client()
306
            itemStockPurchaseParams = inventory_client.getNonZeroItemStockPurchaseParams()
307
            for itemStockPurchaseParam in itemStockPurchaseParams:
308
                inventory_client = InventoryClient().get_client()
9696 amar.kumar 309
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(itemStockPurchaseParam.item_id, 0, 3)
6857 amar.kumar 310
                salesCount = 0
311
                numDaysInStock = 0
8182 amar.kumar 312
                rtoCount = 0
6857 amar.kumar 313
                avgSales = 0.0
314
                lastXdaysSale ="" 
315
                for oosStatus in oosStatuses:
316
                    if oosStatus.is_oos == False:
317
                        salesCount = salesCount + oosStatus.num_orders
318
                        numDaysInStock = numDaysInStock + 1
319
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
320
                    else:
321
                        lastXdaysSale = lastXdaysSale + "X-"
8221 amar.kumar 322
                if oosStatus.rto_orders is not None:
8182 amar.kumar 323
                    rtoCount = oosStatus.rto_orders
6857 amar.kumar 324
                lastXdaysSale = lastXdaysSale[:-1]
325
                if numDaysInStock>0:
326
                    avgSales = float(salesCount)/numDaysInStock
8182 amar.kumar 327
                advancedPOParameters[itemStockPurchaseParam.item_id] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2) , numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6857 amar.kumar 328
                if itemInventorySnapshot.has_key(itemStockPurchaseParam.item_id):
329
                    itemAvailability = itemInventorySnapshot.get(itemStockPurchaseParam.item_id)
330
                    currentAvailability = 0
331
                    currentReserved = 0
332
                    for wId, rQty in itemAvailability.reserved.iteritems():
333
                        if wId in ourGoodWarehouseIds:
334
                            currentReserved = currentReserved + rQty
9261 manish.sha 335
                    #Key Condition Added By Manish Sharma        
336
                    if availability.has_key(itemStockPurchaseParam.item_id):
337
                        if availability[itemStockPurchaseParam.item_id] is None:
338
                                availability[itemStockPurchaseParam.item_id] = [0]
339
                    else:
8182 amar.kumar 340
                        availability[itemStockPurchaseParam.item_id] = [0]
9261 manish.sha 341
                    if (availability[itemStockPurchaseParam.item_id][0] - currentReserved) < max(advancedPOParameters[itemStockPurchaseParam.item_id][0], advancedPOParameters[itemStockPurchaseParam.item_id][3]):
6857 amar.kumar 342
                        SKUListForPO.append(itemStockPurchaseParam.item_id)
343
                else:
344
                    SKUListForPO.append(itemStockPurchaseParam.item_id)
345
 
6821 amar.kumar 346
            for key in requirements:
6857 amar.kumar 347
                if advancedPOParameters.has_key(key):
348
                    continue
12175 manish.sha 349
                print "Item Id ---", key
6821 amar.kumar 350
                inventory_client = InventoryClient().get_client()
9696 amar.kumar 351
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(key, 0, 3)
6821 amar.kumar 352
                salesCount = 0
353
                numDaysInStock = 0
8182 amar.kumar 354
                rtoCount = 0
6857 amar.kumar 355
                avgSales = 0.0
356
                lastXdaysSale = ""
21620 amit.gupta 357
                if not oosStatuses:
358
                    continue
6821 amar.kumar 359
                for oosStatus in oosStatuses:
6832 amar.kumar 360
                    if oosStatus.is_oos == False:
6821 amar.kumar 361
                        salesCount = salesCount + oosStatus.num_orders
362
                        numDaysInStock = numDaysInStock + 1
6857 amar.kumar 363
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
364
                    else:
365
                        lastXdaysSale = lastXdaysSale + "X-"
8182 amar.kumar 366
                lastXdaysSale = lastXdaysSale[:-1]
367
                if oosStatus.rto_orders:
368
                    rtoCount = oosStatus.rto_orders
6832 amar.kumar 369
                if numDaysInStock>0:
6857 amar.kumar 370
                    avgSales = float(salesCount)/float(numDaysInStock)
18588 manish.sha 371
                itemStockPurchaseParam = None
10864 manish.sha 372
                try:
373
                    itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
374
                except Exception as e:
375
                    inventory_client.updateItemStockPurchaseParams(key, 0, 0)
376
                    itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
18588 manish.sha 377
 
378
                if itemStockPurchaseParam.numOfDaysStock is None:
379
                    itemStockPurchaseParam.minStockLevel = 0
380
                    itemStockPurchaseParam.numOfDaysStock = 0
381
                    itemStockPurchaseParam.item_id = key
382
 
8182 amar.kumar 383
                advancedPOParameters[key] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2), numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6821 amar.kumar 384
 
6857 amar.kumar 385
            cumulativeRequirementsItemIds = list(set(requirements.keys()+SKUListForPO))
4754 mandeep.dh 386
            netRequirements = {}
6857 amar.kumar 387
            for itemId in cumulativeRequirementsItemIds:
12341 manish.sha 388
                print "Item Id for Preferred Vendor", itemId
4754 mandeep.dh 389
                requirementsCount = requirements.get(itemId)
6857 amar.kumar 390
                if requirementsCount is None:
391
                    requirementsCount = 0.0
4754 mandeep.dh 392
                if  availability.has_key(itemId):
393
                    availabilityCount = availability.get(itemId)[0]
7105 amar.kumar 394
                    item = self.__get_item_from_master(itemId)
6857 amar.kumar 395
                    if requirementsCount > availabilityCount or itemId in SKUListForPO:
5238 mandeep.dh 396
                        if item.preferredVendor is None:
397
                            raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 398
                        if (netRequirements.has_key(item.preferredVendor)):
399
                            netRequirements[item.preferredVendor].append([item, requirementsCount - availabilityCount])
400
                        else:
401
                            netRequirements[item.preferredVendor] = [[item, requirementsCount - availabilityCount]];
402
                else:
5944 mandeep.dh 403
                    item = self.__get_item_from_master(itemId)
4754 mandeep.dh 404
                    if item.preferredVendor is None:
5238 mandeep.dh 405
                        raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 406
                    if (netRequirements.has_key(item.preferredVendor)):
407
                        netRequirements[item.preferredVendor].append([item, requirementsCount])
408
                    else:
409
                        netRequirements[item.preferredVendor] = [[item, requirementsCount]];
5238 mandeep.dh 410
 
4754 mandeep.dh 411
            if not netRequirements:
412
                return purchaseOrders
413
 
414
            for vendorId in netRequirements.keys():
415
                t_purchase_order = TPurchaseOrder()
416
                t_purchase_order.supplierId = vendorId
417
                t_purchase_order.warehouseId = warehouseId
418
                t_purchase_order.lineitems = []
419
                for key in netRequirements.get(vendorId):
6762 amar.kumar 420
                    item = key[0]
21622 amit.gupta 421
                    if not advancedPOParameters.has_key(item.id):
422
                        continue
4754 mandeep.dh 423
                    quantity = key[1]
424
                    t_po_lineitem = TLineItem()
425
                    t_po_lineitem.productGroup = item.productGroup
426
                    t_po_lineitem.brand = item.brand
427
                    t_po_lineitem.modelNumber = item.modelNumber
428
                    t_po_lineitem.modelName = item.modelName
429
                    t_po_lineitem.color = item.color
430
                    t_po_lineitem.itemId = item.id
6938 amar.kumar 431
                    if quantity <0: #TODO Check this logic
6882 amar.kumar 432
                        quantity=0
6861 amar.kumar 433
                    t_po_lineitem.quantity = quantity
6832 amar.kumar 434
                    t_po_lineitem.availableQuantity = 0
435
                    if availability.has_key(item.id):
6880 amar.kumar 436
                        if previouslyOrderedQty.has_key(item.id):
437
                            t_po_lineitem.availableQuantity = availability[item.id][0] - previouslyOrderedQty[item.id]
438
                        else:
439
                            t_po_lineitem.availableQuantity = availability[item.id][0]
6857 amar.kumar 440
                    if requirements.has_key(item.id):
441
                        t_po_lineitem.reservedQuantity = requirements[item.id]
8221 amar.kumar 442
                    additionalQty = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3])
443
                    additionalQty = max(0,(additionalQty - (advancedPOParameters[item.id][6]/2)))
444
                    suggestedQuantity = additionalQty +key[1]
445
                    t_po_lineitem.suggestedQuantity = max(0,suggestedQuantity)
446
                    #t_po_lineitem.suggestedQuantity = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3]) + key[1]
6821 amar.kumar 447
                    t_po_lineitem.avgSales = advancedPOParameters[item.id][1]
448
                    t_po_lineitem.numberOfDaysInStock = advancedPOParameters[item.id][2] 
449
                    t_po_lineitem.minStockLevel = advancedPOParameters[item.id][3]
6857 amar.kumar 450
                    t_po_lineitem.numberOfDaysStock = advancedPOParameters[item.id][4]
6880 amar.kumar 451
                    t_po_lineitem.lastXdaysSale = advancedPOParameters[item.id][5]
8182 amar.kumar 452
                    t_po_lineitem.rtoOrders = advancedPOParameters[item.id][6]
6880 amar.kumar 453
                    if previouslyOrderedQty.has_key(item.id):
454
                        t_po_lineitem.previouslyOrderedQty = previouslyOrderedQty[item.id]
455
                    else:
456
                        t_po_lineitem.previouslyOrderedQty = 0
4754 mandeep.dh 457
                    if codRequirements.has_key(item.id):
458
                        t_po_lineitem.codCount = min(codRequirements[item.id], quantity)
459
                    try:
5944 mandeep.dh 460
                        item_pricing = inventory_client.getItemPricing(item.id, vendorId)
4754 mandeep.dh 461
                    except Exception as e:
462
                        vendor = self.getSupplier(vendorId)
463
                        print 'Could not find transfer price for Item id: ' + str(item.id) + ' and vendor id: ' + str(vendorId)
464
                        print e
465
                        raise PurchaseServiceException(101, 'Transfer price missing for ' + vendor.name + ' and ' + " ".join([item.brand, item.modelName, item.modelNumber, item.color]))
466
                    t_po_lineitem.unitPrice = item_pricing.transferPrice
7672 rajveer 467
                    t_po_lineitem.nlc = item_pricing.nlc
9416 amar.kumar 468
                    t_po_lineitem.mrp = item.mrp
4754 mandeep.dh 469
                    t_purchase_order.lineitems.append(t_po_lineitem)
470
                purchaseOrders.append(t_purchase_order)
471
            return purchaseOrders
7105 amar.kumar 472
        except Exception as e:
473
            print e
8199 amar.kumar 474
            print sys.exc_info()[0]
21621 amit.gupta 475
            traceback.print_exc()
4754 mandeep.dh 476
        finally:
477
            self.close_session()
478
 
6762 amar.kumar 479
    def getSuppliers(self,):
4754 mandeep.dh 480
        """
481
        Returns all the valid suppliers
482
        """
483
        try:
21619 amit.gupta 484
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.filter(Supplier.id > 220).all()]
4754 mandeep.dh 485
        finally:
486
            self.close_session()
487
 
5185 mandeep.dh 488
    def unFulfillPO(self, purchaseId, itemId, quantity):
489
        """
490
        Unfulfills a given purchase id and an item with its quantity.
491
 
492
        Parameters:
493
         - purchaseId
494
         - itemId
495
         - quantity
496
        """
497
        try:
6762 amar.kumar 498
            purchaseOrderId = Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id
499
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
5185 mandeep.dh 500
            if lineitems:
501
                fulfilledQuantity = lineitems[0].quantity - lineitems[0].unfulfilledQuantity
502
                if fulfilledQuantity < quantity:
503
                    raise PurchaseServiceException(101, 'Can UnFulfill only ' + str(fulfilledQuantity) + 'quantity')
504
                else:
5437 mandeep.dh 505
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity + quantity
5185 mandeep.dh 506
                    lineitems[0].fulfilled = 0
507
                    purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
508
                    purchaseOrder.status = POStatus.PARTIALLY_FULFILLED
509
                    session.commit()
510
                    return
511
 
512
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
513
        finally:
514
            self.close_session()        
515
 
4754 mandeep.dh 516
    def fulfillPO(self, purchaseOrderId, itemId, quantity):
517
        """
518
        Fulfills a given purchase order with an item.
519
 
520
        Parameters:
521
         - purchaseOrderId
522
         - itemId
523
         - quantity
524
        """
525
        try:
6762 amar.kumar 526
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
4754 mandeep.dh 527
            if lineitems:
528
                if lineitems[0].unfulfilledQuantity < quantity:
5361 mandeep.dh 529
                    raise PurchaseServiceException(101, 'Can fulfill only ' + str(lineitems[0].unfulfilledQuantity) + ' quantity')
4754 mandeep.dh 530
                else:
5361 mandeep.dh 531
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity - quantity
4754 mandeep.dh 532
                    if not lineitems[0].unfulfilledQuantity:
533
                        lineitems[0].fulfilled = 1
5361 mandeep.dh 534
                        session.commit()
6762 amar.kumar 535
                        if not LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, fulfilled=0).all():
5361 mandeep.dh 536
                            purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
4754 mandeep.dh 537
                            purchaseOrder.status = POStatus.CLOSED
538
                    session.commit()
539
                    return
540
 
6762 amar.kumar 541
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
4754 mandeep.dh 542
        finally:
543
            self.close_session()
544
 
545
    def updatePurchaseOrder(self, purchaseOrder):
546
        """
547
        Amends a PO sa per the new lineitems passed
548
 
549
        Parameters:
550
         - purchaseOrder
551
        """
552
        try:
6762 amar.kumar 553
            existingPurchaseOrder = PurchaseOrder.get_by(id=purchaseOrder.id)
4754 mandeep.dh 554
            maxRevision = 0
6762 amar.kumar 555
            existingRevisions = RevisionedPurchaseOrder.query.filter_by(purchaseOrderId=purchaseOrder.id).all()
4754 mandeep.dh 556
            if existingRevisions:
557
                maxRevision = max([a.revision for a in existingRevisions]) + 1
5147 mandeep.dh 558
 
559
            newPOItems = {}
560
            for t_lineitem in purchaseOrder.lineitems:
561
                newPOItems[t_lineitem.itemId] = t_lineitem
562
 
4754 mandeep.dh 563
            for lineitem in existingPurchaseOrder.lineitems:
5147 mandeep.dh 564
                fulfilledQuantity = lineitem.quantity - lineitem.unfulfilledQuantity
565
                if fulfilledQuantity:
566
                    if not newPOItems.has_key(lineitem.itemId):
567
                        raise PurchaseServiceException(101, 'Cannot remove fulfilled item id: ' + str(lineitem.itemId) + ' from PO')
568
                    else:
569
                        if newPOItems[lineitem.itemId].quantity < fulfilledQuantity:
570
                            raise PurchaseServiceException(101, 'More quantity already fulfilled for item id: ' + str(lineitem.itemId))
571
                        else:
5437 mandeep.dh 572
                            newPOItems[lineitem.itemId].unfulfilledQuantity = newPOItems[lineitem.itemId].unfulfilledQuantity - fulfilledQuantity
4754 mandeep.dh 573
                revisionedPurchaseOrder = RevisionedPurchaseOrder()
574
                revisionedPurchaseOrder.purchaseOrderId = purchaseOrder.id
575
                revisionedPurchaseOrder.revision = maxRevision
576
                revisionedPurchaseOrder.itemId = lineitem.itemId
577
                revisionedPurchaseOrder.unfulfilledQuantity = lineitem.unfulfilledQuantity
578
                revisionedPurchaseOrder.unitPrice = lineitem.unitPrice
7672 rajveer 579
                revisionedPurchaseOrder.nlc = lineitem.nlc
4754 mandeep.dh 580
                revisionedPurchaseOrder.createdAt = lineitem.createdAt
581
                revisionedPurchaseOrder.quantity = lineitem.quantity
582
                lineitem.delete()
583
            existingPurchaseOrder.lineitems = [LineItem(existingPurchaseOrder, t_lineitem) for t_lineitem in purchaseOrder.lineitems]
584
            existingPurchaseOrder.totalCost = sum([t_lineitem.quantity * t_lineitem.unitPrice for t_lineitem in purchaseOrder.lineitems])
585
            session.commit()
586
        finally:
587
            self.close_session()
588
 
4503 mandeep.dh 589
    def close_session(self):
590
        if session.is_active:
591
            print "session is active. closing it."
592
            session.close()
593
 
5443 mandeep.dh 594
    def getInvoices(self, date):
595
        """
596
        Fetches all invoices for a given date
597
 
598
        Parameters:
599
         - date
600
        """
601
        try:
602
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).all()]
603
        finally:
604
            self.close_session()
6630 amar.kumar 605
 
7410 amar.kumar 606
    def getInvoicesForWarehouse(self, warehouseId, supplierId, date):
607
        """
608
        Fetches all invoices for a given date for specified physical warehouse
609
 
610
        Parameters:
611
         - date
612
        """
613
        try:
614
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).filter(Invoice.warehouseId == warehouseId).filter(Invoice.supplierId == supplierId).all()]
615
        finally:
616
            self.close_session()
617
 
6630 amar.kumar 618
    def getInvoice(self, invoiceNumber, supplierId):
619
        """
620
        Fetches all invoices for  given invoiceNumber and supplierId 
5443 mandeep.dh 621
 
6630 amar.kumar 622
        Parameters:
623
         - invoiceNumber, supplierId
624
        """
625
        try:
6762 amar.kumar 626
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
6638 amar.kumar 627
            if invoice is None:
6762 amar.kumar 628
                return None
6638 amar.kumar 629
            else:
630
                return invoice.to_thrift_object()
6630 amar.kumar 631
        finally:
632
            self.close_session()
633
 
5443 mandeep.dh 634
    def createInvoice(self, invoice):
635
        """
636
        Creates an invoice object
637
 
638
        Parameters:
639
         - invoice
640
        """
641
        try:
6762 amar.kumar 642
            if Invoice.query.filter_by(supplierId=invoice.supplierId, date=to_py_date(invoice.date), invoiceNumber=invoice.invoiceNumber).all():
5768 mandeep.dh 643
                raise PurchaseServiceException(ExceptionType.ILLEGAL_ARGUMENTS, "Already received such invoice")
5443 mandeep.dh 644
            invoiceObj = Invoice()
645
            invoiceObj.invoiceNumber = invoice.invoiceNumber
646
            invoiceObj.date = to_py_date(invoice.date)
647
            invoiceObj.receivedFrom = invoice.receivedFrom
648
            invoiceObj.numItems = invoice.numItems
649
            invoiceObj.supplierId = invoice.supplierId
7410 amar.kumar 650
            invoiceObj.warehouseId = invoice.warehouseId
11219 manish.sha 651
            invoiceObj.invoiceDate = to_py_date(invoice.invoiceDate)
5443 mandeep.dh 652
            session.commit()
653
        finally:
654
            self.close_session()        
655
 
5591 mandeep.dh 656
    def addSupplier(self, supplier):
657
        """
658
        Creates a supplier
659
 
660
        Parameters:
661
         - supplier
662
        """
663
        try:
664
            supplierObj = Supplier()
665
            supplierObj.communicationAddress = supplier.communicationAddress
666
            supplierObj.contactEmail = supplier.contactEmail
667
            supplierObj.contactFax = supplier.contactFax
668
            supplierObj.contactName = supplier.contactName
669
            supplierObj.contactPhone = supplier.contactPhone
670
            supplierObj.fax = supplier.fax
671
            supplierObj.headDesignation = supplier.headDesignation
672
            supplierObj.headEmail = supplier.headEmail
673
            supplierObj.headName = supplier.headName
674
            supplierObj.name = supplier.name
675
            supplierObj.pan = supplier.pan
676
            supplierObj.phone = supplier.phone
677
            supplierObj.registeredAddress = supplier.registeredAddress
678
            supplierObj.tin = supplier.tin
10295 amar.kumar 679
            supplierObj.stateId = supplier.stateId
14072 manish.sha 680
            supplierObj.poValidityLimit = supplier.poValidityLimit
5591 mandeep.dh 681
            session.commit()
682
            return self.getSupplier(supplierObj.id)
683
        finally:
684
            self.close_session()
685
 
686
    def updateSupplier(self, supplier):
687
        """
688
        Updates a supplier
689
 
690
        Parameters:
691
         - supplier
692
        """
693
        try:
694
            supplierObj = Supplier.get(supplier.id)
695
            supplierObj.communicationAddress = supplier.communicationAddress
696
            supplierObj.contactEmail = supplier.contactEmail
697
            supplierObj.contactFax = supplier.contactFax
698
            supplierObj.contactName = supplier.contactName
699
            supplierObj.contactPhone = supplier.contactPhone
700
            supplierObj.fax = supplier.fax
701
            supplierObj.headDesignation = supplier.headDesignation
702
            supplierObj.headEmail = supplier.headEmail
703
            supplierObj.headName = supplier.headName
704
            supplierObj.name = supplier.name
705
            supplierObj.pan = supplier.pan
706
            supplierObj.phone = supplier.phone
707
            supplierObj.registeredAddress = supplier.registeredAddress
708
            supplierObj.tin = supplier.tin
13965 manish.sha 709
            supplierObj.stateId = supplierObj.stateId
14072 manish.sha 710
            supplierObj.poValidityLimit = supplier.poValidityLimit
5591 mandeep.dh 711
            session.commit()
712
        finally:
713
            self.close_session()
714
 
6385 amar.kumar 715
    def getInvoicesForPO(self, poNumber):
716
        '''
717
        For getting invoiceNumbers for a Purchase Order
718
        '''
719
        try:
720
 
6762 amar.kumar 721
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 722
            for purchase in purchases:
723
                invoice = purchase.invoiceNumber
724
        except:
725
            return None
726
        finally:
727
            self.close_session()
6467 amar.kumar 728
 
729
    def createPurchaseReturn(self, t_purchaseReturn):
730
        '''
731
        For creating a new Purchase Return
732
        '''
733
        try:
6762 amar.kumar 734
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 735
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
736
            purchaseReturn.amount = t_purchaseReturn.amount
737
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
738
            purchaseReturn.isSettled = False
6821 amar.kumar 739
            purchaseReturn.type = t_purchaseReturn.type
10864 manish.sha 740
            purchaseReturn.returnInventoryType = t_purchaseReturn.returnInventoryType
13600 manish.sha 741
            purchaseReturn.unsettledAmount = t_purchaseReturn.amount
6467 amar.kumar 742
            session.commit()
743
            return purchaseReturn.id
744
        except Exception as e:
745
            print e
746
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
747
        finally:
748
            self.close_session()
749
 
750
    def getUnsettledPurchaseReturns(self):
751
        '''
752
        For getting all unsettled Purchase Returns
753
        '''
754
        try:
6821 amar.kumar 755
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 756
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
757
        except Exception as e:
758
            print e
759
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
760
        finally:
761
            self.close_session()
6385 amar.kumar 762
 
6467 amar.kumar 763
    def settlePurchaseReturn(self, returnId):
764
        '''
765
        For marking a Purchase Return as settled
766
        '''
767
        try:
6762 amar.kumar 768
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 769
            purchaseReturn.isSettled = True
770
            session.commit()
771
        except Exception as e:
772
            print e
773
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
774
        finally:
775
            self.close_session()
6762 amar.kumar 776
 
7672 rajveer 777
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, nlc, itemId):
6762 amar.kumar 778
        try:
779
            poId = self.getPOforOurExternalBilling()
7672 rajveer 780
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice, nlc)
6762 amar.kumar 781
            self.receiveinvoiceforOursExternalBilling(invoiceNumber)
782
            return self.createPurchaseforOursExternalBilling(poId, invoiceNumber)
783
        except Exception as e:
784
            print e
785
            raise PurchaseServiceException(101, '')
786
        finally:
787
            self.close_session()
788
 
789
    def fulfillPOForExtBilling(self, itemId, quantity):
790
        poId = self.getPOforOurExternalBilling()
791
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
792
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
793
        if not lineItem.unfulfilledQuantity:
794
            lineItem.fulfilled = 1
795
        session.commit()
7410 amar.kumar 796
 
797
    def closePO(self, poId):
798
        purchaseOrder = PurchaseOrder.get_by(id=poId)
799
        if not purchaseOrder:
800
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
801
        purchaseOrder.status = 4
802
        session.commit()
9925 amar.kumar 803
 
804
    def changePOStatus(self, poId, poStatus):
805
        purchaseOrder = PurchaseOrder.get_by(id=poId)
806
        if not purchaseOrder:
807
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
808
        purchaseOrder.status = POStatus.READY
809
        session.commit()
6467 amar.kumar 810
 
7410 amar.kumar 811
    def isInvoiceReceived(self, invoiceNumber, supplierId):
812
        """
813
        Returns whether invoice is already received for given invoiceNumber and supplierId 
814
 
815
        Parameters:
816
         - invoiceNumber, supplierId
817
        """
818
        try:
819
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
820
            if invoice is None:
821
                return False
822
            else:
823
                return True
824
        finally:
825
            self.close_session()
9829 amar.kumar 826
 
827
    def changeWarehouseForPO(self, poId, warehouseId):
828
        try:
829
            purchaseOrder = PurchaseOrder.get_by(id = poId)
830
            for lineitem in purchaseOrder.lineitems:
831
                if lineitem.quantity!=lineitem.unfulfilledQuantity:
832
                    raise PurchaseServiceException(101, 'Items have already been received for this PO and hence cant change warehouse')
833
            purchaseOrder.warehouseId = warehouseId
834
            session.commit()
835
        finally:
11751 manish.sha 836
            self.close_session()  
837
 
838
    def getPurchaseReturn(self, id):
839
        """
840
        Returns the purchase return with the given id. Throws an exception if there is no such purchase return.
841
 
842
        Parameters:
843
         - id
844
        """
845
        try:
846
            purchaseReturn = PurchaseReturn.get_by(id=id)
847
            if not purchaseReturn:
848
                raise PurchaseServiceException(101, "No purchase return can be found with id:" + str(id)) 
849
            return purchaseReturn.to_thrift_object()
850
        finally:
851
            self.close_session()
9829 amar.kumar 852
 
13600 manish.sha 853
    def markPurchasereturnSettled(self, id, settlementType, documentNumber, settlementBy, settledAmount):
854
        try:
855
            currentTime = datetime.datetime.now()
856
            purchaseReturn = PurchaseReturn.get_by(id=id)
857
            if not purchaseReturn:
858
                raise PurchaseServiceException(101, "No purchase return can be found with id:" + str(id)) 
859
            if settledAmount > purchaseReturn.unsettledAmount:
860
                raise PurchaseServiceException(101, "Purchase Return Settled Amount Can't be Greater than Unsettled Amount Purchase Return id:" + str(id))
861
            purchaseReturn.currentSettlementType = settlementType
862
            purchaseReturn.latestSettlementDate = currentTime
863
            if purchaseReturn.documentNumber : 
864
                purchaseReturn.documentNumber = purchaseReturn.documentNumber +";"+documentNumber
865
            else:
866
                purchaseReturn.documentNumber = documentNumber
867
            unsettledAmount = purchaseReturn.unsettledAmount - settledAmount
868
            purchaseReturn.unsettledAmount = purchaseReturn.unsettledAmount - settledAmount
869
            if unsettledAmount ==0:
870
                purchaseReturn.isSettled = 1
871
 
872
            purchaseReturnSettlement = PurchaseReturnSettlement()
873
            purchaseReturnSettlement.purchaseReturnId = id
874
            purchaseReturnSettlement.settlementType = settlementType
875
            purchaseReturnSettlement.settlementBy = settlementBy
876
            purchaseReturnSettlement.settlementAmount = settledAmount
877
            purchaseReturnSettlement.settlementDate = currentTime
878
            purchaseReturnSettlement.documentNumber = documentNumber
879
            session.commit()
880
            return True
881
        finally:
882
            self.close_session()
883
 
884
    def getPrSettlementsForPurchaseReturn(self, purchaseReturnId):
885
        try:
886
            settlements = PurchaseReturnSettlement.query.filter_by(purchaseReturnId=purchaseReturnId).all()
887
            prSettlements = []
888
            for settlement in settlements:
889
                prSettlements.append(settlement.to_thrift_object())
890
            return prSettlements
891
        finally:
892
            self.close_session()
893
 
894
    def updatePurchaseReturn(self, t_purchaseReturn):
895
        '''
896
        Updating a Purchase Return
897
        '''
898
        try:
899
            purchaseReturn = PurchaseReturn.get_by(id=t_purchaseReturn.id)
900
            purchaseReturn.purchaseReturnType = t_purchaseReturn.purchaseReturnType
901
            purchaseReturn.reasonText = t_purchaseReturn.reasonText
902
            purchaseReturn.createdBy = t_purchaseReturn.createdBy
903
            session.commit()
904
        finally:
905
            self.close_session()
906
 
6762 amar.kumar 907
    def isAlive(self,):
4503 mandeep.dh 908
        """
909
        For checking weather service is active alive or not. It also checks connectivity with database
910
        """
911
        try:
912
            session.query(Supplier.id).limit(1).all()
913
            return True
914
        except:
915
            return False
916
        finally:
917
            self.close_session()
5944 mandeep.dh 918
 
919
    def __get_item_from_master(self, item_id):
920
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 921
        return client.getItem(item_id)
13600 manish.sha 922