Esempio n. 1
0
def new_bill_protocol(bill_model: BillModel,
                      entity_slug: str or EntityModel,
                      user_model: UserModel,
                      bill_desc: str = None) -> Tuple[LedgerModel, BillModel]:
    if isinstance(entity_slug, str):
        entity_qs = EntityModel.objects.for_user(user_model=user_model)
        entity_model: EntityModel = get_object_or_404(entity_qs,
                                                      slug__exact=entity_slug)
    elif isinstance(entity_slug, EntityModel):
        entity_model = entity_slug
    else:
        raise ValidationError(
            'entity_slug must be an instance of str or EntityModel')

    bill_model.bill_number = generate_bill_number()
    ledger_name = f'Bill {bill_model.bill_number}'
    if bill_desc:
        ledger_name += f' | {bill_desc}'
    ledger_model: LedgerModel = LedgerModel.objects.create(
        entity=entity_model,
        posted=True,
        name=ledger_name,
    )
    ledger_model.clean()
    bill_model.ledger = ledger_model
    return ledger_model, bill_model
Esempio n. 2
0
def new_bill_protocol(bill_model: BillModel,
                      entity_slug: str or EntityModel,
                      user_model: UserModel,
                      unit_slug: str = None) -> BillModel:
    if isinstance(entity_slug, str):
        entity_qs = EntityModel.objects.for_user(
            user_model=user_model)
        entity_model: EntityModel = get_object_or_404(entity_qs, slug__exact=entity_slug)
    elif isinstance(entity_slug, EntityModel):
        entity_model = entity_slug
    else:
        raise ValidationError('entity_slug must be an instance of str or EntityModel')

    if unit_slug:
        unit_model_qs = entity_model.entityunitmodel_set.all()
        unit_model = get_object_or_404(unit_model_qs, slug__exact=unit_slug)
    else:
        unit_model = None

    bill_model.bill_number = generate_bill_number()
    ledger_model = LedgerModel.objects.create(
        entity=entity_model,
        posted=True,
        name=f'Bill {bill_model.bill_number}',
        unit=unit_model
    )
    ledger_model.clean()
    bill_model.ledger = ledger_model
    return bill_model
Esempio n. 3
0
def generate_random_bill(
        entity_model: EntityModel,
        unit_models: list,
        user_model,
        vendor_models: list,
        expense_models: list,
        is_accruable: bool,
        progress: float,
        accounts_by_role: dict,
        issue_dt: date,
        is_paid: bool,
        paid_dt: date):
    bill_model: BillModel = BillModel(
        vendor=choice(vendor_models),
        accrue=is_accruable,
        progress=progress,
        terms=choice(BillModel.TERMS)[0],
        bill_number=generate_bill_number(),
        amount_due=0,
        cash_account=choice(accounts_by_role['asset_ca_cash']),
        prepaid_account=choice(accounts_by_role['asset_ca_recv']),
        unearned_account=choice(accounts_by_role['lia_cl_acc_pay']),
        date=issue_dt,
        paid=is_paid,
        paid_date=paid_dt
    )

    ledger_model, bill_model = new_bill_protocol(
        bill_model=bill_model,
        entity_slug=entity_model,
        user_model=user_model)

    bill_items = [
        BillModelItemsThroughModel(
            bill_model=bill_model,
            item_model=choice(expense_models),
            quantity=round(random() * randint(1, 5), 2),
            unit_cost=round(random() * randint(100, 800), 2),
            entity_unit=choice(unit_models) if random() > .75 else None
        ) for _ in range(randint(1, 10))
    ]

    for bi in bill_items:
        bi.clean()

    bill_model.update_amount_due(item_list=bill_items)
    bill_model.amount_paid = Decimal.from_float(round(random() * float(bill_model.amount_due), 2))
    bill_model.new_state(commit=True)
    bill_model.clean()
    bill_model.save()
    bill_items = bill_model.billmodelitemsthroughmodel_set.bulk_create(bill_items)
    bill_model.migrate_state(
        user_model=user_model,
        item_models=bill_items,
        entity_slug=entity_model.slug,
        je_date=issue_dt)

    if is_paid:
        ledger_model.locked = True
        ledger_model.save(update_fields=['locked'])
