Пример #1
0
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
Пример #2
0
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
Пример #3
0
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)
Пример #4
0
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
Пример #5
0
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)
Пример #7
0
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
Пример #8
0
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
Пример #9
0
    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()
Пример #10
0
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
Пример #11
0
    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())