Git Product home page Git Product logo

doublecount's Introduction

Doublecount crates.io badge license badge docs.rs badge

A double entry accounting system/library for Rust.

This project is very much inspired by beancount, however it currently presents a much simpler model. It has been designed to embed within other applications for the purpose of running accounting calculations.

Commodities within the system are represented using the primitives provided by the commodity library, which is in turn backed by rust_decimal.

This library is under active development, however it should already be usable for some simple purposes. There's likely to be some API changes in the future to allow transactions/actions to be streamed into the system, and also to support parallel computations of transactions to allow large programs to efficiently executed on multi-core computers.

Changelog

Optional Features

The following features can be enabled to provide extra functionality:

  • serde-support
    • Enables support for serialization/de-serialization via serde

Usage

use doublecount::{
    AccountStatus, EditAccountStatus, Account, Program, Action,
    ProgramState, Transaction, TransactionElement, BalanceAssertion,
    ActionTypeValue,
};
use commodity::{CommodityType, Commodity};
use chrono::NaiveDate;
use std::rc::Rc;
use std::str::FromStr;

// create a commodity from a currency's iso4317 alphanumeric code
let aud = Rc::from(CommodityType::from_currency_alpha3("AUD").unwrap());

// Create a couple of accounts
let account1 = Rc::from(Account::new_with_id(Some("Account 1"), aud.id, None));
let account2 = Rc::from(Account::new_with_id(Some("Account 2"), aud.id, None));

// create a new program state, with accounts starting Closed
let mut program_state = ProgramState::new(
    &vec![account1.clone(), account2.clone()],
    AccountStatus::Closed
);

// open account1
let open_account1 = EditAccountStatus::new(
    account1.id,
    AccountStatus::Open,
    NaiveDate::from_str("2020-01-01").unwrap(),
);

// open account2
let open_account2 = EditAccountStatus::new(
    account2.id,
    AccountStatus::Open,
    NaiveDate::from_str("2020-01-01").unwrap(),
);

// create a transaction to transfer some commodity
// from account1 to account2.
let transaction1 = Transaction::new(
    Some(String::from("Transaction 1")),
    NaiveDate::from_str("2020-01-02").unwrap(),
    vec![
        TransactionElement::new(
            account1.id,
            Some(Commodity::from_str("-2.52 AUD").unwrap()),
            None,
        ),
        TransactionElement::new(
            account2.id,
            Some(Commodity::from_str("2.52 AUD").unwrap()),
            None,
        ),
    ],
);

// create a balance assertion (that will cause the program to return an error
// if it fails), to check that the balance of account1 matches the expected
// value of -1.52 AUD at the start of the date of 2020-01-03
let balance_assertion1 = BalanceAssertion::new(
    account1.id,
    NaiveDate::from_str("2020-01-03").unwrap(),
    Commodity::from_str("-2.52 AUD").unwrap()
);

// create another transaction to transfer commodity from
// account2 to account1, using the simpler syntax.
let transaction2 =  Transaction::new_simple(
   Some("Transaction 2"),
   NaiveDate::from_str("2020-01-03").unwrap(),
   account2.id,
   account1.id,
   Commodity::from_str("1.0 AUD").unwrap(),
   None,
);

let balance_assertion2 = BalanceAssertion::new(
    account1.id,
    NaiveDate::from_str("2020-01-04").unwrap(),
    Commodity::from_str("-1.52 AUD").unwrap()
);

let balance_assertion3 = BalanceAssertion::new(
    account2.id,
    NaiveDate::from_str("2020-01-04").unwrap(),
    Commodity::from_str("1.52 AUD").unwrap()
);

let actions: Vec<Rc<ActionTypeValue>> = vec![
    Rc::new(open_account1.into()),
    Rc::new(open_account2.into()),
    Rc::new(transaction1.into()),
    Rc::new(balance_assertion1.into()),
    Rc::new(transaction2.into()),
    Rc::new(balance_assertion2.into()),
    Rc::new(balance_assertion3.into()),
];

// create a program from the actions
let program = Program::new(actions);

// run the program
program_state.execute_program(&program).unwrap();

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.