Initial
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/output
|
||||
52
CLAUDE.md
Normal file
52
CLAUDE.md
Normal file
@ -0,0 +1,52 @@
|
||||
# Entity maker
|
||||
|
||||
## Description
|
||||
|
||||
Application connects to postgres database, inspects targeted table and creates:
|
||||
|
||||
- sqlalchemy table
|
||||
- model
|
||||
- filter
|
||||
- load options
|
||||
- repository
|
||||
- manager
|
||||
- factory
|
||||
|
||||
Generated source files are targeted for Python 3.13 using SQLAlchemy.
|
||||
|
||||
## Input parameters
|
||||
|
||||
Application have following command line parameters:
|
||||
- optional db host - default `localhost`
|
||||
- optional db port - default `5432`
|
||||
- optional db name
|
||||
- optional db schema - default `public`
|
||||
- optional db user - default `postgres`
|
||||
- optional db password - default `postgres`
|
||||
- optional db table
|
||||
- optional output directory
|
||||
- optional entity name
|
||||
|
||||
When application starts, it will offer users to enter missing parameters from command line, using defaults as listed above. Save entered values in `~/.config/entity-maker` and use it for the next time.
|
||||
|
||||
Generated files are placed in specificied output directory, in subdirectory named after table name, but in sigular. Check naming section for details.
|
||||
|
||||
## Examples
|
||||
|
||||
Example sql table structure is located in `./example/cashbag_conforms.sql`.
|
||||
Example output is located in `./example/cashbag_conform`.
|
||||
|
||||
## Naming example
|
||||
|
||||
Table name: `cashbag_conforms`.
|
||||
Output subdirectory: `cashbag_conform`
|
||||
Model name: `CashbagConform`
|
||||
Filter name `CashbagConformFilter`
|
||||
Load options name `CashbagConformLoadOptions`
|
||||
Repository name `CashbagConformRepository`
|
||||
Manager name `CashbagConformManager`
|
||||
Factory name `CashbagConformFactory`
|
||||
|
||||
## Technologies used
|
||||
|
||||
This is command line application. Application is written in golang. Application needs to be run on Linux only, no need to support other operating systems. Make application output modern and colorful.
|
||||
100
example/cashbag_confirms.sql
Normal file
100
example/cashbag_confirms.sql
Normal file
@ -0,0 +1,100 @@
|
||||
CREATE TABLE cashbag_conforms
|
||||
(
|
||||
id integer DEFAULT NEXTVAL('cashbag_conforms_id_seq'::regclass) NOT NULL
|
||||
PRIMARY KEY,
|
||||
alive boolean NOT NULL,
|
||||
count_coins numeric(12, 4) NOT NULL,
|
||||
count_bills numeric(12, 4) NOT NULL,
|
||||
tokens_number numeric(12, 4) NOT NULL,
|
||||
tokens_total numeric(12, 4) NOT NULL,
|
||||
count_timestamp timestamp with time zone,
|
||||
count_receive_timestamp timestamp with time zone,
|
||||
collect numeric(12, 4) NOT NULL,
|
||||
collect_timestamp timestamp with time zone,
|
||||
diff numeric(12, 4) NOT NULL,
|
||||
author_info_id integer NOT NULL
|
||||
UNIQUE
|
||||
CONSTRAINT cashbag_conf_author_info_id_1663387ed38e04b8_fk_author_infos_id
|
||||
REFERENCES author_infos
|
||||
DEFERRABLE INITIALLY DEFERRED,
|
||||
cashbag_id integer
|
||||
CONSTRAINT cashbag_conforms_cashbag_id_83139826_fk_cashbags_id
|
||||
REFERENCES cashbags
|
||||
DEFERRABLE INITIALLY DEFERRED,
|
||||
cashflow_collection_id integer
|
||||
CONSTRAINT "D4f92ee700d19ebb5990b785681a01fe"
|
||||
REFERENCES cashflow_collections
|
||||
DEFERRABLE INITIALLY DEFERRED,
|
||||
collect_user_id integer
|
||||
CONSTRAINT ca_collect_user_id_7d633e574f6c25a9_fk_custom_users_user_ptr_id
|
||||
REFERENCES custom_users
|
||||
DEFERRABLE INITIALLY DEFERRED,
|
||||
count_user_id integer
|
||||
CONSTRAINT cash_count_user_id_2601834f194be798_fk_custom_users_user_ptr_id
|
||||
REFERENCES custom_users
|
||||
DEFERRABLE INITIALLY DEFERRED,
|
||||
machine_id integer
|
||||
CONSTRAINT cashbag_conforms_machine_id_246129c5a92a0a91_fk_machines_id
|
||||
REFERENCES machines
|
||||
DEFERRABLE INITIALLY DEFERRED,
|
||||
route_id integer
|
||||
CONSTRAINT cashbag_conforms_route_id_18cfcd0d417870ef_fk_route_route_id
|
||||
REFERENCES route_route
|
||||
DEFERRABLE INITIALLY DEFERRED,
|
||||
external_route_id bigint,
|
||||
external_route_name varchar(255),
|
||||
no_cashbag_reason integer,
|
||||
_ver bigint,
|
||||
description text,
|
||||
status cashbag_conform_status_enum
|
||||
);
|
||||
|
||||
ALTER TABLE cashbag_conforms
|
||||
OWNER TO svc_cloud;
|
||||
|
||||
CREATE INDEX cashbag_conforms_6788849c
|
||||
ON cashbag_conforms (cashbag_id);
|
||||
|
||||
CREATE INDEX cashbag_conforms_6fce81cc
|
||||
ON cashbag_conforms (cashflow_collection_id);
|
||||
|
||||
CREATE INDEX cashbag_conforms_7016d9d6
|
||||
ON cashbag_conforms (collect_user_id);
|
||||
|
||||
CREATE INDEX cashbag_conforms_b4347999
|
||||
ON cashbag_conforms (route_id);
|
||||
|
||||
CREATE INDEX cashbag_conforms_d8f07203
|
||||
ON cashbag_conforms (count_user_id);
|
||||
|
||||
CREATE INDEX cashbag_conforms_external_route_id_12045111
|
||||
ON cashbag_conforms (external_route_id);
|
||||
|
||||
CREATE INDEX idx_cashbag_conforms_ver
|
||||
ON cashbag_conforms (COALESCE(_ver, 0::bigint));
|
||||
|
||||
CREATE INDEX idx_cashbag_conforms_collect_timestamp
|
||||
ON cashbag_conforms (collect_timestamp);
|
||||
|
||||
CREATE INDEX idx_cashbag_conforms_count_timestamp
|
||||
ON cashbag_conforms (count_timestamp);
|
||||
|
||||
CREATE INDEX idx_cashbag_conforms_machine_collect_timestamp
|
||||
ON cashbag_conforms (machine_id, collect_timestamp);
|
||||
|
||||
CREATE TRIGGER tr_ver_i_cashbag_conforms
|
||||
BEFORE INSERT
|
||||
ON cashbag_conforms
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE tr_ver_cashbag_conforms();
|
||||
|
||||
CREATE TRIGGER tr_ver_u_cashbag_conforms
|
||||
BEFORE UPDATE
|
||||
ON cashbag_conforms
|
||||
FOR EACH ROW
|
||||
WHEN (old.* IS DISTINCT FROM new.*)
|
||||
EXECUTE PROCEDURE tr_ver_cashbag_conforms();
|
||||
|
||||
GRANT INSERT, UPDATE ON cashbag_conforms TO cloud_write;
|
||||
|
||||
GRANT SELECT ON cashbag_conforms TO cloud_read;
|
||||
0
example/cashbag_conform/__init__.py
Normal file
0
example/cashbag_conform/__init__.py
Normal file
9
example/cashbag_conform/enum.py
Normal file
9
example/cashbag_conform/enum.py
Normal file
@ -0,0 +1,9 @@
|
||||
from enum import StrEnum
|
||||
|
||||
from televend_core.databases.enum import EnumMixin
|
||||
|
||||
|
||||
class CashBagConformStatusEnum(EnumMixin, StrEnum):
|
||||
OPEN = "OPEN"
|
||||
IN_PROGRESS = "IN_PROGRESS"
|
||||
DONE = "DONE"
|
||||
84
example/cashbag_conform/factory.py
Normal file
84
example/cashbag_conform/factory.py
Normal file
@ -0,0 +1,84 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Type
|
||||
|
||||
import factory
|
||||
|
||||
from televend_core.databases.televend_repositories.author_info.factory import (
|
||||
AuthorInfoFactory,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.cashbag.factory import (
|
||||
CashBagFactory,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.model import (
|
||||
CashBagConform,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.cashflow_collection.factory import (
|
||||
CashFlowCollectionFactory,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.custom_user.factory import (
|
||||
CustomUserFactory,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.machine.factory import MachineFactory
|
||||
from televend_core.test_extras.factory_boy_utils import (
|
||||
CustomSelfAttribute,
|
||||
TelevendBaseFactory,
|
||||
)
|
||||
|
||||
|
||||
class CashBagConformFactory(TelevendBaseFactory):
|
||||
alive = True
|
||||
id = None
|
||||
|
||||
count_coins = factory.Faker("pydecimal", left_digits=7, right_digits=4, positive=True)
|
||||
count_bills = factory.Faker("pydecimal", left_digits=7, right_digits=4, positive=True)
|
||||
tokens_number = factory.Faker("pydecimal", left_digits=7, right_digits=4, positive=True)
|
||||
tokens_total = factory.Faker("pydecimal", left_digits=7, right_digits=4, positive=True)
|
||||
count_timestamp = factory.Faker("date_time")
|
||||
count_receive_timestamp = factory.Faker("date_time")
|
||||
collect = factory.Faker("pydecimal", left_digits=7, right_digits=4, positive=True)
|
||||
collect_timestamp = factory.Faker("date_time")
|
||||
diff = factory.Faker("pydecimal", left_digits=7, right_digits=4, positive=True)
|
||||
|
||||
author_info = CustomSelfAttribute("..author_info", AuthorInfoFactory)
|
||||
author_info_id = factory.LazyAttribute(lambda a: a.author_info.id if a.author_info else None)
|
||||
|
||||
cashbag = CustomSelfAttribute("..cashbag", CashBagFactory)
|
||||
cashbag_id = factory.LazyAttribute(lambda a: a.cashbag.id if a.cashbag else None)
|
||||
|
||||
cashflow_collection = CustomSelfAttribute("..cashflow_collection", CashFlowCollectionFactory)
|
||||
cashflow_collection_id = factory.LazyAttribute(
|
||||
lambda a: a.cashflow_collection.id if a.cashflow_collection else None
|
||||
)
|
||||
|
||||
collect_user = CustomSelfAttribute("..collect_user", CustomUserFactory)
|
||||
collect_user_id = factory.LazyAttribute(
|
||||
lambda a: a.collect_user.user_ptr_id if a.collect_user else None
|
||||
)
|
||||
count_user = CustomSelfAttribute("..count_user", CustomUserFactory)
|
||||
count_user_id = factory.LazyAttribute(
|
||||
lambda a: a.count_user.user_ptr_id if a.count_user else None
|
||||
)
|
||||
|
||||
machine = CustomSelfAttribute("..machine", MachineFactory)
|
||||
machine_id = factory.LazyAttribute(lambda a: a.machine.id if a.machine else None)
|
||||
|
||||
external_route_id = factory.Faker("pyint")
|
||||
external_route_name = factory.Faker("pystr", max_chars=255)
|
||||
no_cashbag_reason = factory.Faker("pyint")
|
||||
|
||||
class Meta:
|
||||
model = CashBagConform
|
||||
|
||||
@classmethod
|
||||
def create_minimal(cls: Type[CashBagConformFactory], **kwargs) -> CashBagConform:
|
||||
minimal_params = {
|
||||
"author_info": kwargs.pop("author_info", None) or AuthorInfoFactory.create_minimal(),
|
||||
"cashbag": None,
|
||||
"cashflow_collection": None,
|
||||
"collect_user": None,
|
||||
"count_user": None,
|
||||
"machine": None,
|
||||
}
|
||||
minimal_params.update(kwargs)
|
||||
return cls.create(**minimal_params)
|
||||
14
example/cashbag_conform/filter.py
Normal file
14
example/cashbag_conform/filter.py
Normal file
@ -0,0 +1,14 @@
|
||||
from televend_core.databases.base_filter import BaseFilter
|
||||
from televend_core.databases.common.filters.filters import EQ, IN, filterfield
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.model import CashBagConform
|
||||
|
||||
|
||||
class CashBagConformFilter(BaseFilter):
|
||||
model_cls = CashBagConform
|
||||
|
||||
alive: bool | None = filterfield(operator=EQ, default=True)
|
||||
ids: list[int] | None = filterfield(field="id", operator=IN)
|
||||
machine_ids: list[int] | None = filterfield(field="machine_id", operator=IN)
|
||||
cashflow_collections_ids: list[int] | None = filterfield(
|
||||
field="cashflow_collections_id", operator=IN
|
||||
)
|
||||
12
example/cashbag_conform/load_options.py
Normal file
12
example/cashbag_conform/load_options.py
Normal file
@ -0,0 +1,12 @@
|
||||
from televend_core.databases.base_load_options import LoadOptions
|
||||
from televend_core.databases.common.load_options import joinload
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.model import CashBagConform
|
||||
|
||||
|
||||
class CashBagConformLoadOptions(LoadOptions):
|
||||
model_cls = CashBagConform
|
||||
|
||||
load_cashflow_collection: bool = joinload(relations=["cashflow_collection"])
|
||||
load_machine: bool = joinload(relations=["machine"])
|
||||
load_cashbag: bool = joinload(relations=["cashbag"])
|
||||
load_denominations: bool = joinload(relations=["denominations"])
|
||||
14
example/cashbag_conform/manager.py
Normal file
14
example/cashbag_conform/manager.py
Normal file
@ -0,0 +1,14 @@
|
||||
from televend_core.databases.base_manager import CRUDManager
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.filter import (
|
||||
CashBagConformFilter,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.model import CashBagConform
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.repository import (
|
||||
CashBagConformRepository,
|
||||
)
|
||||
|
||||
|
||||
class CashBagConformManager(
|
||||
CRUDManager[CashBagConform, CashBagConformFilter, CashBagConformRepository]
|
||||
):
|
||||
repository_cls = CashBagConformRepository
|
||||
54
example/cashbag_conform/model.py
Normal file
54
example/cashbag_conform/model.py
Normal file
@ -0,0 +1,54 @@
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from televend_core.databases.base_model import Base
|
||||
from televend_core.databases.televend_repositories.author_info.model import AuthorInfo
|
||||
from televend_core.databases.televend_repositories.cashbag.model import CashBag
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.enum import (
|
||||
CashBagConformStatusEnum,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.cashbag_conform_denominations.model import (
|
||||
CashBagConformDenomination,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.cashflow_collection.model import (
|
||||
CashFlowCollection,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.custom_user.model import CustomUser
|
||||
from televend_core.databases.televend_repositories.machine.model import Machine
|
||||
|
||||
|
||||
@dataclass
|
||||
class CashBagConform(Base):
|
||||
count_coins: Decimal
|
||||
count_bills: Decimal
|
||||
tokens_number: Decimal
|
||||
tokens_total: Decimal
|
||||
collect: Decimal
|
||||
diff: Decimal
|
||||
author_info_id: int
|
||||
author_info: AuthorInfo
|
||||
|
||||
count_timestamp: datetime | None = None
|
||||
count_receive_timestamp: datetime | None = None
|
||||
collect_timestamp: datetime | None = None
|
||||
cashbag_id: int | None = None
|
||||
cashbag: CashBag | None = None
|
||||
cashflow_collection_id: int | None = None
|
||||
cashflow_collection: CashFlowCollection | None = None
|
||||
collect_user_id: int | None = None
|
||||
collect_user: CustomUser | None = None
|
||||
count_user_id: int | None = None
|
||||
count_user: CustomUser | None = None
|
||||
machine_id: int | None = None
|
||||
machine: Machine | None = None
|
||||
external_route_id: int | None = None
|
||||
external_route_name: str | None = None
|
||||
no_cashbag_reason: int | None = None
|
||||
description: str | None = None
|
||||
status: CashBagConformStatusEnum | None = None
|
||||
|
||||
denominations: list[CashBagConformDenomination] | None = field(default_factory=list)
|
||||
|
||||
alive: bool = True
|
||||
id: int | None = None
|
||||
9
example/cashbag_conform/repository.py
Normal file
9
example/cashbag_conform/repository.py
Normal file
@ -0,0 +1,9 @@
|
||||
from televend_core.databases.base_repository import CRUDRepository
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.filter import (
|
||||
CashBagConformFilter,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.model import CashBagConform
|
||||
|
||||
|
||||
class CashBagConformRepository(CRUDRepository[CashBagConform, CashBagConformFilter]):
|
||||
model_cls = CashBagConform
|
||||
78
example/cashbag_conform/table.py
Normal file
78
example/cashbag_conform/table.py
Normal file
@ -0,0 +1,78 @@
|
||||
from sqlalchemy import (
|
||||
BigInteger,
|
||||
Boolean,
|
||||
Column,
|
||||
DateTime,
|
||||
Enum,
|
||||
ForeignKey,
|
||||
Integer,
|
||||
Numeric,
|
||||
String,
|
||||
Table,
|
||||
Text,
|
||||
)
|
||||
|
||||
from televend_core.databases.televend_repositories.cashbag_conform.enum import (
|
||||
CashBagConformStatusEnum,
|
||||
)
|
||||
from televend_core.databases.televend_repositories.table_meta import metadata_obj
|
||||
|
||||
CASHBAG_CONFORM_TABLE = Table(
|
||||
"cashbag_conforms",
|
||||
metadata_obj,
|
||||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||||
Column("alive", Boolean, nullable=False),
|
||||
Column("count_coins", Numeric(12, 4), nullable=False),
|
||||
Column("count_bills", Numeric(12, 4), nullable=False),
|
||||
Column("tokens_number", Numeric(12, 4), nullable=False),
|
||||
Column("tokens_total", Numeric(12, 4), nullable=False),
|
||||
Column("count_timestamp", DateTime(timezone=True)),
|
||||
Column("count_receive_timestamp", DateTime(timezone=True)),
|
||||
Column("collect", Numeric(12, 4), nullable=False),
|
||||
Column("collect_timestamp", DateTime(timezone=True)),
|
||||
Column("diff", Numeric(12, 4), nullable=False),
|
||||
Column(
|
||||
"author_info_id",
|
||||
Integer,
|
||||
ForeignKey("author_infos.id", deferrable=True, initially="DEFERRED"),
|
||||
nullable=False,
|
||||
unique=True,
|
||||
),
|
||||
Column(
|
||||
"cashbag_id",
|
||||
Integer,
|
||||
ForeignKey("cashbags.id", deferrable=True, initially="DEFERRED"),
|
||||
),
|
||||
Column(
|
||||
"cashflow_collection_id",
|
||||
Integer,
|
||||
ForeignKey("cashflow_collections.id", deferrable=True, initially="DEFERRED"),
|
||||
),
|
||||
Column(
|
||||
"collect_user_id",
|
||||
Integer,
|
||||
ForeignKey("custom_users.user_ptr_id", deferrable=True, initially="DEFERRED"),
|
||||
),
|
||||
Column(
|
||||
"count_user_id",
|
||||
Integer,
|
||||
ForeignKey("custom_users.user_ptr_id", deferrable=True, initially="DEFERRED"),
|
||||
),
|
||||
Column(
|
||||
"machine_id",
|
||||
Integer,
|
||||
ForeignKey("machines.id", deferrable=True, initially="DEFERRED"),
|
||||
),
|
||||
Column("external_route_id", BigInteger),
|
||||
Column("external_route_name", String(255)),
|
||||
Column("no_cashbag_reason", Integer),
|
||||
Column("description", Text, nullable=True),
|
||||
Column(
|
||||
"status",
|
||||
Enum(
|
||||
*CashBagConformStatusEnum.to_value_list(),
|
||||
name="cashbag_conform_status_enum",
|
||||
),
|
||||
nullable=True,
|
||||
),
|
||||
)
|
||||
Reference in New Issue
Block a user