Exemplo n.º 1
0
	def AutoTransferReceiptItems(self, ReceiptID):
		'''	Go through the receipt items and check to see if the item is
			an automatic transfer item, that is, the item is marked as a non-
			dispensable item (ie. it cannot be dispensed) so we need to
			transfer it automatically.  Registration and bed assignment are
			examples of such items.  NOTE: dispensing for automatic items
			should only happen AFTER payment.  If the item is not paid for
			then make sure it is not marked dispensed
		'''
		log.debug('AutoTransferReceiptItems');
		receipt = model.InvReceipt.get(ReceiptID)
		for item in receipt.CatalogItems:
			if item.IsPaid() and (not item.CatalogItem.IsDispensable):
				#find all transfers (normally just one) and mark them complete
				for stocklocation in item.StockItems:
					for transfer in stocklocation.TransfersToHere:
						if not transfer.IsComplete:
							transfer.IsComplete = True
							transfer.DateTransferred = model.cur_date_time()
							transfer.FromStockLocation.Quantity -= transfer.Qty
							transfer.ToStockLocation.Quantity += transfer.Qty
							log.debug('....Auto dispensing item %d' % item.id)
			elif (not item.IsPaid()) and (not item.CatalogItem.IsDispensable):
				#find all transfers (normally just one) and mark them not complete
				for stocklocation in item.StockItems:
					for transfer in stocklocation.TransfersToHere:
						if transfer.IsComplete:
							transfer.FromStockLocation.Quantity += transfer.Qty
							transfer.ToStockLocation.Quantity -= transfer.Qty
							transfer.IsComplete = False
						log.debug('....Marking not dispensed item %d' % item.id)
Exemplo n.º 2
0
	def BillingRefund(self, ReceiptID, CashAmt, **kw):
		'''	Refund some cash to a customer
			Only allow refunds if the customer has credit, and only up to the credit amount
			If a refund cannot be fulfilled as requested, then don't do any refund at all, even
			if the customer has some credit
		'''
		# Load the customer
		Customer = model.InvReceipt.get(ReceiptID).Customer
		if (Customer.CalcCashBalance() >= 0):
			ErrorMsg = 'Refund rejected, Customer has no credit'
			NextLink = 'index?receipt_id=%d' % ReceiptID
			raise cherrypy.HTTPRedirect('DataEntryError?error=%s&next_link=%s' % (ErrorMsg, NextLink))
		elif (CashAmt <= 0):
			ErrorMsg = 'Refund ignored, cannot refund a 0 or negative amount'
			NextLink = 'index?receipt_id=%d' % ReceiptID
			raise cherrypy.HTTPRedirect('DataEntryError?error=%s&next_link=%s' % (ErrorMsg, NextLink))
		elif (Customer.CalcBalance() + CashAmt > 0):
			ErrorMsg = 'Refund rejected, Customer has insufficient credit'
			NextLink = 'index?receipt_id=%d' % ReceiptID
			raise cherrypy.HTTPRedirect('DataEntryError?error=%s&next_link=%s' % (ErrorMsg, NextLink))
		else:
			payment = model.InvCustomerPayment(CustomerID=Customer.id, DatePaid=model.cur_date_time(),\
				Amount=-CashAmt,Notes='Cash refund from user id: %s' % (model.cur_user_id()))
		raise cherrypy.HTTPRedirect('index?receipt_id=%d' % ReceiptID)
def CustomerPayment(self, id='',Id='', Op='', CustomerID='', **kw):
	if Id != '':
		id = Id
	if id != '':
		try:
			int_id = int(id)
			record = model.InvCustomerPayment.get(int_id)
		except (ValueError, SQLObjectNotFound):
			int_id = -1
	else:
		int_id = -1
	#Find initial values for our data record
	#Vendor -> Customer
	#Amount NEW
	#ValidOn -> DatePaid
	if int_id > 0:
		Id_data = record.id
		Name_data = record.Name()
		Notes_data = record.Notes
		DatePaid_data = record.DatePaid
		Amount_data = record.Amount
		#ForeignKeys
		try:
			Customer_data = record.CustomerID
			Customer_display = record.Customer.Name + ' ('+str(record.CustomerID)+')'
		except AttributeError: 
			Customer_data = ''
			Customer_display = 'None'
		#MultiJoin and RelatedJoin
	else:
		Id_data = ''
		Name_data = 'New entry'
		Notes_data = ''
		DatePaid_data = model.cur_date_time()
		Amount_data = '0.0'
		#ForeignKeys
		if CustomerID != '':			
			Customer_data = CustomerID
			Customer_display = model.InvCustomer.get(int(CustomerID)).Name
		else:
			Customer_data = ''
			Customer_display = 'None'
		#MultiJoin and RelatedJoin
	#Special manipulations for new records
	if Op == 'CopyIntoNew':
		Id_data = ''
		id = ''
	#Construct our display fields
	Id = dict(id="cp_Id", name="Id", label="Id", type="Hidden",attr={}, data=Id_data)
	Name = dict(id="cp_Name", name="Name", label="Name", type="StringRO",attr=dict(length=50), data=Name_data)
	DatePaid = dict(id="cp_DatePaid", name="DatePaid", label="Date paid", type="DateTime",attr=dict(), data=DatePaid_data)
	Amount = dict(id="cp_Amount", name="Amount", label="Amount", type="Currency",attr=dict(), data=Amount_data)
	Notes = dict(id="cp_Notes", name="Notes", label="Notes", type="String",attr=dict(length=50), data=Notes_data)
	#ForeignKeys
	SrchCustomerName = dict(id="cp_SrchCustomerName", name="Name", label="Name", type="String",attr=dict(length=25), data='')
	Customer = dict(id="cp_Customer", name="Customer", label="Customer", type="ForeignKey",attr=dict(srchUrl="CustomerSearch",lookupUrl="CustomerGet", edit_url='Customer', srchFields=[SrchCustomerName]), data=Customer_data, init_display=Customer_display)
	#MultiJoin
	#Fields
	fields = [Id, Name, Customer, Amount, DatePaid, Notes]
	#Configure any of the links that might need configuring
	if id == '':
		CustomerPaymentMenu = 'CustomerPaymentMenu'
	else:
		CustomerPaymentMenu = 'CustomerPaymentMenu?id=' + id
	#RETURN VALUES HERE
	return dict(id=id, Name='CustomerPayment', Label='Customer payment entry', Fields=fields, FieldsSrch=[Name], Read='CustomerPayment', Add='CustomerPaymentSave', Del='CustomerPaymentDel', UnDel='CustomerPaymentUnDel', Edit='CustomerPayment', Save='CustomerPaymentSave', SrchUrl='CustomerPaymentSearch', MenuBar=CustomerPaymentMenu)
