Subversion Repositories SmartDukaan

Rev

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