Subversion Repositories SmartDukaan

Rev

Rev 6857 | Rev 6861 | 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
 
6821 amar.kumar 265
            unfulfilledPurchaseOrders = PurchaseOrder.query.filter(or_(PurchaseOrder.status == POStatus.PARTIALLY_FULFILLED, PurchaseOrder.status == POStatus.READY)).filter(PurchaseOrder.type == POType.REAL).all()
5238 mandeep.dh 266
            for purchaseOrder in unfulfilledPurchaseOrders:
267
                for lineitem in purchaseOrder.lineitems:
268
                    if availability.has_key(lineitem.itemId):
269
                        availability[lineitem.itemId] = [availability[lineitem.itemId][0] + lineitem.unfulfilledQuantity, availability[lineitem.itemId][1]]
270
                    else:
5944 mandeep.dh 271
                        item = self.__get_item_from_master(lineitem.itemId)
5238 mandeep.dh 272
                        availability[item.id] = [lineitem.unfulfilledQuantity, item]
273
 
4754 mandeep.dh 274
            codRequirements = {}
275
            requirements = {}
276
            for order in pending_orders:
4758 mandeep.dh 277
                if order.purchaseOrderId:
4757 mandeep.dh 278
                    continue
4754 mandeep.dh 279
                for lineitem in order.lineitems:
280
                    if (requirements.has_key(lineitem.item_id)):
281
                        requirements[lineitem.item_id] += lineitem.quantity
282
                    else:
283
                        requirements[lineitem.item_id] = lineitem.quantity
284
 
285
                    if order.cod:
286
                        if (codRequirements.has_key(lineitem.item_id)):
287
                            codRequirements[lineitem.item_id] += lineitem.quantity
288
                        else:
289
                            codRequirements[lineitem.item_id] = lineitem.quantity
6821 amar.kumar 290
 
291
            advancedPOParameters = {}
6857 amar.kumar 292
            SKUListForPO = []
293
            inventory_client = InventoryClient().get_client()
294
            itemStockPurchaseParams = inventory_client.getNonZeroItemStockPurchaseParams()
295
            for itemStockPurchaseParam in itemStockPurchaseParams:
296
                inventory_client = InventoryClient().get_client()
297
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(itemStockPurchaseParam.item_id,5)
298
                salesCount = 0
299
                numDaysInStock = 0
300
                avgSales = 0.0
301
                lastXdaysSale ="" 
302
                for oosStatus in oosStatuses:
303
                    if oosStatus.is_oos == False:
304
                        salesCount = salesCount + oosStatus.num_orders
305
                        numDaysInStock = numDaysInStock + 1
306
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
307
                    else:
308
                        lastXdaysSale = lastXdaysSale + "X-"
309
                lastXdaysSale = lastXdaysSale[:-1]
310
                if numDaysInStock>0:
311
                    avgSales = float(salesCount)/numDaysInStock
312
                advancedPOParameters[itemStockPurchaseParam.item_id] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), avgSales, numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale]
313
                if itemInventorySnapshot.has_key(itemStockPurchaseParam.item_id):
314
                    itemAvailability = itemInventorySnapshot.get(itemStockPurchaseParam.item_id)
315
                    currentAvailability = 0
316
                    currentReserved = 0
317
                    for wId, rQty in itemAvailability.reserved.iteritems():
318
                        if wId in ourGoodWarehouseIds:
319
                            currentReserved = currentReserved + rQty
320
                    if (availability[itemStockPurchaseParam.item_id][0] - currentReserved) < max(advancedPOParameters[itemStockPurchaseParam.item_id][0], advancedPOParameters[itemStockPurchaseParam.item_id][3]): 
321
                        SKUListForPO.append(itemStockPurchaseParam.item_id)
322
                else:
323
                    SKUListForPO.append(itemStockPurchaseParam.item_id)
324
 
6821 amar.kumar 325
            for key in requirements:
6857 amar.kumar 326
                if advancedPOParameters.has_key(key):
327
                    continue
6821 amar.kumar 328
                inventory_client = InventoryClient().get_client()
329
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(key,5)
330
                salesCount = 0
331
                numDaysInStock = 0
6857 amar.kumar 332
                avgSales = 0.0
333
                lastXdaysSale = ""
6821 amar.kumar 334
                for oosStatus in oosStatuses:
6832 amar.kumar 335
                    if oosStatus.is_oos == False:
6821 amar.kumar 336
                        salesCount = salesCount + oosStatus.num_orders
337
                        numDaysInStock = numDaysInStock + 1
6857 amar.kumar 338
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
339
                    else:
340
                        lastXdaysSale = lastXdaysSale + "X-"
341
                lastXdaysSale = lastXdaysSale[:-1]        
6832 amar.kumar 342
                if numDaysInStock>0:
6857 amar.kumar 343
                    avgSales = float(salesCount)/float(numDaysInStock)
6832 amar.kumar 344
                itemStockPurchaseParam = ItemStockPurchaseParams()
345
                itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
6857 amar.kumar 346
                advancedPOParameters[key] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), avgSales, numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale]
6821 amar.kumar 347
 
6857 amar.kumar 348
            cumulativeRequirementsItemIds = list(set(requirements.keys()+SKUListForPO))
4754 mandeep.dh 349
            netRequirements = {}
6857 amar.kumar 350
            for itemId in cumulativeRequirementsItemIds:
4754 mandeep.dh 351
                requirementsCount = requirements.get(itemId)
6857 amar.kumar 352
                if requirementsCount is None:
353
                    requirementsCount = 0.0
4754 mandeep.dh 354
                if  availability.has_key(itemId):
355
                    availabilityCount = availability.get(itemId)[0]
6762 amar.kumar 356
                    item = availability.get(itemId)[1]
6857 amar.kumar 357
                    if requirementsCount > availabilityCount or itemId in SKUListForPO:
5238 mandeep.dh 358
                        if item.preferredVendor is None:
359
                            raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 360
                        if (netRequirements.has_key(item.preferredVendor)):
361
                            netRequirements[item.preferredVendor].append([item, requirementsCount - availabilityCount])
362
                        else:
363
                            netRequirements[item.preferredVendor] = [[item, requirementsCount - availabilityCount]];
364
                else:
5944 mandeep.dh 365
                    item = self.__get_item_from_master(itemId)
4754 mandeep.dh 366
                    if item.preferredVendor is None:
5238 mandeep.dh 367
                        raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 368
                    if (netRequirements.has_key(item.preferredVendor)):
369
                        netRequirements[item.preferredVendor].append([item, requirementsCount])
370
                    else:
371
                        netRequirements[item.preferredVendor] = [[item, requirementsCount]];
5238 mandeep.dh 372
 
4754 mandeep.dh 373
            if not netRequirements:
374
                return purchaseOrders
375
 
376
            for vendorId in netRequirements.keys():
377
                t_purchase_order = TPurchaseOrder()
378
                t_purchase_order.supplierId = vendorId
379
                t_purchase_order.warehouseId = warehouseId
380
                t_purchase_order.lineitems = []
381
                for key in netRequirements.get(vendorId):
6762 amar.kumar 382
                    item = key[0]
4754 mandeep.dh 383
                    quantity = key[1]
384
                    t_po_lineitem = TLineItem()
385
                    t_po_lineitem.productGroup = item.productGroup
386
                    t_po_lineitem.brand = item.brand
387
                    t_po_lineitem.modelNumber = item.modelNumber
388
                    t_po_lineitem.modelName = item.modelName
389
                    t_po_lineitem.color = item.color
390
                    t_po_lineitem.itemId = item.id
6860 amar.kumar 391
                    if quantity <0:
392
                        t_po_lineitem.quantity = 0
393
                    else:
394
                        t_po_lineitem.quantity = quantity
6832 amar.kumar 395
                    t_po_lineitem.availableQuantity = 0
396
                    if availability.has_key(item.id):
397
                        t_po_lineitem.availableQuantity = availability[item.id][0]
6857 amar.kumar 398
                    if requirements.has_key(item.id):
399
                        t_po_lineitem.reservedQuantity = requirements[item.id]
400
                    t_po_lineitem.suggestedQuantity = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3]) + quantity
6821 amar.kumar 401
                    t_po_lineitem.avgSales = advancedPOParameters[item.id][1]
402
                    t_po_lineitem.numberOfDaysInStock = advancedPOParameters[item.id][2] 
403
                    t_po_lineitem.minStockLevel = advancedPOParameters[item.id][3]
6857 amar.kumar 404
                    t_po_lineitem.numberOfDaysStock = advancedPOParameters[item.id][4]
405
                    t_po_lineitem.lastXdaysSale = advancedPOParameters[item.id][5] 
4754 mandeep.dh 406
                    if codRequirements.has_key(item.id):
407
                        t_po_lineitem.codCount = min(codRequirements[item.id], quantity)
408
                    try:
5944 mandeep.dh 409
                        item_pricing = inventory_client.getItemPricing(item.id, vendorId)
4754 mandeep.dh 410
                    except Exception as e:
411
                        vendor = self.getSupplier(vendorId)
412
                        print 'Could not find transfer price for Item id: ' + str(item.id) + ' and vendor id: ' + str(vendorId)
413
                        print e
414
                        raise PurchaseServiceException(101, 'Transfer price missing for ' + vendor.name + ' and ' + " ".join([item.brand, item.modelName, item.modelNumber, item.color]))
415
                    t_po_lineitem.unitPrice = item_pricing.transferPrice
416
                    t_purchase_order.lineitems.append(t_po_lineitem)
417
                purchaseOrders.append(t_purchase_order)
418
            return purchaseOrders
419
        finally:
420
            self.close_session()
421
 
6762 amar.kumar 422
    def getSuppliers(self,):
4754 mandeep.dh 423
        """
424
        Returns all the valid suppliers
425
        """
426
        try:
427
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.all()]
428
        finally:
429
            self.close_session()
430
 
5185 mandeep.dh 431
    def unFulfillPO(self, purchaseId, itemId, quantity):
432
        """
433
        Unfulfills a given purchase id and an item with its quantity.
434
 
435
        Parameters:
436
         - purchaseId
437
         - itemId
438
         - quantity
439
        """
440
        try:
6762 amar.kumar 441
            purchaseOrderId = Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id
442
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
5185 mandeep.dh 443
            if lineitems:
444
                fulfilledQuantity = lineitems[0].quantity - lineitems[0].unfulfilledQuantity
445
                if fulfilledQuantity < quantity:
446
                    raise PurchaseServiceException(101, 'Can UnFulfill only ' + str(fulfilledQuantity) + 'quantity')
447
                else:
5437 mandeep.dh 448
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity + quantity
5185 mandeep.dh 449
                    lineitems[0].fulfilled = 0
450
                    purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
451
                    purchaseOrder.status = POStatus.PARTIALLY_FULFILLED
452
                    session.commit()
453
                    return
454
 
455
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
456
        finally:
457
            self.close_session()        
458
 
4754 mandeep.dh 459
    def fulfillPO(self, purchaseOrderId, itemId, quantity):
460
        """
461
        Fulfills a given purchase order with an item.
462
 
463
        Parameters:
464
         - purchaseOrderId
465
         - itemId
466
         - quantity
467
        """
468
        try:
6762 amar.kumar 469
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
4754 mandeep.dh 470
            if lineitems:
471
                if lineitems[0].unfulfilledQuantity < quantity:
5361 mandeep.dh 472
                    raise PurchaseServiceException(101, 'Can fulfill only ' + str(lineitems[0].unfulfilledQuantity) + ' quantity')
4754 mandeep.dh 473
                else:
5361 mandeep.dh 474
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity - quantity
4754 mandeep.dh 475
                    if not lineitems[0].unfulfilledQuantity:
476
                        lineitems[0].fulfilled = 1
5361 mandeep.dh 477
                        session.commit()
6762 amar.kumar 478
                        if not LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, fulfilled=0).all():
5361 mandeep.dh 479
                            purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
4754 mandeep.dh 480
                            purchaseOrder.status = POStatus.CLOSED
481
                    session.commit()
482
                    return
483
 
6762 amar.kumar 484
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
4754 mandeep.dh 485
        finally:
486
            self.close_session()
487
 
488
    def updatePurchaseOrder(self, purchaseOrder):
489
        """
490
        Amends a PO sa per the new lineitems passed
491
 
492
        Parameters:
493
         - purchaseOrder
494
        """
495
        try:
6762 amar.kumar 496
            existingPurchaseOrder = PurchaseOrder.get_by(id=purchaseOrder.id)
4754 mandeep.dh 497
            maxRevision = 0
6762 amar.kumar 498
            existingRevisions = RevisionedPurchaseOrder.query.filter_by(purchaseOrderId=purchaseOrder.id).all()
4754 mandeep.dh 499
            if existingRevisions:
500
                maxRevision = max([a.revision for a in existingRevisions]) + 1
5147 mandeep.dh 501
 
502
            newPOItems = {}
503
            for t_lineitem in purchaseOrder.lineitems:
504
                newPOItems[t_lineitem.itemId] = t_lineitem
505
 
4754 mandeep.dh 506
            for lineitem in existingPurchaseOrder.lineitems:
5147 mandeep.dh 507
                fulfilledQuantity = lineitem.quantity - lineitem.unfulfilledQuantity
