Subversion Repositories SmartDukaan

Rev

Rev 21620 | Rev 21622 | 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
21621 amit.gupta 13
from shop2020.purchase.main.model.PurchaseOrder import PurchaseOrder
6467 amar.kumar 14
from shop2020.purchase.main.model.PurchaseReturn import PurchaseReturn
21621 amit.gupta 15
from shop2020.purchase.main.model.PurchaseReturnSettlement import \
16
    PurchaseReturnSettlement
5110 mandeep.dh 17
from shop2020.purchase.main.model.RevisionedPurchaseOrder import \
18
    RevisionedPurchaseOrder
4503 mandeep.dh 19
from shop2020.purchase.main.model.Supplier import Supplier
5768 mandeep.dh 20
from shop2020.thriftpy.generic.ttypes import ExceptionType
5944 mandeep.dh 21
from shop2020.thriftpy.model.v1.inventory.ttypes import WarehouseType, \
6832 amar.kumar 22
    InventoryType, ItemStockPurchaseParams
4754 mandeep.dh 23
from shop2020.thriftpy.model.v1.order.ttypes import OrderStatus
24
from shop2020.thriftpy.purchase.ttypes import PurchaseServiceException, POStatus, \
21621 amit.gupta 25
    PurchaseOrder as TPurchaseOrder, LineItem as TLineItem, POType, \
10864 manish.sha 26
    PurchaseReturnType, PurchaseReturnInventoryType
5443 mandeep.dh 27
from shop2020.utils.Utils import to_py_date
4503 mandeep.dh 28
from sqlalchemy import create_engine
5238 mandeep.dh 29
from sqlalchemy.sql.expression import or_
4503 mandeep.dh 30
import datetime
31
import logging
4754 mandeep.dh 32
import sys
21621 amit.gupta 33
import traceback
4503 mandeep.dh 34
 
35
 
36
logging.basicConfig(level=logging.DEBUG)
37
 
38
class PurchaseServiceHandler:
39
    '''
40
    classdocs
41
    '''
42
 
43
    def __init__(self, dbname='warehouse', db_hostname='localhost',  echoOn=True):
44
        '''
45
        Constructor
46
        '''
47
        engine = create_engine('mysql://root:shop2020@' + db_hostname + '/' + dbname, pool_recycle=7200)
48
        metadata.bind = engine
49
        metadata.bind.echo = echoOn
50
        setup_all(True)
51
 
6762 amar.kumar 52
    def getPOforOurExternalBilling(self):
53
        todayDate = datetime.datetime.now()
54
        todayDate = todayDate.replace(hour=0) 
6821 amar.kumar 55
        purchaseOrder = PurchaseOrder.query.filter(PurchaseOrder.supplierId == 1).filter(PurchaseOrder.createdAt > todayDate).filter(PurchaseOrder.type == POType.VIRTUAL).first()
6762 amar.kumar 56
        if purchaseOrder is None:
57
            t_purchaseOrder = TPurchaseOrder()
58
            t_purchaseOrder.supplierId = 1
59
            t_purchaseOrder.createdAt = datetime.datetime.now()
60
            t_purchaseOrder.status = 0
61
            t_purchaseOrder.totalCost = 0
8716 amar.kumar 62
            t_purchaseOrder.warehouseId = 9
6762 amar.kumar 63
            t_purchaseOrder.poNumber = 'Ours-Ext-' + str(todayDate.year) + "-" + str(todayDate.month) + "-" + str(todayDate.day)
6821 amar.kumar 64
            t_purchaseOrder.type = POType.VIRTUAL
6762 amar.kumar 65
            purchaseOrder = PurchaseOrder(t_purchaseOrder)
66
            session.commit()
67
        return purchaseOrder.id    
68
 
7672 rajveer 69
    def updatelineItemforOursExternalBilling(self, poId, itemId, unitPrice, nlc):
6762 amar.kumar 70
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
71
        if lineItem is None:
72
            purchaseOrder = PurchaseOrder.get_by(id=poId)
73
            t_lineItem = TLineItem()
74
            t_lineItem.itemId = itemId
75
            t_lineItem.quantity = 1
76
            t_lineItem.unfulfilledQuantity = 1
77
            t_lineItem.createdAt = datetime.datetime.now()
78
            t_lineItem.unitPrice = unitPrice
7672 rajveer 79
            t_lineItem.nlc = nlc
6762 amar.kumar 80
            t_lineItem.fulfilled = False
81
            lineItem = LineItem(purchaseOrder, t_lineItem)
82
        else:
83
            lineItem.quantity = lineItem.quantity + 1
84
            lineItem.fulfilled = False
85
            lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity + 1
86
        session.commit()
87
 
88
    def receiveinvoiceforOursExternalBilling(self, invoiceNumber):
89
        invoice = Invoice()
90
        invoice.invoiceNumber = invoiceNumber
91
        invoice.date = datetime.datetime.now()
92
        invoice.numItems = 1
93
        invoice.receivedFrom = "Hotspot-Billing"
94
        invoice.supplierId = 1
11219 manish.sha 95
        invoice.invoiceDate = datetime.datetime.now()
6762 amar.kumar 96
        session.commit()
97
 
98
    def createPurchaseforOursExternalBilling(self, poId, invoiceNumber):
99
        purchaseOrder = PurchaseOrder.get_by(id=poId)
100
        purchase = Purchase(purchaseOrder, invoiceNumber, 0)
101
        session.commit()
102
        return purchase.id
103
 
4503 mandeep.dh 104
    def createPurchaseOrder(self, tPurchaseOrder):