Exemplo n.º 4
0
	def MakeReceiptPayment(self, ReceiptID, TotalCashAmt=0, CashAmt=0, CashNotes='', InsrAmt=0, InsrNotes='', **kw):
		'''	Go through all the receipt items in the receipt and mark the items
			as paid for.  Create a new payment record (marking the date and 
			amount when money was exchanged).
			Double check the items on the receipt and make sure they are marked as paid if no payments are
			outstanding.
		'''
		log.debug('MakeReceiptPayment')
		try:
			record = model.InvReceipt.get(ReceiptID)
		except (ValueError, SQLObjectNotFound): #happens when the conversion fails or the record is not found
			return dict(flash='No record to make payment for')
		# Make our payment record
		if TotalCashAmt !=0:
			payment = model.InvCustomerPayment(CustomerID=record.CustomerID, DatePaid=model.cur_date_time(),\
				Amount=TotalCashAmt,Notes=CashNotes)
		# Figure out how much money the customer has for spending - without including the current receipt amount
		CurrCredit = -record.Customer.CalcBalance(DoNotIncludReceiptID=ReceiptID)
		log.debug('....Current credit: %d' % CurrCredit)
		# Make sure no one is trying to cheat the program by forcing an Insurance payment
		if self.IsSelfPay(ReceiptID) and InsrAmt > 0:
			CashAmt += InsrAmt
			InsrAmt = 0
		# Go through and confirm the unit cost again (and verify that all receipt items have been assigned to stock)
		for item in record.CatalogItems:
			# Check to make sure all the items are assigned to a particular stock item
			if len(item.StockItems) == 0: # Hmmm... somehow the item wasn't assigned to a stock location
				# At this point, we'll just assign the next available stock location to the item
				# We'll force a re-adjustment if the quantities cannot be fulfilled (no option at this point?)
				StockItemID = item.CatalogItem.NextStockItemID(item.Quantity)
				if StockItemID == None: # Insufficient stock to fulfill request, try to partially fill it
					StockItemID = item.CatalogItem.NextStockItemID()
					if StockItemID == None: # No stock at all, set the receipt item to zero!!!!!
						item.Quantity = 0
						item.UnitCost = 0
				if StockItemID != None: # Complete the assignment
					StockItem = model.InvStockItem.get(StockItemID)
					if item.Quantity > StockItem.QtyAvailable():
						item.Quantity = StockItem.QtyAvailable()
					StockLocationIDs = StockItem.FindStockLocationIDs(item.Quantity)
					if record.Customer.InventoryLocationID == None:
						LocationID = self.GetDefaultCustomerLocationID()
					else:
						LocationID = record.Customer.InventoryLocationID 
					new_stocklocation = model.InvStockLocation(StockItemID=StockItemID, \
						LocationID=LocationID, ReceiptID=item.id, Quantity=0.0, IsConsumed=True, IsSold=True)
					#Create the stock transfer
					log.debug('......creating %d new stock transfer(s)' % len(StockLocationIDs))
					CurrQuantity = item.Quantity # Keep track of the current quantity transferred
					for stocklocationid in StockLocationIDs:
						StockLocation = model.InvStockLocation.get(stocklocationid)
						if CurrQuantity <= StockLocation.QtyAvailable():
							TransferQty = CurrQuantity
							CurrQuantity = 0
						else:
							TransferQty = StockLocation.QtyAvailable()
							CurrQuantity = CurrQuantity - TransferQty
						new_stck_transfer = model.InvStockTransfer(FromStockLocationID=stocklocationid, \
							ToStockLocation=new_stocklocation.id, Qty=TransferQty)
						if CurrQuantity <= 0:
							break
					#Update the unit price
					item.UnitCost = item.StockItems[0].StockItem.SalePrice
			else:
				item.UnitCost = item.StockItems[0].StockItem.SalePrice
		# Apply the payment to our Receipt and linked items.  Note: record = current receipt
		record.TotalPayment = record.TotalPaymentCalc()
		NewAmt = CurrCredit + InsrAmt # This is what we have to spend
		record.TotalPaid += NewAmt
		# Cap the total paid to the payment required
		if record.TotalPaid > record.TotalPayment:
			record.TotalPaid = record.TotalPayment
			# For cash amounts in excess of the required payment, limit the amount applied
			if CashAmt > record.TotalPayment:
				CashAmt = record.TotalPayment
			# Limit insurance amount payments
			if InsrAmt > record.TotalPayment:
				InsrAmt = record.TotalPayment
			# For combo payments, Insurance is reduced and cash is used as the greater part when needed.
			if (CashAmt + InsrAmt) > record.TotalPayment:
				InsrAmt = record.TotalPayment - CashAmt
		log.debug('....Money to spend: %d' % record.TotalPaid)
		# The TotalAmt is what we have for making payments on our stock location items
		TotalAmt = record.TotalPaid
		record.TotalSelfPay = CashAmt # Shows how much of the bill is Cash amount
		record.SelfPayNotes = CashNotes
		record.TotalInsurance = InsrAmt # How much of this bill is paid by insurance
		record.InsuranceNotes = InsrNotes
		# Update payments on the stock items for accounting and dispensing
		for item in record.CatalogItems:
			if (not item.IsPaid()) and (not item.IsDispensed()):#Don't change items which are paid for or dispensed
				log.debug('....Updating payments on stock location')
				PartPay = round(item.Quantity * item.UnitCost) - item.TotalPaid()
				if PartPay > 0: #We need to apply new payments to our stock (as much as we have money for)
					if PartPay > TotalAmt:
						PartPay = TotalAmt
						TotalAmt = 0
						log.debug('....Too little money')
					else:
						TotalAmt -= PartPay
					for stocklocation in item.StockItems:
						stockpaid = round(stocklocation.QtyAfterTransfers() * stocklocation.StockItem.SalePrice) - stocklocation.TotalPaid
						log.debug('....StockLocation %d with Rs. %d' % (stocklocation.id,stockpaid))
						if stockpaid > 0: # We still have more to pay
							if stockpaid > PartPay:
								stockpaid = PartPay
								PartPay = 0
								log.debug('....Too little rupees')
							else:
								PartPay -= stockpaid
							stocklocation.TotalPaid += round(stockpaid)
						elif stockpaid < 0: # we have reduced stock from this transfer
							PartPay -= stockpaid
							stocklocation.TotalPaid = round(stocklocation.QtyAfterTransfers() * stocklocation.StockItem.SalePrice)
				else: #We've reduced amounts and are actually refunding money at this point.  Fix our payment records
					TotalAmt -= PartPay
					# Go through all the stock items and adjust the TotalPaid.  Don't worry about keeping track
					# since we've reduced cost
					for stocklocation in item.StockItems:
						stocklocation.TotalPaid = round(stocklocation.QtyAfterTransfers() * stocklocation.StockItem.SalePrice)
			else:
				TotalAmt -= item.TotalPaid()
		# For auto-transfer items, transfer them after payment
		self.AutoTransferReceiptItems(ReceiptID)
		return self.LoadPatientData(ReceiptID=ReceiptID)
