Subversion Repositories SmartDukaan

Rev

Rev 6836 | Rev 6860 | 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
391
                    t_po_lineitem.quantity = quantity
6821 amar.kumar 392
 
6832 amar.kumar 393
                    t_po_lineitem.availableQuantity = 0
394
                    if availability.has_key(item.id):
395
                        t_po_lineitem.availableQuantity = availability[item.id][0]
6857 amar.kumar 396
                    if requirements.has_key(item.id):
397
                        t_po_lineitem.reservedQuantity = requirements[item.id]
398
                    t_po_lineitem.suggestedQuantity = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3]) + quantity
6821 amar.kumar 399
                    t_po_lineitem.avgSales = advancedPOParameters[item.id][1]
400
                    t_po_lineitem.numberOfDaysInStock = advancedPOParameters[item.id][2] 
401
                    t_po_lineitem.minStockLevel = advancedPOParameters[item.id][3]
6857 amar.kumar 402
                    t_po_lineitem.numberOfDaysStock = advancedPOParameters[item.id][4]
403
                    t_po_lineitem.lastXdaysSale = advancedPOParameters[item.id][5] 
4754 mandeep.dh 404
                    if codRequirements.has_key(item.id):
405
                        t_po_lineitem.codCount = min(codRequirements[item.id], quantity)
406
                    try:
5944 mandeep.dh 407
                        item_pricing = inventory_client.getItemPricing(item.id, vendorId)
4754 mandeep.dh 408
                    except Exception as e:
409
                        vendor = self.getSupplier(vendorId)
410
                        print 'Could not find transfer price for Item id: ' + str(item.id) + ' and vendor id: ' + str(vendorId)
411
                        print e
412
                        raise PurchaseServiceException(101, 'Transfer price missing for ' + vendor.name + ' and ' + " ".join([item.brand, item.modelName, item.modelNumber, item.color]))
413
                    t_po_lineitem.unitPrice = item_pricing.transferPrice
414
                    t_purchase_order.lineitems.append(t_po_lineitem)
415
                purchaseOrders.append(t_purchase_order)
416
            return purchaseOrders
417
        finally:
418
            self.close_session()
419
 
6762 amar.kumar 420
    def getSuppliers(self,):
4754 mandeep.dh 421
        """
422
        Returns all the valid suppliers
423
        """
424
        try:
425
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.all()]
426
        finally:
427
            self.close_session()
428
 
5185 mandeep.dh 429
    def unFulfillPO(self, purchaseId, itemId, quantity):
430
        """
431
        Unfulfills a given purchase id and an item with its quantity.
432
 
433
        Parameters:
434
         - purchaseId
435
         - itemId
436
         - quantity
437
        """
438
        try:
6762 amar.kumar 439
            purchaseOrderId = Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id
440
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
5185 mandeep.dh 441
            if lineitems:
442
                fulfilledQuantity = lineitems[0].quantity - lineitems[0].unfulfilledQuantity
443
                if fulfilledQuantity < quantity:
444
                    raise PurchaseServiceException(101, 'Can UnFulfill only ' + str(fulfilledQuantity) + 'quantity')
445
                else:
5437 mandeep.dh 446
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity + quantity
5185 mandeep.dh 447
                    lineitems[0].fulfilled = 0
448
                    purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
449
                    purchaseOrder.status = POStatus.PARTIALLY_FULFILLED
450
                    session.commit()
451
                    return
452
 
453
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
454
        finally:
455
            self.close_session()        
456
 
4754 mandeep.dh 457
    def fulfillPO(self, purchaseOrderId, itemId, quantity):
458
        """
459
        Fulfills a given purchase order with an item.
460
 
461
        Parameters:
462
         - purchaseOrderId
463
         - itemId
464
         - quantity
465
        """
466
        try:
6762 amar.kumar 467
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
4754 mandeep.dh 468
            if lineitems:
469
                if lineitems[0].unfulfilledQuantity < quantity:
5361 mandeep.dh 470
                    raise PurchaseServiceException(101, 'Can fulfill only ' + str(lineitems[0].unfulfilledQuantity) + ' quantity')
4754 mandeep.dh 471
                else:
5361 mandeep.dh 472
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity - quantity
4754 mandeep.dh 473
                    if not lineitems[0].unfulfilledQuantity:
474
                        lineitems[0].fulfilled = 1
5361 mandeep.dh 475
                        session.commit()
6762 amar.kumar 476
                        if not LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, fulfilled=0).all():
5361 mandeep.dh 477
                            purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
4754 mandeep.dh 478
                            purchaseOrder.status = POStatus.CLOSED
479
                    session.commit()
480
                    return
481
 
6762 amar.kumar 482
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
4754 mandeep.dh 483
        finally:
484
            self.close_session()
485
 
486
    def updatePurchaseOrder(self, purchaseOrder):
487
        """
488
        Amends a PO sa per the new lineitems passed
489
 
490
        Parameters:
491
         - purchaseOrder
492
        """
