Начало: модуль счёта добавлен
Этот коммит содержится в:
коммит
5ea7f5d13c
11 изменённых файлов: 488 добавлений и 0 удалений
30
pkg/schet/celi.go
Обычный файл
30
pkg/schet/celi.go
Обычный файл
|
@ -0,0 +1,30 @@
|
|||
package schet
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Цели struct {
|
||||
год *Год
|
||||
Кварталы []*Квартал
|
||||
}
|
||||
|
||||
func NewЦели(год *Год) *Цели {
|
||||
c := &Цели{
|
||||
год: год,
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Цели) Квартал(in int) (k *Квартал, e error) {
|
||||
e = errors.New("неизвестный квартал")
|
||||
|
||||
if in < НомерПервогоКвартала || in > НомерПоследнегоКвартала {
|
||||
return
|
||||
}
|
||||
|
||||
index := in - 1
|
||||
k = c.Кварталы[index]
|
||||
e = nil
|
||||
return
|
||||
}
|
82
pkg/schet/features/app.feature
Обычный файл
82
pkg/schet/features/app.feature
Обычный файл
|
@ -0,0 +1,82 @@
|
|||
# Во имя Бога Милостивого, Милосердного!!!
|
||||
# language: ru
|
||||
Функциональность: Счёт
|
||||
|
||||
Сценарий: Платёж по ОПС в квартале
|
||||
Дано Год: 2024
|
||||
Дано Квартал: <квартал>
|
||||
Когда Расчитать год
|
||||
То Есть цель: ОПС за этот квартал: 12375
|
||||
|
||||
Примеры:
|
||||
| квартал |
|
||||
| 1 |
|
||||
| 2 |
|
||||
| 3 |
|
||||
| 4 |
|
||||
|
||||
Сценарий: Платёж 1% сверх 300тр: в год и за 1-ый квартал
|
||||
Дано Год: 2024
|
||||
Дано Квартал: 1
|
||||
Дано Доход: <доход>
|
||||
Когда Расчитать год
|
||||
То Есть цель: 1% сверх 300тр за квартал: "<оплатить_за_квартал>"
|
||||
То Есть цель: 1% сверх 300тр за год: "<оплатить_за_год>"
|
||||
|
||||
Примеры:
|
||||
| доход | оплатить_за_квартал | оплатить_за_год |
|
||||
| 0 | 0 | 0 |
|
||||
| 300000 | 0 | 0 |
|
||||
| 300001 | 0 | 0 |
|
||||
| 300049 | 0 | 0 |
|
||||
| 300050 | 1 | 1 |
|
||||
| 300051 | 1 | 1 |
|
||||
| 300100 | 1 | 1 |
|
||||
| 300200 | 2 | 2 |
|
||||
| 400000 | 1000 | 1000 |
|
||||
| 500000 | 2000 | 2000 |
|
||||
|
||||
Сценарий: Платёж 1% сверх 300тр: в год и за все кварталы
|
||||
Дано Год: 2024
|
||||
Дано Доход <доход1> за 1 квартал
|
||||
Дано Доход <доход2> за 2 квартал
|
||||
Дано Доход <доход3> за 3 квартал
|
||||
Дано Доход <доход4> за 4 квартал
|
||||
Когда Расчитать год
|
||||
То Есть цель: 1% сверх 300тр за 1 квартал: "<оплатить1>"
|
||||
То Есть цель: 1% сверх 300тр за 2 квартал: "<оплатить2>"
|
||||
То Есть цель: 1% сверх 300тр за 3 квартал: "<оплатить3>"
|
||||
То Есть цель: 1% сверх 300тр за 4 квартал: "<оплатить4>"
|
||||
То Есть цель: 1% сверх 300тр за год: "<оплатить_за_год>"
|
||||
|
||||
Примеры:
|
||||
| доход1 | оплатить1 | доход2 | оплатить2 | доход3 | оплатить3 | доход4 | оплатить4 | оплатить_за_год |
|
||||
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
|
||||
| 100000 | 0 | 100000 | 0 | 0 | 0 | 0 | 0 | 0 |
|
||||
| 100000 | 0 | 100000 | 0 | 100000 | 0 | 0 | 0 | 0 |
|
||||
| 1000 | 0 | 90000 | 0 | 100000 | 0 | 100000 | 0 | 0 |
|
||||
| 100000 | 0 | 250000 | 500 | 0 | 0 | 0 | 0 | 500 |
|
||||
| 100000 | 0 | 100000 | 0 | 100000 | 0 | 100000 | 1000 | 1000 |
|
||||
| 100000 | 0 | 100000 | 0 | 200000 | 1000 | 100000 | 1000 | 2000 |
|
||||
| 100000 | 0 | 250000 | 500 | 400000 | 4000 | 0 | 0 | 4500 |
|
||||
| 100000 | 0 | 250000 | 500 | 400000 | 4000 | 500000 | 5000 | 9500 |
|
||||
| 400000 | 1000 | 0 | 0 | 0 | 0 | 0 | 0 | 1000 |
|
||||
| 0 | 0 | 400000 | 1000 | 0 | 0 | 0 | 0 | 1000 |
|
||||
| 0 | 0 | 0 | 0 | 400000 | 1000 | 0 | 0 | 1000 |
|
||||
| 0 | 0 | 0 | 0 | 0 | 0 | 400000 | 1000 | 1000 |
|
||||
| 400000 | 1000 | 100000 | 1000 | 0 | 0 | 0 | 0 | 2000 |
|
||||
| 400000 | 1000 | 500000 | 5000 | 600000 | 6000 | 700000 | 7000 | 19000 |
|
||||
|
||||
Сценарий: Платёж по УСН в квартале: 4%
|
||||
Дано Год: 2024
|
||||
Дано Квартал: <квартал>
|
||||
Дано Доход: 500000
|
||||
Когда Расчитать год
|
||||
То Есть цель: УСН за этот квартал: 20000
|
||||
|
||||
Примеры:
|
||||
| квартал |
|
||||
| 1 |
|
||||
| 2 |
|
||||
| 3 |
|
||||
| 4 |
|
11
pkg/schet/helpers.go
Обычный файл
11
pkg/schet/helpers.go
Обычный файл
|
@ -0,0 +1,11 @@
|
|||
package schet
|
||||
|
||||
import (
|
||||
"my/gnocount/pkg/accuracy"
|
||||
)
|
||||
|
||||
func процентСуммы(сумма float64) float64 {
|
||||
часть := сумма / 100.
|
||||
часть = float64(accuracy.ОкруглитьРубли(часть))
|
||||
return часть
|
||||
}
|
61
pkg/schet/init_test.go
Обычный файл
61
pkg/schet/init_test.go
Обычный файл
|
@ -0,0 +1,61 @@
|
|||
package schet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
. "my/gnocount/pkg/testlib"
|
||||
|
||||
"github.com/cucumber/godog"
|
||||
"github.com/cucumber/godog/colors"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func InitializeScenario(ctx *godog.ScenarioContext) {
|
||||
ctx.Step(`^Год: (\d+)$`, год)
|
||||
ctx.Step(`^Квартал: (\d+)$`, квартал)
|
||||
ctx.Step(`^Доход: (\d+)$`, доход)
|
||||
ctx.Step(`^Доход (\d+) за (\d+) квартал$`, доходЗаКвартал)
|
||||
ctx.Step(`^Расчитать год$`, расчитатьГод)
|
||||
ctx.Step(`^Есть цель: ОПС за этот квартал: (\d+)$`, естьЦельОПСЗаЭтотКвартал)
|
||||
ctx.Step(`^Есть цель: УСН за этот квартал: (\d+)$`, естьЦельУСНЗаЭтотКвартал)
|
||||
ctx.Step(`^Есть цель: (\d+)% сверх (\d+)тр за квартал: "([^"]*)"$`, естьЦельСверхТрЗаКвартал)
|
||||
ctx.Step(`^Есть цель: (\d+)% сверх (\d+)тр за (\d+) квартал: "([^"]*)"$`, естьЦельСверхТрЗаNКвартал)
|
||||
ctx.Step(`^Есть цель: (\d+)% сверх (\d+)тр за год: "([^"]*)"$`, естьЦельСверхТрЗаГод)
|
||||
|
||||
// -----------------------
|
||||
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()
|
||||
}
|
49
pkg/schet/kvartal.go
Обычный файл
49
pkg/schet/kvartal.go
Обычный файл
|
@ -0,0 +1,49 @@
|
|||
package schet
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Квартал struct {
|
||||
номер int
|
||||
год *Год
|
||||
доход float64
|
||||
ОПС *ОПС_type
|
||||
УСН *УСН_type
|
||||
}
|
||||
|
||||
func NewКвартал(номер int, год *Год) *Квартал {
|
||||
k := &Квартал{
|
||||
номер: номер,
|
||||
год: год,
|
||||
}
|
||||
k.создатьПлатежи()
|
||||
return k
|
||||
}
|
||||
|
||||
func (k *Квартал) создатьПлатежи() error {
|
||||
k.ОПС = NewОПС_type(k)
|
||||
k.УСН = NewУСН_type(k)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *Квартал) Номер() int {
|
||||
return k.номер
|
||||
}
|
||||
|
||||
func (k *Квартал) ДобавитьДоход(доход float64) error {
|
||||
k.доход = доход
|
||||
return nil
|
||||
}
|
||||
func (k *Квартал) Доход() float64 {
|
||||
return k.доход
|
||||
}
|
||||
|
||||
func (k *Квартал) ПроцентСверх300тр() (float64, error) {
|
||||
сумма, err := k.год.Сверх300трвКвартале(k.номер)
|
||||
if err != nil {
|
||||
return 0, errors.Join(errors.New("Квартал"), errors.New("Сверх300тр"), err)
|
||||
}
|
||||
|
||||
return процентСуммы(сумма), nil
|
||||
}
|
18
pkg/schet/ops.go
Обычный файл
18
pkg/schet/ops.go
Обычный файл
|
@ -0,0 +1,18 @@
|
|||
package schet
|
||||
|
||||
type ОПС_type struct {
|
||||
квартал *Квартал
|
||||
сумма float64
|
||||
}
|
||||
|
||||
func NewОПС_type(квартал *Квартал) *ОПС_type {
|
||||
o := &ОПС_type{
|
||||
квартал: квартал,
|
||||
сумма: 12375,
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *ОПС_type) Сумма() float64 {
|
||||
return o.сумма
|
||||
}
|
5
pkg/schet/out.go
Обычный файл
5
pkg/schet/out.go
Обычный файл
|
@ -0,0 +1,5 @@
|
|||
package schet
|
||||
|
||||
type OutIface interface {
|
||||
Печать(*Год) error
|
||||
}
|
77
pkg/schet/schet.go
Обычный файл
77
pkg/schet/schet.go
Обычный файл
|
@ -0,0 +1,77 @@
|
|||
package schet
|
||||
|
||||
const (
|
||||
КоличествоКварталов = 4
|
||||
НомерПервогоКвартала = 1
|
||||
НомерПоследнегоКвартала = 4
|
||||
)
|
||||
|
||||
type Год struct {
|
||||
год int
|
||||
цели *Цели
|
||||
доход float64
|
||||
out OutIface
|
||||
}
|
||||
|
||||
func NewГод(год int) *Год {
|
||||
g := &Год{
|
||||
год: год,
|
||||
}
|
||||
g.создатьЦели()
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *Год) создатьЦели() {
|
||||
c := NewЦели(g)
|
||||
for i := 0; i < КоличествоКварталов; i++ {
|
||||
c.Кварталы = append(c.Кварталы, NewКвартал(i+1, g))
|
||||
}
|
||||
g.цели = c
|
||||
}
|
||||
func (g *Год) Цели() *Цели {
|
||||
return g.цели
|
||||
}
|
||||
|
||||
func (g *Год) Год() int {
|
||||
return g.год
|
||||
}
|
||||
|
||||
func (g *Год) Квартал(in int) (k *Квартал, e error) {
|
||||
return g.цели.Квартал(in)
|
||||
}
|
||||
|
||||
func (g *Год) ДобавитьДоход(доход float64, i int) error {
|
||||
k, err := g.Квартал(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.доход += доход
|
||||
|
||||
return k.ДобавитьДоход(доход)
|
||||
}
|
||||
func (g *Год) Доход() float64 {
|
||||
return g.доход
|
||||
}
|
||||
|
||||
func (g *Год) ПроцентСверх300тр() (float64, error) {
|
||||
return ПроцентСверх300тр(g.доход), nil
|
||||
}
|
||||
|
||||
func (g *Год) Сверх300трвКвартале(квартал int) (float64, error) {
|
||||
сумматор := NewСумматор300тр()
|
||||
for i := НомерПервогоКвартала; i <= квартал; i++ {
|
||||
k, err := g.Квартал(i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
сумматор.ДобавитьКвартал(k.доход)
|
||||
}
|
||||
|
||||
return сумматор.Квартал(квартал)
|
||||
}
|
||||
|
||||
func (g *Год) Вывести(out OutIface) error {
|
||||
g.out = out
|
||||
return out.Печать(g)
|
||||
}
|
84
pkg/schet/schet_test.go
Обычный файл
84
pkg/schet/schet_test.go
Обычный файл
|
@ -0,0 +1,84 @@
|
|||
package schet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "my/gnocount/pkg/testlib"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
type testData struct {
|
||||
g *Год
|
||||
год_номер int
|
||||
квартал_номер int
|
||||
квартал *Квартал
|
||||
доход float64
|
||||
цели *Цели
|
||||
}
|
||||
|
||||
var (
|
||||
t *testData
|
||||
)
|
||||
|
||||
func resetTestData() {
|
||||
t = &testData{}
|
||||
}
|
||||
|
||||
func beforeSuite() {
|
||||
}
|
||||
func afterSuite() {
|
||||
}
|
||||
|
||||
func beforeScenario() {
|
||||
resetTestData()
|
||||
_ = Ω
|
||||
|
||||
}
|
||||
func afterScenario() {
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
func год(год int) {
|
||||
t.год_номер = год
|
||||
t.g = NewГод(t.год_номер)
|
||||
t.цели = t.g.Цели()
|
||||
}
|
||||
func квартал(квартал int) {
|
||||
t.квартал_номер = квартал
|
||||
k, err := t.цели.Квартал(t.квартал_номер)
|
||||
Ok(err)
|
||||
t.квартал = k
|
||||
}
|
||||
|
||||
func доход(доход float64) {
|
||||
t.доход = доход
|
||||
err := t.g.ДобавитьДоход(t.доход, t.квартал_номер)
|
||||
Ok(err)
|
||||
}
|
||||
func доходЗаКвартал(доход float64, квартал int) {
|
||||
err := t.g.ДобавитьДоход(доход, квартал)
|
||||
Ok(err)
|
||||
}
|
||||
|
||||
func расчитатьГод() {}
|
||||
|
||||
func естьЦельОПСЗаЭтотКвартал(v float64) {
|
||||
Ω(t.квартал.ОПС.Сумма()).To(Be(v), "ОПС за квартал")
|
||||
}
|
||||
|
||||
func естьЦельУСНЗаЭтотКвартал(v float64) {
|
||||
Ω(t.квартал.УСН.Сумма()).To(Be(v), "УСН за квартал")
|
||||
}
|
||||
|
||||
func естьЦельСверхТрЗаКвартал(_, _, оплатить string) {
|
||||
Ω(t.квартал.ПроцентСверх300тр()).To(Be(Atof(оплатить)), "1пр сверх 300тр за квартал")
|
||||
}
|
||||
func естьЦельСверхТрЗаNКвартал(arg1, arg2, in int, оплатить string) {
|
||||
k, err := t.цели.Квартал(in)
|
||||
Ok(err)
|
||||
|
||||
Ω(k.ПроцентСверх300тр()).To(Be(Atof(оплатить)), fmt.Sprintf("1пр сверх 300тр за квартал %v", in))
|
||||
}
|
||||
func естьЦельСверхТрЗаГод(_, _, оплатить string) {
|
||||
Ω(t.g.ПроцентСверх300тр()).To(Be(Atof(оплатить)), "1пр сверх 300тр за год")
|
||||
}
|
53
pkg/schet/summator300tr.go
Обычный файл
53
pkg/schet/summator300tr.go
Обычный файл
|
@ -0,0 +1,53 @@
|
|||
package schet
|
||||
|
||||
import "errors"
|
||||
|
||||
const (
|
||||
Сумма300тр = 300000
|
||||
)
|
||||
|
||||
type Сумматор300тр struct {
|
||||
набегающим_итогом float64
|
||||
сверхСуммы []float64
|
||||
}
|
||||
|
||||
func NewСумматор300тр() *Сумматор300тр {
|
||||
return &Сумматор300тр{}
|
||||
}
|
||||
|
||||
func (s *Сумматор300тр) Квартал(номер int) (float64, error) {
|
||||
index := номер - 1
|
||||
if index >= len(s.сверхСуммы) || index < 0 {
|
||||
return 0, errors.New("неизвестный квартал")
|
||||
}
|
||||
return s.сверхСуммы[index], nil
|
||||
}
|
||||
|
||||
func (s *Сумматор300тр) ДобавитьКвартал(сумма float64) {
|
||||
сверх := s.сверх300трСуммаЗаКвартал(сумма)
|
||||
s.сверхСуммы = append(s.сверхСуммы, сверх)
|
||||
}
|
||||
|
||||
func (s *Сумматор300тр) сверх300трСуммаЗаКвартал(сумма_за_квартал float64) float64 {
|
||||
сумма_предыдущих_кварталов := s.набегающим_итогом
|
||||
s.набегающим_итогом += сумма_за_квартал
|
||||
|
||||
if s.набегающим_итогом <= Сумма300тр {
|
||||
return 0
|
||||
}
|
||||
|
||||
if сумма_предыдущих_кварталов > Сумма300тр {
|
||||
return сумма_за_квартал
|
||||
}
|
||||
|
||||
return s.набегающим_итогом - Сумма300тр
|
||||
}
|
||||
|
||||
func ПроцентСверх300тр(сумма float64) float64 {
|
||||
свыше_300тр := сумма - Сумма300тр
|
||||
if свыше_300тр < 0 {
|
||||
свыше_300тр = 0
|
||||
}
|
||||
часть := процентСуммы(свыше_300тр)
|
||||
return часть
|
||||
}
|
18
pkg/schet/ucn.go
Обычный файл
18
pkg/schet/ucn.go
Обычный файл
|
@ -0,0 +1,18 @@
|
|||
package schet
|
||||
|
||||
type УСН_type struct {
|
||||
квартал *Квартал
|
||||
}
|
||||
|
||||
func NewУСН_type(квартал *Квартал) *УСН_type {
|
||||
o := &УСН_type{
|
||||
квартал: квартал,
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *УСН_type) Сумма() float64 {
|
||||
d := o.квартал.Доход()
|
||||
procent := d / 100.
|
||||
return 4 * procent
|
||||
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче