Przeglądaj źródła

Initial commit

Signed-off-by: Slava Barinov <rayslava@gmail.com>
Slava Barinov 5 lat temu
commit
e7761cac1d
9 zmienionych plików z 599 dodań i 0 usunięć
  1. 43 0
      .github/workflows/rust.yml
  2. 1 0
      .gitignore
  3. 87 0
      Cargo.lock
  4. 11 0
      Cargo.toml
  5. 21 0
      LICENSE
  6. 3 0
      README.md
  7. 35 0
      src/main.rs
  8. 147 0
      src/receipt.rs
  9. 251 0
      tests/resources/test.json

+ 43 - 0
.github/workflows/rust.yml

@@ -0,0 +1,43 @@
+on: push
+
+name: CI Build
+
+jobs:
+  ci:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        rust:
+          - stable
+          - beta
+          - nightly
+
+    steps:
+      - uses: actions/checkout@v1
+
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: ${{ matrix.rust }}
+          override: true
+          components: rustfmt, clippy
+
+      - uses: actions-rs/cargo@v1
+        with:
+          command: build
+          args: --release
+
+      - uses: actions-rs/cargo@v1
+        with:
+          command: test
+          args: --release
+
+      - uses: actions-rs/cargo@v1
+        with:
+          command: fmt
+          args: --all -- --check
+
+      - uses: actions-rs/cargo@v1
+        with:
+          command: clippy
+          args: -- -D warnings

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/target

+ 87 - 0
Cargo.lock

@@ -0,0 +1,87 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "itoa"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "receqif"
+version = "0.1.0"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+
+[[package]]
+name = "serde"
+version = "1.0.118"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.118"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"

+ 11 - 0
Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "receqif"
+version = "0.1.0"
+authors = ["Slava Barinov <rayslava@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2021 Slava Barinov <rayslava@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# receqif
+
+Receipt to QIF coverter in rust.

+ 35 - 0
src/main.rs

@@ -0,0 +1,35 @@
+use std::env;
+use std::fs;
+
+mod receipt;
+
+fn read_receipt(f: &str) -> Vec<receipt::Item> {
+    let json = fs::read_to_string(f).expect("Can't read file");
+    receipt::parse_receipt(&json)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::path::PathBuf;
+
+    #[test]
+    fn test_read_receipt() {
+        let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+        p.push("tests/resources/test.json");
+        let full_path = p.to_string_lossy();
+
+        let result = read_receipt(&full_path);
+        assert_eq!(result[0].name, "ХРЕН РУССКИЙ 170Г");
+        assert_eq!(result[0].sum, 5549);
+    }
+}
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    let filename = &args[1];
+    let items = read_receipt(filename);
+    for i in items.iter() {
+        println!("{}", i.to_string());
+    }
+}

+ 147 - 0
src/receipt.rs

@@ -0,0 +1,147 @@
+use serde::Deserialize;
+use std::fmt;
+
+#[derive(Deserialize)]
+pub struct Item {
+    pub name: String,
+    pub sum: i64,
+}
+
+impl fmt::Display for Item {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}:{}", self.name, self.sum)
+    }
+}
+
+#[allow(dead_code)]
+#[allow(non_snake_case)]
+#[derive(Deserialize)]
+struct Receipt {
+    totalSum: i64,
+    items: Vec<Item>,
+}
+
+#[allow(dead_code)]
+#[derive(Deserialize)]
+struct Document {
+    receipt: Receipt,
+}
+
+#[allow(dead_code)]
+#[derive(Deserialize)]
+struct Input {
+    document: Document,
+}
+
+pub fn parse_receipt(line: &str) -> Vec<Item> {
+    let result: Input = serde_json::from_str(&line).unwrap();
+    result.document.receipt.items
+}
+
+#[cfg(test)]
+mod receipt {
+    use super::*;
+
+    #[test]
+    fn item() {
+        let line = String::from(
+            r#"
+{
+    "quantity" : 1,
+    "ndsRate" : 1,
+    "price" : 5549,
+    "calculationSubjectSign" : 1,
+    "calculationTypeSign" : 4,
+    "name" : "ХРЕН РУССКИЙ 170Г",
+    "sum" : 5549
+}
+"#,
+        );
+
+        let testit: Item = serde_json::from_str(&line).unwrap();
+        assert_eq!(testit.name, "ХРЕН РУССКИЙ 170Г");
+        assert_eq!(testit.sum, 5549);
+    }
+
+    #[test]
+    fn receipt() {
+        let line = String::from(
+            r#"
+{
+    "totalSum" : 548702,
+    "userInn" : "7703270067",
+    "operator" : "Теpминал 24",
+    "items" : [
+        {
+	    "quantity" : 1,
+	    "ndsRate" : 1,
+	    "price" : 5549,
+	    "calculationSubjectSign" : 1,
+	    "calculationTypeSign" : 4,
+	    "name" : "ХРЕН РУССКИЙ 170Г",
+	    "sum" : 5549
+        },
+        {
+	    "quantity" : 1,
+	    "ndsRate" : 1,
+	    "price" : 20599,
+	    "calculationSubjectSign" : 1,
+	    "calculationTypeSign" : 4,
+	    "name" : "СОУС ОСТР.380Г КИНТО",
+	    "sum" : 20599
+        }
+    ]
+}
+"#,
+        );
+
+        let testit: Receipt = serde_json::from_str(&line).unwrap();
+        assert_eq!(testit.totalSum, 548702);
+        assert_eq!(testit.items.len(), 2);
+        assert_eq!(testit.items[0].sum, 5549);
+        assert_eq!(testit.items[1].sum, 20599);
+    }
+
+    #[test]
+    fn input() {
+        let line = String::from(
+            r#"
+{
+  "document" : {
+    "receipt" : {
+      "totalSum" : 548702,
+      "userInn" : "7703270067",
+      "operator" : "Теpминал 24",
+      "items" : [
+        {
+          "quantity" : 1,
+          "ndsRate" : 1,
+          "price" : 5549,
+          "calculationSubjectSign" : 1,
+          "calculationTypeSign" : 4,
+          "name" : "ХРЕН РУССКИЙ 170Г",
+          "sum" : 5549
+        },
+        {
+          "quantity" : 1,
+          "ndsRate" : 1,
+          "price" : 20599,
+          "calculationSubjectSign" : 1,
+          "calculationTypeSign" : 4,
+          "name" : "СОУС ОСТР.380Г КИНТО",
+          "sum" : 20599
+        }
+      ]
+    }
+  }
+}
+"#,
+        );
+
+        let testit: Input = serde_json::from_str(&line).unwrap();
+        assert_eq!(testit.document.receipt.totalSum, 548702);
+        assert_eq!(testit.document.receipt.items.len(), 2);
+        assert_eq!(testit.document.receipt.items[0].sum, 5549);
+        assert_eq!(testit.document.receipt.items[1].sum, 20599);
+    }
+}

Plik diff jest za duży
+ 251 - 0
tests/resources/test.json


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików