diff --git a/go.mod b/go.mod index 79d3cac..1610e62 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/yosuke-furukawa/json5 v0.1.1 // indirect golang.org/x/net v0.8.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9b2e182..8e5e0cc 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/pkg/delo_lib/delo_lib.go b/pkg/delo_lib/delo_lib.go new file mode 100644 index 0000000..09b61ec --- /dev/null +++ b/pkg/delo_lib/delo_lib.go @@ -0,0 +1,39 @@ +package delo_lib + +import ( + "errors" + "strconv" + "strings" +) + +func ДатувКвартал(in string) (int, error) { + parts := strings.Split(in, ".") + if len(parts) < 3 { + return 0, errors.New("формат даты") + } + месяц, err := strconv.ParseInt(parts[1], 10, 64) + if err != nil { + return 0, err + } + квартал, err := МесяцвКвартал(месяц) + if err != nil { + return 0, err + } + return квартал, nil +} + +func МесяцвКвартал(in int64) (int, error) { + if in < 1 || in > 12 { + return 0, errors.New("неправильный месяц") + } + + switch in { + case 1, 2, 3: + return 1, nil + case 4, 5, 6: + return 2, nil + case 7, 8, 9: + return 3, nil + } + return 4, nil +} diff --git a/pkg/input/txt/features/app.feature b/pkg/input/txt/features/app.feature new file mode 100644 index 0000000..3314c71 --- /dev/null +++ b/pkg/input/txt/features/app.feature @@ -0,0 +1,3 @@ +# Во имя Бога Милостивого, Милосердного!!! +# language: ru +Функциональность: Конфиг Txt diff --git a/pkg/input/txt/init_test.go b/pkg/input/txt/init_test.go new file mode 100644 index 0000000..be00131 --- /dev/null +++ b/pkg/input/txt/init_test.go @@ -0,0 +1,51 @@ +package txt + +import ( + "context" + "os" + "testing" + + . "my/schet/pkg/testlib" + + "github.com/cucumber/godog" + "github.com/cucumber/godog/colors" + + . "github.com/onsi/gomega" +) + +func InitializeScenario(ctx *godog.ScenarioContext) { + + // ----------------------- + ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) { + beforeScenario() + return ctx, nil + }) + ctx.After(func(ctx context.Context, sc *godog.Scenario, err error) (context.Context, error) { + afterScenario() + return ctx, nil + }) + InitializeGomegaForGodog(ctx) + _ = Ω +} + +func InitializeSuite(tsc *godog.TestSuiteContext) { + tsc.BeforeSuite(beforeSuite) + tsc.AfterSuite(afterSuite) +} + +func TestMain(t *testing.T) { + var opts = godog.Options{ + Output: colors.Colored(os.Stdout), + Strict: true, + StopOnFailure: true, + TestingT: t, + } + + godog.BindCommandLineFlags("godog.", &opts) + godog.TestSuite{ + Name: "app", + TestSuiteInitializer: InitializeSuite, + ScenarioInitializer: InitializeScenario, + Options: &opts, + }.Run() +} diff --git a/pkg/input/txt/stroka.go b/pkg/input/txt/stroka.go new file mode 100644 index 0000000..58ea25d --- /dev/null +++ b/pkg/input/txt/stroka.go @@ -0,0 +1,48 @@ +package txt + +import ( + "my/schet/pkg/delo_lib" + "my/schet/pkg/input/config" + "my/schet/pkg/schet" + "strconv" +) + +type СтрокаДокумента struct { + год *schet.Год + parts []string + дляДохода *config.Доход +} + +func NewСтрокаДокумента(год *schet.Год, parts []string, дляДохода *config.Доход) *СтрокаДокумента { + c := &СтрокаДокумента{ + год: год, + parts: parts, + дляДохода: дляДохода, + } + return c +} + +func (c *СтрокаДокумента) Заполнить() error { + switch c.parts[0] { + case "Сумма": + сумма, err := strconv.ParseFloat(c.parts[1], 64) + if err != nil { + return err + } + c.дляДохода.Сумма = сумма + case "Дата": + квартал, err := delo_lib.ДатувКвартал(c.parts[1]) + if err != nil { + return err + } + c.дляДохода.Квартал = квартал + case "ПолучательСчет": + if c.parts[1] != c.год.Счёт() { + return ErrНеподходящийДокумент + } + case "Плательщик1": + c.дляДохода.Клиент = c.parts[1] + } + + return nil +} diff --git a/pkg/input/txt/txt.go b/pkg/input/txt/txt.go new file mode 100644 index 0000000..aa40fed --- /dev/null +++ b/pkg/input/txt/txt.go @@ -0,0 +1,108 @@ +package txt + +import ( + "bufio" + "errors" + "io" + "my/schet/pkg/input/config" + "my/schet/pkg/schet" + "os" + "strings" + + "golang.org/x/text/encoding/charmap" + "golang.org/x/text/transform" +) + +var ( + ErrНеподходящийДокумент = errors.New("неподходящий документ") +) + +type TXT struct { + path string + config *config.Config + год *schet.Год + дляДохода *config.Доход +} + +func NewTXT(path string) *TXT { + c := &TXT{ + config: config.NewConfig(), + path: path, + } + return c +} + +func (c *TXT) СчитатьиЗагрузитьвГод(год *schet.Год) error { + c.год = год + + f, err := os.Open(c.path) + if err != nil { + return err + } + defer f.Close() + + fenc := transform.NewReader(f, charmap.Windows1251.NewDecoder()) + + return c.парсить(fenc) +} + +func (c *TXT) парсить(f io.Reader) error { + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + err := c.обработатьСтрокуФайла(line) + if err != nil { + return err + } + } + + return scanner.Err() +} + +func (c *TXT) обработатьСтрокуФайла(l string) error { + parts := strings.Split(l, "=") + if len(parts) < 2 { + return c.отправитьмиУдалитьПеременнуюДляДохода(l) + } + return c.создатьиЗаполнитьСтруктуруДляДохода(parts) +} + +func (c *TXT) отправитьмиУдалитьПеременнуюДляДохода(l string) error { + if !конецДокумента(l) { + return nil + } + if c.дляДохода == nil { + return nil + } + + err := c.год.ДобавитьДоход(c.дляДохода.Сумма, c.дляДохода.Квартал) + c.дляДохода = nil + + return err +} + +func (c *TXT) создатьиЗаполнитьСтруктуруДляДохода(parts []string) error { + if началоДокумента(parts) { + c.дляДохода = &config.Доход{} + return nil + } + + if c.дляДохода == nil { + return nil + } + + sd := NewСтрокаДокумента(c.год, parts, c.дляДохода) + err := sd.Заполнить() + if errors.Is(err, ErrНеподходящийДокумент) { + c.дляДохода = nil + return nil + } + return err +} + +func началоДокумента(parts []string) bool { + return parts[0] == "СекцияДокумент" && parts[1] == "Платежное поручение" +} +func конецДокумента(l string) bool { + return l == "КонецДокумента" +} diff --git a/pkg/input/txt/txt_test.go b/pkg/input/txt/txt_test.go new file mode 100644 index 0000000..59bb85d --- /dev/null +++ b/pkg/input/txt/txt_test.go @@ -0,0 +1,31 @@ +package txt + +import ( + . "github.com/onsi/gomega" +) + +type testData struct { +} + +var ( + t *testData +) + +func resetTestData() { + t = &testData{} +} + +func beforeSuite() { +} +func afterSuite() { +} + +func beforeScenario() { + resetTestData() + _ = Ω + +} +func afterScenario() { +} + +// -----------------------