def create_line_obj(line_dic, codes): line = SalesItemLine() line.LineNum = line_dic['lineno'] line.Description = line_dic['itemdesc'] line.Amount = line_dic['unitprice'] line.SalesItemLineDetail = SalesItemLineDetail() line_item_code = line_dic['itemcode'] line.SalesItemLineDetail.ItemRef = codes[line_item_code].to_ref() return line
def create_line_obj_for_post(validate_date, codes): line = SalesItemLine() line.LineNum = validate_date.get('line_no') line.Description = validate_date.get('item_description') line.Amount = validate_date.get('unit_price') line.SalesItemLineDetail = SalesItemLineDetail() line_item_code = validate_date.get('item_code') line.SalesItemLineDetail.ItemRef = codes[line_item_code].to_ref() line.SalesItemLineDetail.TaxCodeRef = '24' return line
def qbo_create_invoice(so, customer_id): client = create_qbc() customer_ref = Customer.get(customer_id, qb=client).to_ref() line_detail = SalesItemLineDetail() line_detail.UnitPrice = 100 # in dollars line_detail.Qty = 1 # quantity can be decimal item_ref = Item.get(35, qb=client).to_ref() line_detail.ItemRef = item_ref line = SalesItemLine() line.Amount = 100 # in dollars line.SalesItemLineDetail = line_detail line.DetailType = "SalesItemLineDetail" invoice = Invoice() invoice.CustomerRef = customer_ref invoice.Line = [line] invoice.save(qb=client)
def stripe_fee_line_item(payments, total, payment_id, stripe_fees_item, order_date, other_fees=0, qbo_class=None): charge = payments.get(payment_id) if charge is None: return transaction = stripe.BalanceTransaction.retrieve( charge.balance_transaction) stripe_fee_info = None for fee_info in transaction.fee_details: if fee_info.type == 'stripe_fee': stripe_fee_info = fee_info break if stripe_fee_info is None: logger.error(str(transaction.fee_details)) raise Exception("could not find stripe fee in fees") stripe_fee_amount = Decimal(stripe_fee_info.amount) / Decimal(100.0) logger.debug("stripe fee amount %s" % stripe_fee_amount) line = SalesItemLine() if stripe_fee_for_total(total) == stripe_fee_amount: line.Amount = (-1) * stripe_fee_for_total(total) line.Description = "Stripe fees of {:.1%} of ${:.2f} plus ${:.2f}".format( stripe_rate, total, stripe_fixed) elif stripe_fee_for_total_amex(total) == stripe_fee_amount: line.Amount = (-1) * stripe_fee_for_total_amex(total) line.Description = "Stripe AmEx fees of {:.1%} of ${:.2f}".format( stripe_amex_rate, total, stripe_fixed) else: logger.debug( "stripe fees of %s don't match standard fees of %s or amex fees of %s" % (stripe_fee_amount, stripe_fee_for_total(total), stripe_fee_for_total_amex(total))) line.Amount = (-1) * stripe_fee_amount line.Description = "Stripe fees" detail = SalesItemLineDetail() detail.ItemRef = stripe_fees_item.to_ref() detail.Qty = one detail.UnitPrice = line.Amount if qbo_class is not None: detail.ClassRef = qbo_class.to_ref() detail.ServiceDate = order_date.strftime("%Y-%m-%d") line.SalesItemLineDetail = detail return line
def save_invoice(order): customer = get_customer(order.student) invoice = Invoice.filter(max_results=1, DocNumber=order.number, qb=client) if invoice: invoice = invoice[0] else: invoice = Invoice() invoice.DocNumber = order.number invoice.CustomerRef = customer.to_ref() invoice.DueDate = order.date_paid # Term does not have a to_ref method, go figure, so we manually generate this value invoice.SalesTermRef = {"value": get_default_terms().Id} orderlineitem_set = list(order.orderlineitem_set.all()) for i, l in enumerate(invoice.Line): try: l.Amount = orderlineitem_set[i].total_charge l.Description = orderlineitem_set[i].product.name item = get_item(orderlineitem_set[i].product) l.SalesItemLineDetail.ItemRef = item.to_ref() l.SalesItemLineDetail.ServiceDate = order.date_paid l.SalesItemLineDetail.Qty = orderlineitem_set[i].qty l.SalesItemLineDetail.UnitPrice = orderlineitem_set[i].charge l.save(qb=client) except IndexError: # the order has been updated to remove a line item l.delete(qb=client) if len(orderlineitem_set) > len( invoice.Line ): # the order has been updated or created to add line items for l in orderlineitem_set[len(invoice.Line):]: line = SalesItemLine() line.Amount = l.total_charge line.Description = l.product.name line.SalesItemLineDetail = SalesItemLineDetail() item = get_item(l.product) line.SalesItemLineDetail.ItemRef = item.to_ref() line.SalesItemLineDetail.ServiceDate = order.date_paid line.SalesItemLineDetail.Qty = l.qty line.SalesItemLineDetail.UnitPrice = l.charge invoice.Line.append(line) invoice.save(qb=client) return invoice
def test_create(self): refund_receipt = RefundReceipt() refund_receipt.DocNumber = "DocNum123" refund_receipt.TotalAmt = 100 refund_receipt.Balance = 100 refund_receipt.PrivateNote = "Private Note" refund_receipt.PaymentType = "Check" memo = CustomerMemo() memo.value = "Customer Memo" refund_receipt.CustomerMemo = memo refund_receipt.CheckPayment = RefundReceiptCheckPayment() refund_receipt.CheckPayment.CheckNum = "1001" refund_receipt.CheckPayment.NameOnAcct = "John Smith" refund_receipt.CheckPayment.AcctNum = "0000000000" refund_receipt.CheckPayment.BankName = "Bank" item = Item.all(max_results=1, qb=self.qb_client)[0] line = DetailLine() line.DetailType = "SalesItemLineDetail" line.Amount = 200 line.SalesItemLineDetail = SalesItemLineDetail() line.SalesItemLineDetail.ItemRef = item.to_ref() refund_receipt.Line.append(line) account = Account.where("Name = 'checking'", max_results=1, qb=self.qb_client)[0] refund_receipt.DepositToAccountRef = account.to_ref() refund_receipt.save(qb=self.qb_client) query_refund_receipt = RefundReceipt.get(refund_receipt.Id, qb=self.qb_client) self.assertEqual(query_refund_receipt.DocNumber, refund_receipt.DocNumber) self.assertEqual(query_refund_receipt.Line[0].Amount, 200) self.assertEqual(refund_receipt.DepositToAccountRef.value, account.Id)
def vendor_unit_fee_line_item(vendor_rate, qty, vendor_fee_item, order_date, qbo_class=None): line = SalesItemLine() line.Amount = (-1) * vendor_rate * qty line.Description = "{} of ${:.2f} x {}".format(vendor_fee_item.Name, abs(vendor_rate), qty) detail = SalesItemLineDetail() detail.ItemRef = vendor_fee_item.to_ref() detail.Qty = qty detail.UnitPrice = line.Amount / qty if qbo_class is not None: detail.ClassRef = qbo_class.to_ref() detail.ServiceDate = order_date.strftime("%Y-%m-%d") line.SalesItemLineDetail = detail return line
def transaction_line_item(total, description, qty, item, service_date, qbo_class=None): line = SalesItemLine() line.Amount = total line.Description = description detail = SalesItemLineDetail() detail.Qty = qty detail.UnitPrice = line.Amount / detail.Qty detail.ItemRef = item.to_ref() if qbo_class is not None: detail.ClassRef = qbo_class.to_ref() if service_date: detail.ServiceDate = service_date.strftime("%Y-%m-%d") line.SalesItemLineDetail = detail return line
def send_to_quickbooks(self, request): # Before we ship to quickbooks, let's save the freshsheet used by this Order self.freshsheet = FreshSheet.objects.latest('published_at') self.save() client = get_qb_client() customer = Ref() # customer.value = 1 customer.value = self.created_by.qb_customer_id # customer.name = self.created_by.req_info.business_name customer.type = 'Customer' line_items = [] for item in self.items.all(): item_lookup = Item.where( f"Name = '{item.item.name}{item.unit_quantity}'", qb=client) if item_lookup: product = item_lookup[0] product.UnitPrice = item.unit_cost product.Type = 'NonInventory' product.IncomeAccountRef = Account.where( "Name = 'Sales'", qb=client)[0].to_ref() product.save(qb=client) else: product = Item() product.Name = f"{item.item.name}{item.unit_quantity}" product.UnitPrice = item.unit_cost product.Type = 'NonInventory' product.IncomeAccountRef = Account.where( "Name = 'Sales'", qb=client)[0].to_ref() product.save(qb=client) line_detail = SalesItemLineDetail() line_detail.ItemRef = product.to_ref() line_detail.UnitPrice = item.unit_cost # in dollars line_detail.Qty = item.quantity # quantity can be decimal # Need to change this date to be the DELIVERY DATE of shipment, # not the date on which it was created # Check if it's between Sunday and Tuesday (Yields Tuesday date().isoformat()) # Check if it's between Wednesday and Friday (Yields Friday date().isoformat()) line_detail.ServiceDate = get_next_service_date().isoformat() line = SalesItemLine() line.Id = '1' line.Amount = item.total_cost # in dollars line.Description = f"{item.quantity} {item.item.get_unit_verbose()} of {product.Name} from " \ f"{item.item.farm}." line.SalesItemLineDetail = line_detail line_items.append(line) invoice = Invoice() invoice.CustomerRef = customer invoice.Line = line_items invoice.save(qb=client) # NOTE: If we try to just save the user model, it _could_ overwrite some Quickbooks auth settings. # By getting a fresh model we'll for sure have the latest settings fresh_user_model = User.objects.get(pk=request.user.pk) fresh_user_model.cart = None fresh_user_model.save()
def create_daily_sales(txdate, daily_reports): refresh_session() pattern = re.compile(r"\d+\.\d\d") store_refs = {x.Name: x.to_ref() for x in Department.all()} existing_receipts = { x.DepartmentRef.name if x.DepartmentRef else "20025": x for x in SalesReceipt.filter(TxnDate=qb_date_format(txdate)) } new_receipts = {} for store, sref in store_refs.items(): if store in existing_receipts: new_receipts[store] = existing_receipts[store] # clear old lines new_receipts[store].Line.clear() else: new_receipts[store] = SalesReceipt() for store, new_receipt in new_receipts.items(): if not (store in daily_reports): continue new_receipts[store].DepartmentRef = store_refs[store] new_receipt.TxnDate = qb_date_format(txdate) new_receipt.CustomerRef = Customer.all()[0].to_ref() daily_report = daily_reports[store] line_num = 1 amount_total = Decimal(0.0) for line_item, line_id in detail_map.items(): daily_report[line_item] line = SalesItemLine() line.LineNum = line_num line.Description = "{} imported from ({})".format( line_item, daily_report[line_item]) if daily_report[line_item]: if daily_report[line_item].startswith("N"): line.Amount = 0 else: line.Amount = atof( daily_report[line_item].strip("$")) * line_id[1] amount_total += Decimal(line.Amount) else: line.Amount = 0 line.SalesItemLineDetail = SalesItemLineDetail() item = Item.query("select * from Item where id = '{}'".format( line_id[0]))[0] line.SalesItemLineDetail.ItemRef = item.to_ref() line.SalesItemLineDetail.ServiceDate = None new_receipt.Line.append(line) line_num += 1 # Payin line = SalesItemLine() line.LineNum = line_num line_num += 1 line.Description = daily_report["Payins"].strip() if line.Description.count("\n") > 0: amount = Decimal(0) for payin_line in line.Description.split("\n")[1:]: if payin_line.startswith("TOTAL"): continue amount = amount + Decimal( atof(pattern.search(payin_line).group())) line.Amount = amount.quantize(TWOPLACES) amount_total += amount else: line.Amount = 0 line.SalesItemLineDetail = SalesItemLineDetail() item = Item.query("select * from Item where id = '{}'".format(43))[0] line.SalesItemLineDetail.ItemRef = item.to_ref() line.SalesItemLineDetail.ServiceDate = None new_receipt.Line.append(line) # Register Audit line = SalesItemLine() line.LineNum = line_num line_num += 1 line.Description = daily_report["Bank Deposits"].strip() # test if there was a recorded deposit if line.Description: line.Amount = Decimal(atof(line.Description.split()[4])) - Decimal( amount_total).quantize(TWOPLACES) else: line.Amount = 0 line.SalesItemLineDetail = SalesItemLineDetail() item = Item.query("select * from Item where id = '{}'".format(31))[0] line.SalesItemLineDetail.ItemRef = item.to_ref() line.SalesItemLineDetail.ServiceDate = None new_receipt.Line.append(line) new_receipt.PrivateNote = json.dumps(daily_report, indent=1) new_receipt.save() return
def create(self, request): # validate estimate data estimate_serializer = EstimateCreateQBOSerializer(data=request.data) estimate_serializer.is_valid(raise_exception=True) estimate_data = estimate_serializer.validated_data # validate estimate lines data estimate_category_items_serializer = EstimateLineCategoryItemsQBOSerializer( data=estimate_data['category_items'], many=True) estimate_category_items_serializer.is_valid(raise_exception=True) categories_items = estimate_category_items_serializer.validated_data # # create estimate # estimate = Estimate() estimate.TxnStatus = estimate_data['status'] estimate.CustomerRef = { "value": estimate_data['customer_id'], } estimate.BillEmail = EmailAddress() estimate.BillEmail.Address = estimate_data['email'] estimate.PrivateNote = estimate_data['private_notes'][: 4000] # 4000 max estimate.CustomerMemo = { "value": estimate_data['public_notes'][:1000], # 1000 max } estimate.ExpirationDate = estimate_data['expiration_date'].isoformat() # populate DocNumber by incrementing from the most recent estimate recent_estimates = [ e for e in Estimate.filter(order_by='Id DESC', qb=self.qbo_client) if e.DocNumber ] if recent_estimates: # remove non-digits last_doc_number = re.sub(r'[^0-9]', '', recent_estimates[0].DocNumber) try: last_doc_number = int(last_doc_number) except ValueError as e: logging.exception(e) logging.error('Could not auto increment DocNumber: {}'.format( last_doc_number)) else: # increment estimate.DocNumber = last_doc_number + 1 # keep track in case there's a discount applied inventory_sub_total = .0 # build lines for category_items in categories_items: # append items for category for item in category_items['items']: sales_line = SalesItemLine() sales_line.Amount = item['amount'] sales_line.Description = item['description'] sales_line.SalesItemLineDetail = SalesItemLineDetail() sales_line.SalesItemLineDetail.Qty = item['quantity'] sales_line.SalesItemLineDetail.ItemRef = Ref() sales_line.SalesItemLineDetail.ItemRef.name = item['name'] sales_line.SalesItemLineDetail.ItemRef.value = item['id'] sales_line.SalesItemLineDetail.UnitPrice = item['price'] sales_line.SalesItemLineDetail.TaxCodeRef = Ref() if item['type'] == EstimateLineQBOSerializer.LINE_TYPE_INVENTORY: sales_line.SalesItemLineDetail.TaxCodeRef.value = 'TAX' inventory_sub_total += item['amount'] else: sales_line.SalesItemLineDetail.TaxCodeRef.value = 'NON' estimate.Line.append(sales_line) # add subtotal for category subtotal_line = DescriptionLine() subtotal_line.Description = "Subtotal: {}".format( sum(item['amount'] for item in category_items['items'])) estimate.Line.append(subtotal_line) # discount if estimate_data['discount_percent']: discount_line = DiscountLine() discount_line.DiscountLineDetail = DiscountLineDetail() # applied to whole estimate if estimate_data['discount_applied_to_all']: discount_line.DiscountLineDetail.PercentBased = True discount_line.DiscountLineDetail.DiscountPercent = estimate_data[ 'discount_percent'] # applied only to inventory items else: discount_line.Amount = inventory_sub_total * estimate_data[ 'discount_percent'] / 100 estimate.Line.append(discount_line) # add tax tax_code = get_qbo_tax_code_rate(TaxCode, qbo_client=self.qbo_client) estimate.TxnTaxDetail = TxnTaxDetail() estimate.TxnTaxDetail.TxnTaxCodeRef = { 'name': tax_code['Name'], 'value': tax_code['Id'], } # query preferences so we can get the custom field ids cached_preferences = cache.get('preferences') if cached_preferences: logging.info('using cached preferences') preferences = cached_preferences else: logging.info('querying preferences and caching') preferences = Preferences.filter(qb=self.qbo_client)[0].to_dict() cache.set('preferences', preferences, None) # set custom fields custom_fields = { 'Bike/Model': estimate_data['bike_model'], 'Tag #': estimate_data['tag_number'], 'Expiration Time': estimate_data['expiration_time'].strftime( '%I:%M %p'), # i.e 04:14 PM } for name, value in custom_fields.items(): estimate.CustomField.append({ "DefinitionId": get_custom_field_index_from_preferences(name, preferences), "Type": "StringType", "Name": name, "StringValue": value, }) estimate.save(qb=self.qbo_client) # save signature (data uri) to temporary file so we can upload and attach it to the estimate with tempfile.NamedTemporaryFile() as fh: # save to image header, encoded = estimate_data['signature'].split(",", 1) data = b64decode(encoded) fh.write(data) # create attachment attachment = Attachable() attachable_ref = AttachableRef() attachable_ref.IncludeOnSend = True attachable_ref.EntityRef = { "type": 'Estimate', "value": estimate.Id, } attachment.AttachableRef.append(attachable_ref) attachment.FileName = 'signature.jpg' attachment._FilePath = fh.name attachment.ContentType = 'image/jpg' attachment.save(qb=self.qbo_client) return Response(estimate.to_dict())