493
        try:
6762 amar.kumar 494
            existingPurchaseOrder = PurchaseOrder.get_by(id=purchaseOrder.id)
4754 mandeep.dh 495
            maxRevision = 0
6762 amar.kumar 496
            existingRevisions = RevisionedPurchaseOrder.query.filter_by(purchaseOrderId=purchaseOrder.id).all()
4754 mandeep.dh 497
            if existingRevisions:
498
                maxRevision = max([a.revision for a in existingRevisions]) + 1
5147 mandeep.dh 499
 
500
            newPOItems = {}
501
            for t_lineitem in purchaseOrder.lineitems:
502
                newPOItems[t_lineitem.itemId] = t_lineitem
503
 
4754 mandeep.dh 504
            for lineitem in existingPurchaseOrder.lineitems:
5147 mandeep.dh 505
                fulfilledQuantity = lineitem.quantity - lineitem.unfulfilledQuantity
506
                if fulfilledQuantity:
507
                    if not newPOItems.has_key(lineitem.itemId):
508
                        raise PurchaseServiceException(101, 'Cannot remove fulfilled item id: ' + str(lineitem.itemId) + ' from PO')
509
                    else:
510
                        if newPOItems[lineitem.itemId].quantity < fulfilledQuantity:
511
                            raise PurchaseServiceException(101, 'More quantity already fulfilled for item id: ' + str(lineitem.itemId))
512
                        else:
5437 mandeep.dh 513
                            newPOItems[lineitem.itemId].unfulfilledQuantity = newPOItems[lineitem.itemId].unfulfilledQuantity - fulfilledQuantity
4754 mandeep.dh 514
                revisionedPurchaseOrder = RevisionedPurchaseOrder()
515
                revisionedPurchaseOrder.purchaseOrderId = purchaseOrder.id
516
                revisionedPurchaseOrder.revision = maxRevision
517
                revisionedPurchaseOrder.itemId = lineitem.itemId
518
                revisionedPurchaseOrder.unfulfilledQuantity = lineitem.unfulfilledQuantity
519
                revisionedPurchaseOrder.unitPrice = lineitem.unitPrice
520
                revisionedPurchaseOrder.createdAt = lineitem.createdAt
521
                revisionedPurchaseOrder.quantity = lineitem.quantity
522
                lineitem.delete()
523
            existingPurchaseOrder.lineitems = [LineItem(existingPurchaseOrder, t_lineitem) for t_lineitem in purchaseOrder.lineitems]
524
            existingPurchaseOrder.totalCost = sum([t_lineitem.quantity * t_lineitem.unitPrice for t_lineitem in purchaseOrder.lineitems])
525
            session.commit()
526
        finally:
527
            self.close_session()
528
 
4503 mandeep.dh 529
    def close_session(self):
530
        if session.is_active:
531
            print "session is active. closing it."
532
            session.close()
533
 
5443 mandeep.dh 534
    def getInvoices(self, date):
535
        """
536
        Fetches all invoices for a given date
537
 
538
        Parameters:
539
         - date
540
        """
541
        try:
542
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).all()]
543
        finally:
544
            self.close_session()
6630 amar.kumar 545
 
546
    def getInvoice(self, invoiceNumber, supplierId):
547
        """
548
        Fetches all invoices for  given invoiceNumber and supplierId 
5443 mandeep.dh 549
 
6630 amar.kumar 550
        Parameters:
551
         - invoiceNumber, supplierId
552
        """
553
        try:
6762 amar.kumar 554
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
6638 amar.kumar 555
            if invoice is None:
6762 amar.kumar 556
                return None
6638 amar.kumar 557
            else:
558
                return invoice.to_thrift_object()
6630 amar.kumar 559
        finally:
560
            self.close_session()
561
 
5443 mandeep.dh 562
    def createInvoice(self, invoice):
563
        """
564
        Creates an invoice object
565
 
566
        Parameters:
567
         - invoice
568
        """
569
        try:
6762 amar.kumar 570
            if Invoice.query.filter_by(supplierId=invoice.supplierId, date=to_py_date(invoice.date), invoiceNumber=invoice.invoiceNumber).all():
5768 mandeep.dh 571
                raise PurchaseServiceException(ExceptionType.ILLEGAL_ARGUMENTS, "Already received such invoice")
5443 mandeep.dh 572
            invoiceObj = Invoice()
573
            invoiceObj.invoiceNumber = invoice.invoiceNumber
574
            invoiceObj.date = to_py_date(invoice.date)
575
            invoiceObj.receivedFrom = invoice.receivedFrom
576
            invoiceObj.numItems = invoice.numItems
577
            invoiceObj.supplierId = invoice.supplierId
578
            session.commit()
579
        finally:
580
            self.close_session()        
581
 
5591 mandeep.dh 582
    def addSupplier(self, supplier):
583
        """
584
        Creates a supplier
585
 
586
        Parameters:
587
         - supplier
588
        """