508
                if fulfilledQuantity:
509
                    if not newPOItems.has_key(lineitem.itemId):
510
                        raise PurchaseServiceException(101, 'Cannot remove fulfilled item id: ' + str(lineitem.itemId) + ' from PO')
511
                    else:
512
                        if newPOItems[lineitem.itemId].quantity < fulfilledQuantity:
513
                            raise PurchaseServiceException(101, 'More quantity already fulfilled for item id: ' + str(lineitem.itemId))
514
                        else:
5437 mandeep.dh 515
                            newPOItems[lineitem.itemId].unfulfilledQuantity = newPOItems[lineitem.itemId].unfulfilledQuantity - fulfilledQuantity
4754 mandeep.dh 516
                revisionedPurchaseOrder = RevisionedPurchaseOrder()
517
                revisionedPurchaseOrder.purchaseOrderId = purchaseOrder.id
518
                revisionedPurchaseOrder.revision = maxRevision
519
                revisionedPurchaseOrder.itemId = lineitem.itemId
520
                revisionedPurchaseOrder.unfulfilledQuantity = lineitem.unfulfilledQuantity
521
                revisionedPurchaseOrder.unitPrice = lineitem.unitPrice
522
                revisionedPurchaseOrder.createdAt = lineitem.createdAt
523
                revisionedPurchaseOrder.quantity = lineitem.quantity
524
                lineitem.delete()
525
            existingPurchaseOrder.lineitems = [LineItem(existingPurchaseOrder, t_lineitem) for t_lineitem in purchaseOrder.lineitems]
526
            existingPurchaseOrder.totalCost = sum([t_lineitem.quantity * t_lineitem.unitPrice for t_lineitem in purchaseOrder.lineitems])
527
            session.commit()
528
        finally:
529
            self.close_session()
530
 
4503 mandeep.dh 531
    def close_session(self):
532
        if session.is_active:
533
            print "session is active. closing it."
534
            session.close()
535
 
5443 mandeep.dh 536
    def getInvoices(self, date):
537
        """
538
        Fetches all invoices for a given date
539
 
540
        Parameters:
541
         - date
542
        """
543
        try:
544
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).all()]
545
        finally:
546
            self.close_session()
6630 amar.kumar 547
 
548
    def getInvoice(self, invoiceNumber, supplierId):
549
        """
550
        Fetches all invoices for  given invoiceNumber and supplierId 
5443 mandeep.dh 551
 
6630 amar.kumar 552
        Parameters:
553
         - invoiceNumber, supplierId
554
        """
555
        try:
6762 amar.kumar 556
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
6638 amar.kumar 557
            if invoice is None:
6762 amar.kumar 558
                return None
6638 amar.kumar 559
            else:
560
                return invoice.to_thrift_object()
6630 amar.kumar 561
        finally:
562
            self.close_session()
563
 
5443 mandeep.dh 564
    def createInvoice(self, invoice):
565
        """
566
        Creates an invoice object
567
 
568
        Parameters:
569
         - invoice
570
        """
571
        try:
6762 amar.kumar 572
            if Invoice.query.filter_by(supplierId=invoice.supplierId, date=to_py_date(invoice.date), invoiceNumber=invoice.invoiceNumber).all():
5768 mandeep.dh 573
                raise PurchaseServiceException(ExceptionType.ILLEGAL_ARGUMENTS, "Already received such invoice")
5443 mandeep.dh 574
            invoiceObj = Invoice()
575
            invoiceObj.invoiceNumber = invoice.invoiceNumber
576
            invoiceObj.date = to_py_date(invoice.date)
577
            invoiceObj.receivedFrom = invoice.receivedFrom
578
            invoiceObj.numItems = invoice.numItems
579
            invoiceObj.supplierId = invoice.supplierId
580
            session.commit()
581
        finally:
582
            self.close_session()        
583
 
5591 mandeep.dh 584
    def addSupplier(self, supplier):
585
        """
586
        Creates a supplier
587
 
588
        Parameters:
589
         - supplier
590
        """
591
        try:
592
            supplierObj = Supplier()
593
            supplierObj.communicationAddress = supplier.communicationAddress
594
            supplierObj.contactEmail = supplier.contactEmail
595
            supplierObj.contactFax = supplier.contactFax
596
            supplierObj.contactName = supplier.contactName
597
            supplierObj.contactPhone = supplier.contactPhone
598
            supplierObj.fax = supplier.fax
599
            supplierObj.headDesignation = supplier.headDesignation