105
        """
106
        Creates a purchase order based on the data in the given purchase order object.
107
        This method populates a number of missing fields
108
 
109
        Parameters:
110
         - purchaseOrder
111
        """
112
        try:
113
            purchaseOrder = PurchaseOrder(tPurchaseOrder)
114
            session.commit()
115
            purchaseOrder.set_po_number()
116
            session.commit()
117
            return purchaseOrder.id
118
        finally:
119
            self.close_session()
120
 
121
    def getAllPurchaseOrders(self, status):
122
        """
123
        Returns a list of all the purchase orders in the given state
124
 
125
        Parameters:
126
         - status
127
        """
128
        try:
6821 amar.kumar 129
            pos = PurchaseOrder.query.filter_by(status=status, type=POType.REAL).all()
4503 mandeep.dh 130
            return [po.to_thrift_object() for po in pos ]
131
        finally:
132
            self.close_session()
133
 
134
    def getPurchaseOrder(self, id):
135
        """
136
        Returns the purchase order with the given id. Throws an exception if there is no such purchase order.
137
 
138
        Parameters:
139
         - id
140
        """
141
        try:
142
            purchaseOrder = PurchaseOrder.get_by(id=id)
143
            if not purchaseOrder:
144
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id)) 
145
            return purchaseOrder.to_thrift_object()
146
        finally:
147
            self.close_session()
148
 
149
    def getSupplier(self, id):
150
        """
151
        Returns the supplier with the given order id. Throws an exception if there is no such supplier.
152
 
153
        Parameters:
154
         - id
155
        """
156
        try:
157
            return Supplier.get_by(id=id).to_thrift_object()
158
        finally:
159
            self.close_session()
160
 
11801 manish.sha 161
    def startPurchase(self, purchaseOrderId, invoiceNumber, freightCharges, purchaseComments):
4503 mandeep.dh 162
        """
163
        Creates a purchase for the given purchase order.
164
        Throws an exception if no more purchases are allowed against the given purchase order.
165
 
166
        Parameters:
167
         - purchaseOrderId
168
         - invoiceNumber
169
         - freightCharges
170
        """
171
        try:
6762 amar.kumar 172
            purchase_order = PurchaseOrder.get_by(id=purchaseOrderId)
11801 manish.sha 173
            purchase = Purchase(purchase_order, invoiceNumber, freightCharges, purchaseComments)
4503 mandeep.dh 174
            session.commit()
175
            return purchase.id
176
        finally:
177
            self.close_session()
178
 
179
    def closePurchase(self, purchaseId):
180
        """
181
        Marks a purchase as complete and updates the receivedOn time.
182
        Throws an exception if no such purchase exists.
183
 
184
        Parameters:
185
         - purchaseId
186
        """
187
        try:
188
            purchase = Purchase.get_by(id=purchaseId)
189
            purchase.receivedOn = datetime.datetime.now()
190
            session.commit()
191
        finally:
192
            self.close_session()
193
 
194
    def getAllPurchases(self, purchaseOrderId, open):
195
        """
196
        Returns all open or closed purchases for the given purchase order. Throws an exception if no such purchase order exists
197
 
198
        Parameters:
199
         - purchaseOrderId
200
         - open
201
        """
202
        try:
203
            if open:
6762 amar.kumar 204
                purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId, receivedOn=None).all()
4503 mandeep.dh 205
            else:
6762 amar.kumar 206
                purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId).filter(Purchase.receivedOn != None).all()
4503 mandeep.dh 207
 
208
            return [purchase.to_thrift_object() for purchase in purchases]
209
        finally:
210
            self.close_session()
6385 amar.kumar 211
 
212
    def getPurchasesForPO(self, purchaseOrderId):
213
        """
214
        Returns all purchases for the given purchase order. Throws an exception if no such purchase order exists
215
 
216
        Parameters:
217
         - purchaseOrderId
218
         - open
219
        """
220
        try:
6762 amar.kumar 221
            purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId).all()
6385 amar.kumar 222
            return [purchase.to_thrift_object() for purchase in purchases]
223
        finally:
224
            self.close_session()
4503 mandeep.dh 225
 
6385 amar.kumar 226
 
4555 mandeep.dh 227
    def getPurchaseOrderForPurchase(self, purchaseId):
4503 mandeep.dh 228
        """
4555 mandeep.dh 229
        Returns the purchase order for a given purchase
4503 mandeep.dh 230
 
231
        Parameters:
232
         - purchaseId
233
        """
4555 mandeep.dh 234
        try:
6762 amar.kumar 235
            return self.getPurchaseOrder(Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id)
4555 mandeep.dh 236
        finally:
237
            self.close_session()
4503 mandeep.dh 238
 
4754 mandeep.dh 239
    def getPendingPurchaseOrders(self, warehouseId):
240
        """
241
        Creates purchase order objects from pending orders
242
 
243
        Parameters:
244
         - warehouseId
245
        """
246
        try:
247
            purchaseOrders = []
248
            if not warehouseId:
249
                raise PurchaseServiceException(101, "bad warehouse id")
250
 
251
            transactionClient = TransactionClient().get_client()
18426 manish.sha 252
            pending_orders = transactionClient.getOrdersInBatch([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.ACCEPTED, OrderStatus.COD_VERIFICATION_PENDING], 0, 0, warehouseId, 0)
4754 mandeep.dh 253
 
254
            if not pending_orders:
255
                return purchaseOrders
256
 
5944 mandeep.dh 257
            inventory_client = InventoryClient().get_client()
4754 mandeep.dh 258
            availability = {}
