Subversion Repositories SmartDukaan

Rev

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