Начало: модуль счёта добавлен

Этот коммит содержится в:
Softonik 2024-06-25 18:03:31 +03:00 коммит произвёл Nobody
коммит 5ea7f5d13c
11 изменённых файлов: 488 добавлений и 0 удалений

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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -0,0 +1,11 @@
package schet
import (
"my/gnocount/pkg/accuracy"
)
func процентСуммы(сумма float64) float64 {
часть := сумма / 100.
часть = float64(accuracy.ОкруглитьРубли(часть))
return часть
}

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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -0,0 +1,5 @@
package schet
type OutIface interface {
Печать(*Год) error
}

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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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
}