5110 mandeep.dh 259
 
5944 mandeep.dh 260
            ourGoodWarehouseIds = [w.id for w in inventory_client.getWarehouses(WarehouseType.OURS, InventoryType.GOOD, 0, None, warehouseId)]
261
            itemInventorySnapshot = inventory_client.getInventorySnapshot(0)
262
            for itemId, itemInventory in itemInventorySnapshot.iteritems():
7105 amar.kumar 263
                '''item = self.__get_item_from_master(itemId)'''
5944 mandeep.dh 264
                for warehouseId, quantity in itemInventory.availability.iteritems():
265
                    if warehouseId in ourGoodWarehouseIds:
7105 amar.kumar 266
                        if availability.has_key(itemId):
267
                            availability[itemId] = [availability[itemId][0] + quantity]
5944 mandeep.dh 268
                        else:
7105 amar.kumar 269
                            availability[itemId] = [quantity]
4754 mandeep.dh 270
 
6880 amar.kumar 271
            previouslyOrderedQty = {}
6821 amar.kumar 272
            unfulfilledPurchaseOrders = PurchaseOrder.query.filter(or_(PurchaseOrder.status == POStatus.PARTIALLY_FULFILLED, PurchaseOrder.status == POStatus.READY)).filter(PurchaseOrder.type == POType.REAL).all()
5238 mandeep.dh 273
            for purchaseOrder in unfulfilledPurchaseOrders:
274
                for lineitem in purchaseOrder.lineitems:
6880 amar.kumar 275
                    if previouslyOrderedQty.has_key(lineitem.itemId):
276
                        previouslyOrderedQty[lineitem.itemId] = previouslyOrderedQty[lineitem.itemId] + lineitem.unfulfilledQuantity
277
                    else:
278
                        previouslyOrderedQty[lineitem.itemId] = lineitem.unfulfilledQuantity
279
 
5238 mandeep.dh 280
                    if availability.has_key(lineitem.itemId):
7105 amar.kumar 281
                        availability[lineitem.itemId] = [availability[lineitem.itemId][0] + lineitem.unfulfilledQuantity]
5238 mandeep.dh 282
                    else:
7105 amar.kumar 283
                        '''item = self.__get_item_from_master(lineitem.itemId)'''
7106 amar.kumar 284
                        availability[lineitem.itemId] = [lineitem.unfulfilledQuantity]
5238 mandeep.dh 285
 
4754 mandeep.dh 286
            codRequirements = {}
287
            requirements = {}
288
            for order in pending_orders:
4758 mandeep.dh 289
                if order.purchaseOrderId:
4757 mandeep.dh 290
                    continue
4754 mandeep.dh 291
                for lineitem in order.lineitems:
292
                    if (requirements.has_key(lineitem.item_id)):
293
                        requirements[lineitem.item_id] += lineitem.quantity
294
                    else:
295
                        requirements[lineitem.item_id] = lineitem.quantity
296
 
297
                    if order.cod:
298
                        if (codRequirements.has_key(lineitem.item_id)):
299
                            codRequirements[lineitem.item_id] += lineitem.quantity
300
                        else:
301
                            codRequirements[lineitem.item_id] = lineitem.quantity
6821 amar.kumar 302
 
303
            advancedPOParameters = {}
6857 amar.kumar 304
            SKUListForPO = []
305
            inventory_client = InventoryClient().get_client()
306
            itemStockPurchaseParams = inventory_client.getNonZeroItemStockPurchaseParams()
307
            for itemStockPurchaseParam in itemStockPurchaseParams:
308
                inventory_client = InventoryClient().get_client()
9696 amar.kumar 309
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(itemStockPurchaseParam.item_id, 0, 3)
6857 amar.kumar 310
                salesCount = 0
311
                numDaysInStock = 0
8182 amar.kumar 312
                rtoCount = 0
6857 amar.kumar 313
                avgSales = 0.0
314
                lastXdaysSale ="" 
315
                for oosStatus in oosStatuses:
316
                    if oosStatus.is_oos == False:
317
                        salesCount = salesCount + oosStatus.num_orders
318
                        numDaysInStock = numDaysInStock + 1
319
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
320
                    else:
321
                        lastXdaysSale = lastXdaysSale + "X-"
8221 amar.kumar 322
                if oosStatus.rto_orders is not None:
8182 amar.kumar 323
                    rtoCount = oosStatus.rto_orders
6857 amar.kumar 324
                lastXdaysSale = lastXdaysSale[:-1]
325
                if numDaysInStock>0:
326
                    avgSales = float(salesCount)/numDaysInStock
8182 amar.kumar 327
                advancedPOParameters[itemStockPurchaseParam.item_id] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2) , numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6857 amar.kumar 328
                if itemInventorySnapshot.has_key(itemStockPurchaseParam.item_id):
329
                    itemAvailability = itemInventorySnapshot.get(itemStockPurchaseParam.item_id)
330
                    currentAvailability = 0
331
                    currentReserved = 0
332
                    for wId, rQty in itemAvailability.reserved.iteritems():
333
                        if wId in ourGoodWarehouseIds:
334
                            currentReserved = currentReserved + rQty
9261 manish.sha 335
                    #Key Condition Added By Manish Sharma        
336
                    if availability.has_key(itemStockPurchaseParam.item_id):
337
                        if availability[itemStockPurchaseParam.item_id] is None:
338
                                availability[itemStockPurchaseParam.item_id] = [0]
339
                    else:
8182 amar.kumar 340
                        availability[itemStockPurchaseParam.item_id] = [0]
9261 manish.sha 341
                    if (availability[itemStockPurchaseParam.item_id][0] - currentReserved) < max(advancedPOParameters[itemStockPurchaseParam.item_id][0], advancedPOParameters[itemStockPurchaseParam.item_id][3]):
6857 amar.kumar 342
                        SKUListForPO.append(itemStockPurchaseParam.item_id)
343
                else:
344
                    SKUListForPO.append(itemStockPurchaseParam.item_id)
345
 
6821 amar.kumar 346
            for key in requirements:
6857 amar.kumar 347
                if advancedPOParameters.has_key(key):
348
                    continue
12175 manish.sha 349
                print "Item Id ---", key
6821 amar.kumar 350
                inventory_client = InventoryClient().get_client()
9696 amar.kumar 351
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(key, 0, 3)
6821 amar.kumar 352
                salesCount = 0
353
                numDaysInStock = 0
8182 amar.kumar 354
                rtoCount = 0
6857 amar.kumar 355
                avgSales = 0.0
356
                lastXdaysSale = ""
21620 amit.gupta 357
                if not oosStatuses:
358
                    continue
6821 amar.kumar 359
                for oosStatus in oosStatuses:
6832 amar.kumar 360
                    if oosStatus.is_oos == False:
6821 amar.kumar 361
                        salesCount = salesCount + oosStatus.num_orders
362
                        numDaysInStock = numDaysInStock + 1
6857 amar.kumar 363
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
364
                    else:
365
                        lastXdaysSale = lastXdaysSale + "X-"
8182 amar.kumar 366
                lastXdaysSale = lastXdaysSale[:-1]
367
                if oosStatus.rto_orders:
368
                    rtoCount = oosStatus.rto_orders
6832 amar.kumar 369
                if numDaysInStock>0:
6857 amar.kumar 370
                    avgSales = float(salesCount)/float(numDaysInStock)
18588 manish.sha 371
                itemStockPurchaseParam = None
10864 manish.sha 372
                try:
373
                    itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
374
                except Exception as e:
375
                    inventory_client.updateItemStockPurchaseParams(key, 0, 0)
376
                    itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
18588 manish.sha 377
 
378
                if itemStockPurchaseParam.numOfDaysStock is None:
379
                    itemStockPurchaseParam.minStockLevel = 0
380
                    itemStockPurchaseParam.numOfDaysStock = 0
381
                    itemStockPurchaseParam.item_id = key
382
 
8182 amar.kumar 383
                advancedPOParameters[key] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2), numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6821 amar.kumar 384
 
6857 amar.kumar 385
            cumulativeRequirementsItemIds = list(set(requirements.keys()+SKUListForPO))
4754 mandeep.dh 386
            netRequirements = {}
6857 amar.kumar 387
            for itemId in cumulativeRequirementsItemIds:
12341 manish.sha 388
                print "Item Id for Preferred Vendor", itemId
4754 mandeep.dh 389
                requirementsCount = requirements.get(itemId)
6857 amar.kumar 390
                if requirementsCount is None:
391
                    requirementsCount = 0.0
4754 mandeep.dh 392
                if  availability.has_key(itemId):
393
                    availabilityCount = availability.get(itemId)[0]
7105 amar.kumar 394
                    item = self.__get_item_from_master(itemId)
6857 amar.kumar 395
                    if requirementsCount > availabilityCount or itemId in SKUListForPO:
5238 mandeep.dh 396
                        if item.preferredVendor is None:
397
                            raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 398
                        if (netRequirements.has_key(item.preferredVendor)):
399
                            netRequirements[item.preferredVendor].append([item, requirementsCount - availabilityCount])
400
                        else:
401
                            netRequirements[item.preferredVendor] = [[item, requirementsCount - availabilityCount]];
402
                else:
5944 mandeep.dh 403
                    item = self.__get_item_from_master(itemId)
4754 mandeep.dh 404
                    if item.preferredVendor is None:
5238 mandeep.dh 405
                        raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 406
                    if (netRequirements.has_key(item.preferredVendor)):
407
                        netRequirements[item.preferredVendor].append([item, requirementsCount])
408
                    else:
409
                        netRequirements[item.preferredVendor] = [[item, requirementsCount]];
5238 mandeep.dh 410
 
4754 mandeep.dh 411
            if not netRequirements:
412
                return purchaseOrders
413
 
414
            for vendorId in netRequirements.keys():
415
                t_purchase_order = TPurchaseOrder()
416
                t_purchase_order.supplierId = vendorId
417
                t_purchase_order.warehouseId = warehouseId
418
                t_purchase_order.lineitems = []
419
                for key in netRequirements.get(vendorId):
6762 amar.kumar 420
                    item = key[0]
4754 mandeep.dh 421
                    quantity = key[1]
422
                    t_po_lineitem = TLineItem()
423
                    t_po_lineitem.productGroup = item.productGroup
424
                    t_po_lineitem.brand = item.brand
425
                    t_po_lineitem.modelNumber = item.modelNumber
426
                    t_po_lineitem.modelName = item.modelName
427
                    t_po_lineitem.color = item.color
428
                    t_po_lineitem.itemId = item.id
6938 amar.kumar 429
                    if quantity <0: #TODO Check this logic
6882 amar.kumar 430
                        quantity=0
6861 amar.kumar 431
                    t_po_lineitem.quantity = quantity
6832 amar.kumar 432
                    t_po_lineitem.availableQuantity = 0
433
                    if availability.has_key(item.id):
6880 amar.kumar 434
                        if previouslyOrderedQty.has_key(item.id):