def StockTransferRequest(self, id='',Id='', Op='', **kw):
	if Id != '':
		id = Id
	if id != '':
		try:
			int_id = int(id)
			record = model.InvStockTransferRequest.get(int_id)
		except (ValueError, SQLObjectNotFound):
			int_id = -1
	else:
		int_id = -1
	#Find initial values for our data record
	if int_id > 0:
		Id_data = record.id
		Name_data = record.Name()
		Notes_data = record.Notes
		RequestedBy_data = record.RequestedBy
		RequestedOn_data = record.RequestedOn
		RequiredBy_data = record.RequiredBy
		#ForeignKeys
		try:
			ForLocation_data = record.ForLocation.id
			ForLocation_display = record.ForLocation.Name + ' ('+str(record.ForLocation.id)+')'
		except AttributeError: 
			ForLocation_data = ''
			ForLocation_display = 'None'
		#MultiJoin and RelatedJoin
		Items_data = 'There are ' + str(len(record.Items)) + ' records'
		if record.Status == 'deleted':
			DisplayMessage_data = "NOTE: This record is marked deleted!"
		else:
			DisplayMessage_data = ""
	else:
		Id_data = ''
		Name_data = ''
		Notes_data = ''
		RequestedBy_data = model.cur_user_id()
		RequestedOn_data = model.cur_date_time().strftime('%Y-%m-%d')
		RequiredBy_data = model.cur_date_time().strftime('%Y-%m-%d')
		#ForeignKeys
		ForLocation_data = ''
		ForLocation_display = 'None'
		#MultiJoin and RelatedJoin
		Items_data = 'There are no records'
	#Special manipulations for new records
	if Op == 'CopyIntoNew':
		#ForeignKeys
		Name_data = ''
		RequestedBy_data = model.cur_user_id()
		RequestedOn_data = model.cur_date_time().strftime('%Y-%m-%d')
		RequiredBy_data = model.cur_date_time().strftime('%Y-%m-%d')
		#MultiJoin and RelatedJoin
		Items_data = 'There are no records'
		Id_data = ''
		id = ''
	#Construct our display fields
	Id = dict(id="str_Id", name="Id", label="Id", type="Hidden",attr={}, data=Id_data)
	Name = dict(id="str_Name", name="Name", label="Name", type="StringRO",attr=dict(length=50), data=Name_data)
	RequestedBy = dict(id="str_RequestedBy", name="RequestedBy", label="Requested by", type="StringRO",attr=dict(length=50), data=RequestedBy_data)
	RequestedOn = dict(id="str_RequestedOn", name="RequestedOn", label="Requested on", type="DateTime",attr=dict(), data=RequestedOn_data)
	RequiredBy = dict(id="str_RequiredBy", name="RequiredBy", label="Required by", type="DateTime",attr=dict(), data=RequiredBy_data)
	Notes = dict(id="str_Notes", name="Notes", label="Notes", type="String",attr=dict(length=50), data=Notes_data)
	#ForeignKeys
	SrchLocationName = dict(id="str_SrchLocationName", name="Name", label="Name", type="String",attr=dict(length=25), data='')
	ForLocation = dict(id="str_ForLocation", name="ForLocation", label="ForLocation", type="ForeignKey",attr=dict(srchUrl="LocationSearch",lookupUrl="LocationGet", edit_url='Location', srchFields=[SrchLocationName]), data=ForLocation_data, init_display=ForLocation_display)
	#MultiJoin
	Items = dict(id="str_Items", name="Items", label="Items", type="MultiJoin",attr=dict(displayUrl="StockTransferRequestMultiJoinList",listUrl="StockTransferRequestMultiJoinList", linkUrl="StockTransferRequestItem"), data=Items_data)
	#Fields
	fields = [Id, Name, RequestedBy, RequestedOn, RequiredBy, ForLocation, Items, Notes]
	#Configure any of the links that might need configuring
	if id == '':
		StockTransferRequestMenu = 'StockTransferRequestMenu'
	else:
		StockTransferRequestMenu = 'StockTransferRequestMenu?id=' + id
	#RETURN VALUES HERE
	return dict(id=id, Name='StockTransferRequest', Label='Stock transfer request entry', Fields=fields, FieldsSrch=[Name], Read='StockTransferRequest', Add='StockTransferRequestSave', Del='StockTransferRequestDel', UnDel='StockTransferRequestUnDel', Edit='StockTransferRequest', Save='StockTransferRequestSave', SrchUrl='StockTransferRequestSearch', MenuBar=StockTransferRequestMenu)