Subversion Repositories SmartDukaan

Rev

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