435
                            t_po_lineitem.availableQuantity = availability[item.id][0] - previouslyOrderedQty[item.id]
436
                        else:
437
                            t_po_lineitem.availableQuantity = availability[item.id][0]
6857 amar.kumar 438
                    if requirements.has_key(item.id):
439
                        t_po_lineitem.reservedQuantity = requirements[item.id]
8221 amar.kumar 440
                    additionalQty = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3])
441
                    additionalQty = max(0,(additionalQty - (advancedPOParameters[item.id][6]/2)))
442
                    suggestedQuantity = additionalQty +key[1]
443
                    t_po_lineitem.suggestedQuantity = max(0,suggestedQuantity)
444
                    #t_po_lineitem.suggestedQuantity = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3]) + key[1]
6821 amar.kumar 445
                    t_po_lineitem.avgSales = advancedPOParameters[item.id][1]
446
                    t_po_lineitem.numberOfDaysInStock = advancedPOParameters[item.id][2] 
447
                    t_po_lineitem.minStockLevel = advancedPOParameters[item.id][3]
6857 amar.kumar 448
                    t_po_lineitem.numberOfDaysStock = advancedPOParameters[item.id][4]
6880 amar.kumar 449
                    t_po_lineitem.lastXdaysSale = advancedPOParameters[item.id][5]
8182 amar.kumar 450
                    t_po_lineitem.rtoOrders = advancedPOParameters[item.id][6]
6880 amar.kumar 451
                    if previouslyOrderedQty.has_key(item.id):
452
                        t_po_lineitem.previouslyOrderedQty = previouslyOrderedQty[item.id]
453
                    else:
454
                        t_po_lineitem.previouslyOrderedQty = 0
4754 mandeep.dh 455
                    if codRequirements.has_key(item.id):
456
                        t_po_lineitem.codCount = min(codRequirements[item.id], quantity)
457
                    try:
5944 mandeep.dh 458
                        item_pricing = inventory_client.getItemPricing(item.id, vendorId)
4754 mandeep.dh 459
                    except Exception as e:
460
                        vendor = self.getSupplier(vendorId)
461
                        print 'Could not find transfer price for Item id: ' + str(item.id) + ' and vendor id: ' + str(vendorId)
462
                        print e
463
                        raise PurchaseServiceException(101, 'Transfer price missing for ' + vendor.name + ' and ' + " ".join([item.brand, item.modelName, item.modelNumber, item.color]))
464
                    t_po_lineitem.unitPrice = item_pricing.transferPrice
7672 rajveer 465
                    t_po_lineitem.nlc = item_pricing.nlc
9416 amar.kumar 466
                    t_po_lineitem.mrp = item.mrp
4754 mandeep.dh 467
                    t_purchase_order.lineitems.append(t_po_lineitem)
468
                purchaseOrders.append(t_purchase_order)
469
            return purchaseOrders
7105 amar.kumar 470
        except Exception as e:
471
            print e
8199 amar.kumar 472
            print sys.exc_info()[0]
21621 amit.gupta 473
            traceback.print_exc()
4754 mandeep.dh 474
        finally:
475
            self.close_session()
476
 
6762 amar.kumar 477
    def getSuppliers(self,):
4754 mandeep.dh 478
        """
479
        Returns all the valid suppliers
480
        """
481
        try:
21619 amit.gupta 482
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.filter(Supplier.id > 220).all()]
4754 mandeep.dh 483
        finally:
484
            self.close_session()
485
 
5185 mandeep.dh 486
    def unFulfillPO(self, purchaseId, itemId, quantity):
487
        """
488
        Unfulfills a given purchase id and an item with its quantity.
489
 
490
        Parameters:
491
         - purchaseId
492
         - itemId
493
         - quantity
494
        """
495
        try:
6762 amar.kumar 496
            purchaseOrderId = Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id
497
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
5185 mandeep.dh 498
            if lineitems:
499
                fulfilledQuantity = lineitems[0].quantity - lineitems[0].unfulfilledQuantity
500
                if fulfilledQuantity < quantity:
501
                    raise PurchaseServiceException(101, 'Can UnFulfill only ' + str(fulfilledQuantity) + 'quantity')
502
                else:
5437 mandeep.dh 503
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity + quantity
5185 mandeep.dh 504
                    lineitems[0].fulfilled = 0
505
                    purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
506
                    purchaseOrder.status = POStatus.PARTIALLY_FULFILLED
507
                    session.commit()
508
                    return
509
 
510
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
511
        finally:
512
            self.close_session()        
513
 
4754 mandeep.dh 514
    def fulfillPO(self, purchaseOrderId, itemId, quantity):
515
        """
516
        Fulfills a given purchase order with an item.
517
 
518
        Parameters:
519
         - purchaseOrderId
520
         - itemId
521
         - quantity
522
        """
523
        try:
6762 amar.kumar 524
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
4754 mandeep.dh 525
            if lineitems:
526
                if lineitems[0].unfulfilledQuantity < quantity:
5361 mandeep.dh 527
                    raise PurchaseServiceException(101, 'Can fulfill only ' + str(lineitems[0].unfulfilledQuantity) + ' quantity')
4754 mandeep.dh 528
                else:
5361 mandeep.dh 529
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity - quantity
4754 mandeep.dh 530
                    if not lineitems[0].unfulfilledQuantity:
531
                        lineitems[0].fulfilled = 1
5361 mandeep.dh 532
                        session.commit()
6762 amar.kumar 533
                        if not LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, fulfilled=0).all():
5361 mandeep.dh 534
                            purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