600
            supplierObj.headEmail = supplier.headEmail
601
            supplierObj.headName = supplier.headName
602
            supplierObj.name = supplier.name
603
            supplierObj.pan = supplier.pan
604
            supplierObj.phone = supplier.phone
605
            supplierObj.registeredAddress = supplier.registeredAddress
606
            supplierObj.tin = supplier.tin
607
            session.commit()
608
            return self.getSupplier(supplierObj.id)
609
        finally:
610
            self.close_session()
611
 
612
    def updateSupplier(self, supplier):
613
        """
614
        Updates a supplier
615
 
616
        Parameters:
617
         - supplier
618
        """
619
        try:
620
            supplierObj = Supplier.get(supplier.id)
621
            supplierObj.communicationAddress = supplier.communicationAddress
622
            supplierObj.contactEmail = supplier.contactEmail
623
            supplierObj.contactFax = supplier.contactFax
624
            supplierObj.contactName = supplier.contactName
625
            supplierObj.contactPhone = supplier.contactPhone
626
            supplierObj.fax = supplier.fax
627
            supplierObj.headDesignation = supplier.headDesignation
628
            supplierObj.headEmail = supplier.headEmail
629
            supplierObj.headName = supplier.headName
630
            supplierObj.name = supplier.name
631
            supplierObj.pan = supplier.pan
632
            supplierObj.phone = supplier.phone
633
            supplierObj.registeredAddress = supplier.registeredAddress
634
            supplierObj.tin = supplier.tin
635
            session.commit()
636
        finally:
637
            self.close_session()
638
 
6385 amar.kumar 639
    def getInvoicesForPO(self, poNumber):
640
        '''
641
        For getting invoiceNumbers for a Purchase Order
642
        '''
643
        try:
644
 
6762 amar.kumar 645
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 646
            for purchase in purchases:
647
                invoice = purchase.invoiceNumber
648
        except:
649
            return None
650
        finally:
651
            self.close_session()
6467 amar.kumar 652
 
653
    def createPurchaseReturn(self, t_purchaseReturn):
654
        '''
655
        For creating a new Purchase Return
656
        '''
657
        try:
6762 amar.kumar 658
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 659
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
660
            purchaseReturn.amount = t_purchaseReturn.amount
661
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
662
            purchaseReturn.isSettled = False
6821 amar.kumar 663
            purchaseReturn.type = t_purchaseReturn.type
6467 amar.kumar 664
            session.commit()
665
            return purchaseReturn.id
666
        except Exception as e:
667
            print e
668
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
669
        finally:
670
            self.close_session()
671
 
672
    def getUnsettledPurchaseReturns(self):
673
        '''
674
        For getting all unsettled Purchase Returns
675
        '''
676
        try:
6821 amar.kumar 677
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 678
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
679
        except Exception as e:
680
            print e
681
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
682
        finally:
683
            self.close_session()
6385 amar.kumar 684
 
6467 amar.kumar 685
    def settlePurchaseReturn(self, returnId):
686
        '''
687
        For marking a Purchase Return as settled
688
        '''
689
        try:
6762 amar.kumar 690
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 691
            purchaseReturn.isSettled = True
692
            session.commit()
693
        except Exception as e:
694
            print e
695
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
696
        finally:
697
            self.close_session()
6762 amar.kumar 698
 
699
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, itemId):
700
        try:
701
            poId = self.getPOforOurExternalBilling()
702
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice)
703
            self.receiveinvoiceforOursExternalBilling(invoiceNumber)
704
            return self.createPurchaseforOursExternalBilling(poId, invoiceNumber)
705
        except Exception as e:
706
            print e
707
            raise PurchaseServiceException(101, '')
708
        finally:
709
            self.close_session()
710
 
711
    def fulfillPOForExtBilling(self, itemId, quantity):
712
        poId = self.getPOforOurExternalBilling()
713
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
714
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
715
        if not lineItem.unfulfilledQuantity:
716
            lineItem.fulfilled = 1
717
        session.commit()
6467 amar.kumar 718
 
6762 amar.kumar 719
    def isAlive(self,):
4503 mandeep.dh 720
        """
721
        For checking weather service is active alive or not. It also checks connectivity with database
722
        """
723
        try:
724
            session.query(Supplier.id).limit(1).all()
725
            return True
726
        except:
727
            return False
728
        finally:
729
            self.close_session()
5944 mandeep.dh 730
 
731
    def __get_item_from_master(self, item_id):
732
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 733
        return client.getItem(item_id)