Subversion Repositories SmartDukaan

Rev

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