4754 mandeep.dh 535
                            purchaseOrder.status = POStatus.CLOSED
536
                    session.commit()
537
                    return
538
 
6762 amar.kumar 539
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
4754 mandeep.dh 540
        finally:
541
            self.close_session()
542
 
543
    def updatePurchaseOrder(self, purchaseOrder):
544
        """
545
        Amends a PO sa per the new lineitems passed
546
 
547
        Parameters:
548
         - purchaseOrder
549
        """
550
        try:
6762 amar.kumar 551
            existingPurchaseOrder = PurchaseOrder.get_by(id=purchaseOrder.id)
4754 mandeep.dh 552
            maxRevision = 0
6762 amar.kumar 553
            existingRevisions = RevisionedPurchaseOrder.query.filter_by(purchaseOrderId=purchaseOrder.id).all()
4754 mandeep.dh 554
            if existingRevisions:
555
                maxRevision = max([a.revision for a in existingRevisions]) + 1
5147 mandeep.dh 556
 
557
            newPOItems = {}
558
            for t_lineitem in purchaseOrder.lineitems:
559
                newPOItems[t_lineitem.itemId] = t_lineitem
560
 
4754 mandeep.dh 561
            for lineitem in existingPurchaseOrder.lineitems:
5147 mandeep.dh 562
                fulfilledQuantity = lineitem.quantity - lineitem.unfulfilledQuantity
563
                if fulfilledQuantity:
564
                    if not newPOItems.has_key(lineitem.itemId):
565
                        raise PurchaseServiceException(101, 'Cannot remove fulfilled item id: ' + str(lineitem.itemId) + ' from PO')
566
                    else:
567
                        if newPOItems[lineitem.itemId].quantity < fulfilledQuantity:
568
                            raise PurchaseServiceException(101, 'More quantity already fulfilled for item id: ' + str(lineitem.itemId))
569
                        else:
5437 mandeep.dh 570
                            newPOItems[lineitem.itemId].unfulfilledQuantity = newPOItems[lineitem.itemId].unfulfilledQuantity - fulfilledQuantity
4754 mandeep.dh 571
                revisionedPurchaseOrder = RevisionedPurchaseOrder()
572
                revisionedPurchaseOrder.purchaseOrderId = purchaseOrder.id
573
                revisionedPurchaseOrder.revision = maxRevision
574
                revisionedPurchaseOrder.itemId = lineitem.itemId
575
                revisionedPurchaseOrder.unfulfilledQuantity = lineitem.unfulfilledQuantity
576
                revisionedPurchaseOrder.unitPrice = lineitem.unitPrice
7672 rajveer 577
                revisionedPurchaseOrder.nlc = lineitem.nlc
4754 mandeep.dh 578
                revisionedPurchaseOrder.createdAt = lineitem.createdAt
579
                revisionedPurchaseOrder.quantity = lineitem.quantity
580
                lineitem.delete()
581
            existingPurchaseOrder.lineitems = [LineItem(existingPurchaseOrder, t_lineitem) for t_lineitem in purchaseOrder.lineitems]
582
            existingPurchaseOrder.totalCost = sum([t_lineitem.quantity * t_lineitem.unitPrice for t_lineitem in purchaseOrder.lineitems])
583
            session.commit()
584
        finally:
585
            self.close_session()
586
 
4503 mandeep.dh 587
    def close_session(self):
588
        if session.is_active:
589
            print "session is active. closing it."
590
            session.close()
591
 
5443 mandeep.dh 592
    def getInvoices(self, date):
593
        """
594
        Fetches all invoices for a given date
595
 
596
        Parameters:
597
         - date
598
        """
599
        try:
600
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).all()]
601
        finally:
602
            self.close_session()
6630 amar.kumar 603
 
7410 amar.kumar 604
    def getInvoicesForWarehouse(self, warehouseId, supplierId, date):
605
        """
606
        Fetches all invoices for a given date for specified physical warehouse
607
 
608
        Parameters:
609
         - date
610
        """
611
        try:
612
            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()]
613
        finally:
614
            self.close_session()
615
 
6630 amar.kumar 616
    def getInvoice(self, invoiceNumber, supplierId):
617
        """
618
        Fetches all invoices for  given invoiceNumber and supplierId 
5443 mandeep.dh 619
 
6630 amar.kumar 620
        Parameters:
621
         - invoiceNumber, supplierId
622
        """
623
        try:
6762 amar.kumar 624
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
6638 amar.kumar 625
            if invoice is None:
6762 amar.kumar 626
                return None
6638 amar.kumar 627
            else:
628
                return invoice.to_thrift_object()
6630 amar.kumar 629
        finally:
630
            self.close_session()
631
 
5443 mandeep.dh 632
    def createInvoice(self, invoice):
633
        """
634
        Creates an invoice object
635
 
636
        Parameters:
637
         - invoice
638
        """
639
        try:
6762 amar.kumar 640
            if Invoice.query.filter_by(supplierId=invoice.supplierId, date=to_py_date(invoice.date), invoiceNumber=invoice.invoiceNumber).all():
5768 mandeep.dh 641
                raise PurchaseServiceException(ExceptionType.ILLEGAL_ARGUMENTS, "Already received such invoice")
5443 mandeep.dh 642
            invoiceObj = Invoice()
643
            invoiceObj.invoiceNumber = invoice.invoiceNumber
644
            invoiceObj.date = to_py_date(invoice.date)
645
            invoiceObj.receivedFrom = invoice.receivedFrom
646
            invoiceObj.numItems = invoice.numItems