Esempio n. 4
0
def generate_random_bill(
        entity_model: EntityModel,
        user_model,
        vendor_models: list,
        expense_models: list,
        is_progressible: bool,
        progress: float,
        accounts_by_role: dict,
        issue_dt: date,
        is_paid: bool,
        paid_dt: date):
    bill_model = BillModel(
        vendor=choice(vendor_models),
        progressible=is_progressible,
        progress=progress,
        terms=choice(BillModel.TERMS)[0],
        bill_number=generate_bill_number(),
        amount_due=0,
        cash_account=choice(accounts_by_role['asset_ca_cash']),
        receivable_account=choice(accounts_by_role['asset_ca_recv']),
        payable_account=choice(accounts_by_role['lia_cl_acc_pay']),
        earnings_account=choice(accounts_by_role['ex_op']),
        date=issue_dt,
        paid=is_paid,
        paid_date=paid_dt
    )

    bill_model = new_bill_protocol(
        bill_model=bill_model,
        entity_slug=entity_model,
        user_model=user_model)

    bill_model.clean()
    bill_model.save()

    bill_items = [
        BillModelItemsThroughModel(
            bill_model=bill_model,
            item_model=choice(expense_models),
            quantity=round(random() * randint(1, 5), 2),
            unit_cost=round(random() * randint(100, 800), 2)
        ) for _ in range(randint(1, 10))
    ]

    for ii in bill_items:
        ii.clean()

    bill_model.billmodelitemsthroughmodel_set.bulk_create(bill_items)
    bill_model.update_amount_due()
    bill_model.amount_paid = Decimal(round(random() * float(bill_model.amount_due), 2))
    bill_model.new_state(commit=True)
    bill_model.clean()
    bill_model.save()
    bill_model.migrate_state(
        user_model=user_model,
        entity_slug=entity_model.slug,
        je_date=paid_dt)
Esempio n. 5
0
def new_bill_protocol(bill_model: BillModel, entity_slug: str or EntityModel, user_model: UserModel) -> BillModel:
    if isinstance(entity_slug, str):
        entity_model = EntityModel.objects.for_user(
            user_model=user_model).get(
            slug__exact=entity_slug)
    elif isinstance(entity_slug, EntityModel):
        entity_model = entity_slug
    else:
        raise ValidationError('entity_slug must be an instance of str or EntityModel')

    bill_model.bill_number = generate_bill_number()
    ledger_model = LedgerModel.objects.create(
        entity=entity_model,
        posted=True,
        name=f'Bill {bill_model.bill_number}'
    )
    ledger_model.clean()
    bill_model.ledger = ledger_model
    return bill_model