589
        try:
590
            supplierObj = Supplier()
591
            supplierObj.communicationAddress = supplier.communicationAddress
592
            supplierObj.contactEmail = supplier.contactEmail
593
            supplierObj.contactFax = supplier.contactFax
594
            supplierObj.contactName = supplier.contactName
595
            supplierObj.contactPhone = supplier.contactPhone
596
            supplierObj.fax = supplier.fax
597
            supplierObj.headDesignation = supplier.headDesignation
598
            supplierObj.headEmail = supplier.headEmail
599
            supplierObj.headName = supplier.headName
600
            supplierObj.name = supplier.name
601
            supplierObj.pan = supplier.pan
602
            supplierObj.phone = supplier.phone
603
            supplierObj.registeredAddress = supplier.registeredAddress
604
            supplierObj.tin = supplier.tin
605
            session.commit()
606
            return self.getSupplier(supplierObj.id)
607
        finally:
608
            self.close_session()
609
 
610
    def updateSupplier(self, supplier):
611
        """
612
        Updates a supplier
613
 
614
        Parameters:
615
         - supplier
616
        """
617
        try:
618
            supplierObj = Supplier.get(supplier.id)
619
            supplierObj.communicationAddress = supplier.communicationAddress
620
            supplierObj.contactEmail = supplier.contactEmail
621
            supplierObj.contactFax = supplier.contactFax
622
            supplierObj.contactName = supplier.contactName
623
            supplierObj.contactPhone = supplier.contactPhone
624
            supplierObj.fax = supplier.fax
625
            supplierObj.headDesignation = supplier.headDesignation
626
            supplierObj.headEmail = supplier.headEmail
627
            supplierObj.headName = supplier.headName
628
            supplierObj.name = supplier.name
629
            supplierObj.pan = supplier.pan
630
            supplierObj.phone = supplier.phone
631
            supplierObj.registeredAddress = supplier.registeredAddress
632
            supplierObj.tin = supplier.tin
633
            session.commit()
634
        finally:
635
            self.close_session()
636
 
6385 amar.kumar 637
    def getInvoicesForPO(self, poNumber):
638
        '''
639
        For getting invoiceNumbers for a Purchase Order
640
        '''
641
        try:
642
 
6762 amar.kumar 643
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 644
            for purchase in purchases:
645
                invoice = purchase.invoiceNumber
646
        except:
647
            return None
648
        finally:
649
            self.close_session()
6467 amar.kumar 650
 
651
    def createPurchaseReturn(self, t_purchaseReturn):
652
        '''
653
        For creating a new Purchase Return
654
        '''
655
        try:
6762 amar.kumar 656
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 657
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
658
            purchaseReturn.amount = t_purchaseReturn.amount
659
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
660
            purchaseReturn.isSettled = False
6821 amar.kumar 661
            purchaseReturn.type = t_purchaseReturn.type
6467 amar.kumar 662
            session.commit()
663
            return purchaseReturn.id
664
        except Exception as e:
665
            print e
666
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
667
        finally:
668
            self.close_session()
669
 
670
    def getUnsettledPurchaseReturns(self):
671
        '''
672
        For getting all unsettled Purchase Returns
673
        '''
674
        try:
6821 amar.kumar 675
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 676
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
677
        except Exception as e:
678
            print e
679
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
680
        finally:
681
            self.close_session()
6385 amar.kumar 682
 
6467 amar.kumar 683
    def settlePurchaseReturn(self, returnId):
684
        '''
685
        For marking a Purchase Return as settled
686
        '''
687
        try:
6762 amar.kumar 688
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 689
            purchaseReturn.isSettled = True
690
            session.commit()
691
        except Exception as e:
692
            print e
693
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
694
        finally:
695
            self.close_session()
6762 amar.kumar 696
 
697
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, itemId):
698
        try:
699
            poId = self.getPOforOurExternalBilling()
700
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice)
701
            self.receiveinvoiceforOursExternalBilling(invoiceNumber)
702
            return self.createPurchaseforOursExternalBilling(poId, invoiceNumber)
703
        except Exception as e:
704
            print e
705
            raise PurchaseServiceException(101, '')
706
        finally:
707
            self.close_session()
708
 
709
    def fulfillPOForExtBilling(self, itemId, quantity):
710
        poId = self.getPOforOurExternalBilling()
711
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
712
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
713
        if not lineItem.unfulfilledQuantity:
714
            lineItem.fulfilled = 1
715
        session.commit()
6467 amar.kumar 716
 
6762 amar.kumar 717
    def isAlive(self,):
4503 mandeep.dh 718
        """
719
        For checking weather service is active alive or not. It also checks connectivity with database
720
        """
721
        try:
722
            session.query(Supplier.id).limit(1).all()
723
            return True
724
        except:
725
            return False
726
        finally:
727
            self.close_session()
5944 mandeep.dh 728
 
729
    def __get_item_from_master(self, item_id):
730
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 731
        return client.getItem(item_id)