647
            invoiceObj.supplierId = invoice.supplierId
7410 amar.kumar 648
            invoiceObj.warehouseId = invoice.warehouseId
11219 manish.sha 649
            invoiceObj.invoiceDate = to_py_date(invoice.invoiceDate)
5443 mandeep.dh 650
            session.commit()
651
        finally:
652
            self.close_session()        
653
 
5591 mandeep.dh 654
    def addSupplier(self, supplier):
655
        """
656
        Creates a supplier
657
 
658
        Parameters:
659
         - supplier
660
        """
661
        try:
662
            supplierObj = Supplier()
663
            supplierObj.communicationAddress = supplier.communicationAddress
664
            supplierObj.contactEmail = supplier.contactEmail
665
            supplierObj.contactFax = supplier.contactFax
666
            supplierObj.contactName = supplier.contactName
667
            supplierObj.contactPhone = supplier.contactPhone
668
            supplierObj.fax = supplier.fax
669
            supplierObj.headDesignation = supplier.headDesignation
670
            supplierObj.headEmail = supplier.headEmail
671
            supplierObj.headName = supplier.headName
672
            supplierObj.name = supplier.name
673
            supplierObj.pan = supplier.pan
674
            supplierObj.phone = supplier.phone
675
            supplierObj.registeredAddress = supplier.registeredAddress
676
            supplierObj.tin = supplier.tin
10295 amar.kumar 677
            supplierObj.stateId = supplier.stateId
14072 manish.sha 678
            supplierObj.poValidityLimit = supplier.poValidityLimit
5591 mandeep.dh 679
            session.commit()
680
            return self.getSupplier(supplierObj.id)
681
        finally:
682
            self.close_session()
683
 
684
    def updateSupplier(self, supplier):
685
        """
686
        Updates a supplier
687
 
688
        Parameters:
689
         - supplier
690
        """
691
        try:
692
            supplierObj = Supplier.get(supplier.id)
693
            supplierObj.communicationAddress = supplier.communicationAddress
694
            supplierObj.contactEmail = supplier.contactEmail
695
            supplierObj.contactFax = supplier.contactFax
696
            supplierObj.contactName = supplier.contactName
697
            supplierObj.contactPhone = supplier.contactPhone
698
            supplierObj.fax = supplier.fax
699
            supplierObj.headDesignation = supplier.headDesignation
700
            supplierObj.headEmail = supplier.headEmail
701
            supplierObj.headName = supplier.headName
702
            supplierObj.name = supplier.name
703
            supplierObj.pan = supplier.pan
704
            supplierObj.phone = supplier.phone
705
            supplierObj.registeredAddress = supplier.registeredAddress
706
            supplierObj.tin = supplier.tin
13965 manish.sha 707
            supplierObj.stateId = supplierObj.stateId
14072 manish.sha 708
            supplierObj.poValidityLimit = supplier.poValidityLimit
5591 mandeep.dh 709
            session.commit()
710
        finally:
711
            self.close_session()
712
 
6385 amar.kumar 713
    def getInvoicesForPO(self, poNumber):
714
        '''
715
        For getting invoiceNumbers for a Purchase Order
716
        '''
717
        try:
718
 
6762 amar.kumar 719
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 720
            for purchase in purchases:
721
                invoice = purchase.invoiceNumber
722
        except:
723
            return None
724
        finally:
725
            self.close_session()
6467 amar.kumar 726
 
727
    def createPurchaseReturn(self, t_purchaseReturn):
728
        '''
729
        For creating a new Purchase Return
730
        '''
731
        try:
6762 amar.kumar 732
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 733
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
734
            purchaseReturn.amount = t_purchaseReturn.amount
735
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
736
            purchaseReturn.isSettled = False
6821 amar.kumar 737
            purchaseReturn.type = t_purchaseReturn.type
10864 manish.sha 738
            purchaseReturn.returnInventoryType = t_purchaseReturn.returnInventoryType
13600 manish.sha 739
            purchaseReturn.unsettledAmount = t_purchaseReturn.amount
6467 amar.kumar 740
            session.commit()
741
            return purchaseReturn.id
742
        except Exception as e:
743
            print e
744
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
745
        finally:
746
            self.close_session()
747
 
748
    def getUnsettledPurchaseReturns(self):
749
        '''
750
        For getting all unsettled Purchase Returns
751
        '''
752
        try:
6821 amar.kumar 753
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 754
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
755
        except Exception as e:
756
            print e
757
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
758
        finally:
759
            self.close_session()
6385 amar.kumar 760
 
6467 amar.kumar 761
    def settlePurchaseReturn(self, returnId):
762
        '''
763
        For marking a Purchase Return as settled
764
        '''
765
        try:
6762 amar.kumar 766
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 767
            purchaseReturn.isSettled = True
768
            session.commit()
769
        except Exception as e:
770
            print e
771
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
772
        finally:
773
            self.close_session()
6762 amar.kumar 774
 
7672 rajveer 775
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, nlc, itemId):
6762 amar.kumar 776
        try:
777
            poId = self.getPOforOurExternalBilling()
7672 rajveer 778
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice, nlc)
6762 amar.kumar 779
            self.receiveinvoiceforOursExternalBilling(invoiceNumber)
780
            return self.createPurchaseforOursExternalBilling(poId, invoiceNumber)
781
        except Exception as e:
782
            print e
783
            raise PurchaseServiceException(101, '')
784
        finally:
785
            self.close_session()
786
 
787
    def fulfillPOForExtBilling(self, itemId, quantity):
788
        poId = self.getPOforOurExternalBilling()