Esempio n. 6
0
def generate_sample_data(entity: str or EntityModel,
                         user_model,
                         start_dt: datetime,
                         days_fw: int,
                         cap_contribution: float or int = 20000,
                         income_tx_avg: float or int = 2000,
                         expense_tx_avg: float or int = 1000,
                         tx_quantity: int = 100,
                         is_progressible_probability: float = 0.2,
                         is_paid_probability: float = 0.97):
    """
    TXS = List[{
            'account_id': Account Database UUID
            'tx_type': credit/debit,
            'amount': Decimal/Float/Integer,
            'description': string,
            'staged_tx_model': StagedTransactionModel or None
        }]
    :param is_paid_probability:
    :param is_progressible_probability:
    :param tx_quantity:
    :param expense_tx_avg:
    :param income_tx_avg:
    :param cap_contribution:
    :param days_fw:
    :param start_dt:
    :param user_model:
    :param entity:
    :return:
    """

    try:
        from faker import Faker
        from faker.providers import company, address, phone_number
        global FAKER_IMPORTED
        FAKER_IMPORTED = True

        fk = Faker()
        fk.add_provider(company)
        fk.add_provider(address)
        fk.add_provider(phone_number)

    except ImportError:
        return False

    if not isinstance(entity, EntityModel):
        entity = EntityModel.objects.get(slug__exact=entity)

    entity.ledgers.all().delete()
    entity.customers.all().delete()
    entity.vendors.all().delete()

    vendor_count = randint(40, 60)
    vendor_models = [
        VendorModel(vendor_name=fk.name() if random() > .7 else fk.company(),
                    entity=entity,
                    address_1=fk.street_address(),
                    address_2=f'{fk.city()}. {fk.postcode()}',
                    phone=fk.phone_number(),
                    email=fk.email(),
                    website=fk.url(),
                    active=True,
                    hidden=False) for _ in range(vendor_count)
    ]

    for vendor in vendor_models:
        vendor.clean()

    vendor_models = VendorModel.objects.bulk_create(vendor_models)

    customer_count = randint(40, 60)
    customer_models = [
        CustomerModel(
            customer_name=fk.name() if random() > .2 else fk.company(),
            entity=entity,
            address_1=fk.street_address(),
            address_2=f'{fk.city()}. {fk.postcode()}',
            phone=fk.phone_number(),
            email=fk.email(),
            website=fk.url(),
            active=True,
            hidden=False) for _ in range(customer_count)
    ]

    for customer in customer_models:
        customer.clean()

    customer_models = CustomerModel.objects.bulk_create(customer_models)

    # todo: create bank account models...

    ledger, created = entity.ledgers.get_or_create(
        name='Business Funding Ledger', posted=True)

    accounts = AccountModel.on_coa.for_entity_available(
        entity_slug=entity.slug, user_model=user_model).order_by('role')

    accounts_gb = {
        g: list(v)
        for g, v in groupby(accounts, key=lambda a: a.role)
    }

    capital_acc = choice(accounts_gb['eq_capital'])
    cash_acc = choice(accounts_gb['asset_ca_cash'])

    txs = list()

    txs.append({
        'account_id': cash_acc.uuid,
        'tx_type': 'debit',
        'amount': cap_contribution,
        'description': f'Sample data for {entity.name}'
    })
    txs.append({
        'account_id': capital_acc.uuid,
        'tx_type': 'credit',
        'amount': cap_contribution,
        'description': f'Sample data for {entity.name}'
    })

    entity.commit_txs(je_date=start_dt,
                      je_txs=txs,
                      je_activity='op',
                      je_posted=True,
                      je_ledger=ledger)

    loc_time = localtime()
    rng = tx_quantity
    for i in range(rng):

        issue_dttm = start_dt + timedelta(days=randint(0, days_fw))
        if issue_dttm > loc_time:
            issue_dttm = loc_time

        is_progressible = random() < is_progressible_probability
        progress = Decimal(round(random(), 2)) if is_progressible else 0

        is_paid = random() < is_paid_probability
        paid_dttm = issue_dttm + timedelta(
            days=randint(0, 60)) if is_paid else None
        if paid_dttm and paid_dttm >= loc_time:
            paid_dttm = None
            is_paid = False

        issue_dt = issue_dttm.date()
        paid_dt = paid_dttm.date() if paid_dttm else None
        switch_amt = random() > 0.75

        if i % 2 == 0:

            amt = expense_tx_avg if not switch_amt else income_tx_avg
            bill_amt = Decimal(round(random() * amt, 2))
            bill_amt_paid = Decimal(round(Decimal(random()) * bill_amt, 2))

            bill = BillModel(
                vendor=choice(vendor_models),
                progressible=is_progressible,
                progress=progress,
                terms=choice(BillModel.TERMS)[0],
                xref=generate_bill_number(length=15, prefix=False),
                cash_account=choice(accounts_gb['asset_ca_cash']),
                receivable_account=choice(accounts_gb['asset_ca_recv']),
                payable_account=choice(accounts_gb['lia_cl_acc_pay']),
                earnings_account=choice(accounts_gb['ex_op']),
                amount_due=bill_amt,
                amount_paid=bill_amt_paid,
                date=issue_dt,
                paid=is_paid,
                paid_date=paid_dt)

            bill = new_bill_protocol(bill_model=bill,
                                     entity_slug=entity.slug,
                                     user_model=user_model)
            bill.clean()
            bill.migrate_state(user_model=user_model,
                               entity_slug=entity.slug,
                               je_date=paid_dt)
            bill.save()

        else:

            amt = income_tx_avg if not switch_amt else expense_tx_avg
            inv_amt = Decimal(round(random() * amt, 2))
            inv_amt_paid = Decimal(round(Decimal(random()) * inv_amt, 2))

            invoice = InvoiceModel(
                customer=choice(customer_models),
                progressible=is_progressible,
                progress=progress,
                terms=choice(InvoiceModel.TERMS)[0],
                invoice_number=generate_invoice_number(),
                cash_account=choice(accounts_gb['asset_ca_cash']),
                receivable_account=choice(accounts_gb['asset_ca_recv']),
                payable_account=choice(accounts_gb['lia_cl_acc_pay']),
                earnings_account=choice(accounts_gb['in_sales']),
                amount_due=inv_amt,
                amount_paid=inv_amt_paid,
                date=issue_dt,
                paid=is_paid,
                paid_date=paid_dt)

            invoice = new_invoice_protocol(invoice_model=invoice,
                                           entity_slug=entity.slug,
                                           user_model=user_model)

            invoice.clean()
            invoice.migrate_state(user_model=user_model,
                                  entity_slug=entity.slug,
                                  je_date=paid_dt)
            invoice.save()