789
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
790
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
791
        if not lineItem.unfulfilledQuantity:
792
            lineItem.fulfilled = 1
793
        session.commit()
7410 amar.kumar 794
 
795
    def closePO(self, poId):
796
        purchaseOrder = PurchaseOrder.get_by(id=poId)
797
        if not purchaseOrder:
798
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
799
        purchaseOrder.status = 4
800
        session.commit()
9925 amar.kumar 801
 
802
    def changePOStatus(self, poId, poStatus):
803
        purchaseOrder = PurchaseOrder.get_by(id=poId)
804
        if not purchaseOrder:
805
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
806
        purchaseOrder.status = POStatus.READY
807
        session.commit()
6467 amar.kumar 808
 
7410 amar.kumar 809
    def isInvoiceReceived(self, invoiceNumber, supplierId):
810
        """
811
        Returns whether invoice is already received for given invoiceNumber and supplierId 
812
 
813
        Parameters:
814
         - invoiceNumber, supplierId
815
        """
816
        try:
817
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
818
            if invoice is None:
819
                return False
820
            else:
821
                return True
822
        finally:
823
            self.close_session()
9829 amar.kumar 824
 
825
    def changeWarehouseForPO(self, poId, warehouseId):
826
        try:
827
            purchaseOrder = PurchaseOrder.get_by(id = poId)
828
            for lineitem in purchaseOrder.lineitems:
829
                if lineitem.quantity!=lineitem.unfulfilledQuantity:
830
                    raise PurchaseServiceException(101, 'Items have already been received for this PO and hence cant change warehouse')
831
            purchaseOrder.warehouseId = warehouseId
832
            session.commit()
833
        finally:
11751 manish.sha 834
            self.close_session()  
835
 
836
    def getPurchaseReturn(self, id):
837
        """
838
        Returns the purchase return with the given id. Throws an exception if there is no such purchase return.
839
 
840
        Parameters:
841
         - id
842
        """
843
        try:
844
            purchaseReturn = PurchaseReturn.get_by(id=id)
845
            if not purchaseReturn:
846
                raise PurchaseServiceException(101, "No purchase return can be found with id:" + str(id)) 
847
            return purchaseReturn.to_thrift_object()
848
        finally:
849
            self.close_session()
9829 amar.kumar 850
 
13600 manish.sha 851
    def markPurchasereturnSettled(self, id, settlementType, documentNumber, settlementBy, settledAmount):
852
        try:
853
            currentTime = datetime.datetime.now()
854
            purchaseReturn = PurchaseReturn.get_by(id=id)
855
            if not purchaseReturn:
856
                raise PurchaseServiceException(101, "No purchase return can be found with id:" + str(id)) 
857
            if settledAmount > purchaseReturn.unsettledAmount:
858
                raise PurchaseServiceException(101, "Purchase Return Settled Amount Can't be Greater than Unsettled Amount Purchase Return id:" + str(id))
859
            purchaseReturn.currentSettlementType = settlementType
860
            purchaseReturn.latestSettlementDate = currentTime
861
            if purchaseReturn.documentNumber : 
862
                purchaseReturn.documentNumber = purchaseReturn.documentNumber +";"+documentNumber
863
            else:
864
                purchaseReturn.documentNumber = documentNumber
865
            unsettledAmount = purchaseReturn.unsettledAmount - settledAmount
866
            purchaseReturn.unsettledAmount = purchaseReturn.unsettledAmount - settledAmount
867
            if unsettledAmount ==0:
868
                purchaseReturn.isSettled = 1
869
 
870
            purchaseReturnSettlement = PurchaseReturnSettlement()
871
            purchaseReturnSettlement.purchaseReturnId = id
872
            purchaseReturnSettlement.settlementType = settlementType
873
            purchaseReturnSettlement.settlementBy = settlementBy
874
            purchaseReturnSettlement.settlementAmount = settledAmount
875
            purchaseReturnSettlement.settlementDate = currentTime
876
            purchaseReturnSettlement.documentNumber = documentNumber
877
            session.commit()
878
            return True
879
        finally:
880
            self.close_session()
881
 
882
    def getPrSettlementsForPurchaseReturn(self, purchaseReturnId):
883
        try:
884
            settlements = PurchaseReturnSettlement.query.filter_by(purchaseReturnId=purchaseReturnId).all()
885
            prSettlements = []
886
            for settlement in settlements:
887
                prSettlements.append(settlement.to_thrift_object())
888
            return prSettlements
889
        finally:
890
            self.close_session()
891
 
892
    def updatePurchaseReturn(self, t_purchaseReturn):
893
        '''
894
        Updating a Purchase Return
895
        '''
896
        try:
897
            purchaseReturn = PurchaseReturn.get_by(id=t_purchaseReturn.id)
898
            purchaseReturn.purchaseReturnType = t_purchaseReturn.purchaseReturnType
899
            purchaseReturn.reasonText = t_purchaseReturn.reasonText
900
            purchaseReturn.createdBy = t_purchaseReturn.createdBy
901
            session.commit()
902
        finally:
903
            self.close_session()
904
 
6762 amar.kumar 905
    def isAlive(self,):
4503 mandeep.dh 906
        """
907
        For checking weather service is active alive or not. It also checks connectivity with database
908
        """
909
        try:
910
            session.query(Supplier.id).limit(1).all()
911
            return True
912
        except:
913
            return False
914
        finally:
915
            self.close_session()
5944 mandeep.dh 916
 
917
    def __get_item_from_master(self, item_id):
918
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 919
        return client.getItem(item_id)
13600 manish.sha 920