/
YakuninAV
/
Convertors
Обзор
Документация
Войти
/
YakuninAV
/
Convertors
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Estimate/EstCommons.pas
3 492 строки
115 KB
YakuninAV
ПЗ, ТСН, ЛСР
04 авг 2026, 20:42
04 авг 2026, 20:42
0454200
Код
Авторство
О чём код?
unit EstCommons; {$I mormot.defines.inc} interface uses {$IFDEF DELPHIXE2} System.SysUtils, System.Classes, System.Types, System.DateUtils, System.StrUtils, System.TypInfo, {$ELSE} SysUtils, Classes, Types, DateUtils, StrUtils, TypInfo, {$ENDIF} mormot.core.base, mormot.core.variants, mormot.core.os, mormot.core.unicode, mormot.core.text, mormot.core.json, mormot.core.rtti, mormot.core.interfaces, mormot.core.data, mormot.core.datetime, mormot.core.buffers, DBDIntfs, DBDNotifiers, DBDCommons, DBDStrUtils, DBDUtils, dbdutf8utils, EstTypes, EstFlags, //EstPrices, EstInflationRates, EstRusStringsA, // EstRequisites, EstIntfsV3; var EstOrdersSeparator: AnsiChar = '|'; type TGetBaseUnitFunc= function(const U: string; var K: extended): string; var GetBaseFunction: TGetBaseUnitFunc; type TEstLinkDocumentV3=class(TInterfacedObject, IEstLinkDocumentV3) private function GetDescription: RawUtf8; function GetDocLinkType: Integer; function GetFileName: TFileName; function GetFileID: Integer; function GetIfcGUIDs: RawUtf8; function GetIfcPropName(const Index: Integer): RawUtf8; function GetIfcPropValue(const Index: Integer): RawUtf8; function GetIfcPropDescr(const Index: Integer): RawUtf8; function GetName: RawUtf8; function GetPages: RawUtf8; procedure SetDescription(const Value: RawUtf8); procedure SetFileName(const Value: TFileName); procedure SetFileID(const Value: Integer); procedure SetIfcGUIDs(const Value: RawUtf8); procedure SetIfcPropName(const Index: Integer; const Value: RawUtf8); procedure SetIfcPropValue(const Index: Integer; const Value: RawUtf8); procedure SetIfcPropDescr(const Index: Integer; const Value: RawUtf8); procedure SetName(const Value: RawUtf8); procedure SetPages(const Value: RawUtf8); protected FName: RawUtf8; FDescriptions, FNames, FValues: TRawUtf8List; FFileID: Integer; FLinkType: Integer; FFileName: TFileName; FFileListPtr: Pointer; public property Description: RawUtf8 read GetDescription write SetDescription; /// Тип ссылки-документа // 0 - ссылка на страницы документа // 1 - ссылки на идентификаторы IFC-документа // 2 - ссылки на свойства IFC-элементов в IFC-документе property DocLinkType: Integer read GetDocLinkType; /// Идентификатор файла property FileID: Integer read GetFileID write SetFileID; /// Имя файла с документом property FileName: TFileName read GetFileName write SetFileName; /// Список уникальных ifc идентификаторов элементов в файле, разделенных пробелом. property IfcGUIDs: RawUtf8 read GetIfcGUIDs write SetIfcGUIDs; /// Описание свойства propertyName элемента в ifc файле property IfcPropDescr[const Index: Integer]: RawUtf8 read GetIfcPropDescr write SetIfcPropDescr; /// Название свойства элемента в ifc файле property IfcPropName[const Index: Integer]: RawUtf8 read GetIfcPropName write SetIfcPropName; /// Значение свойства propertyName элемента в ifc файле property IfcPropValue[const Index: Integer]: RawUtf8 read GetIfcPropValue write SetIfcPropValue; constructor Create(const ALinkType: Integer; const AFileListPtr: Pointer); constructor CreatePages(const APages, ADescription: RawUtf8; const AFileListPtr: Pointer); constructor CreateGuids(const AGuids, ADescription: RawUtf8; const AFileListPtr: Pointer); constructor CreateProps(const APropName, APropValue, APropDescr: RawUtf8; const AFileListPtr: Pointer); destructor Destroy; override; /// Функция добавляет свойство function AddIfcProp(const APropName, APropValue, APropDescr: RawUtf8): Integer; /// Функция возвращает количество свойств function PropsCount: Integer; function IsPages: Boolean; function IsGuids: Boolean; function IsProps: Boolean; /// Наименование документа property Name: RawUtf8 read GetName write SetName; /// список номеров страниц документа, представленный в виде CSV-строки property Pages: RawUtf8 read GetPages write SetPages; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; TEstLinksV3 = class(TInterfacedObject, IEstLinksV3) private function GetAutoID: Boolean; function GetDoc(const ID: Integer): IEstLinkDocumentV3; function GetDocs: TEstLinkDocumentV3DynArray; protected FAutoID: Boolean; FDocs: TEstLinkDocumentV3DynArray; public /// Признак автогенерации ID для документов. Если признак установлен, то в функции AddOrUpdateDoc параметр ADocID игнорируется property AutoID: Boolean read GetAutoID; /// Массив документов привязанных к строке property Docs: TEstLinkDocumentV3DynArray read GetDocs; property Doc[const ID: Integer]: IEstLinkDocumentV3 read GetDoc; constructor Create(const AAutoID: Boolean); destructor Destroy; override; /// функция добавляет документ в массив документов привязанных к строке // Если ADocID больше нуля, то при наличии в массиве документов привязанных к строке документа с таки же ID производится // замена существующего, а, если нет, то производится добавление и документу присваивается указанный ID // Если ADocID меньше или равно нулю, документ добавляется и ему присваивается ID автоматически function AddOrUpdateDoc(const ADoc: IEstLinkDocumentV3; const AID: Integer=0): Integer; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; /// Информация об IFC-элементе BIM TEstBIMDataV3 = class(TInterfacedObject, IEstBIMDataV3) private function GetFileRef: Word; function GetIFCGuid: string; function GetIFCQuantity: Double; procedure SetFileRef(const Value: Word); procedure SetIFCGuid(const Value: string); procedure SetIFCQuantity(const Value: Double); protected FFileRef: Word; FIFCGuid: string; FIFCQuantity: Double; public /// Ссылка на порядковый номер IFC-файла в списке BIMFiles property FileRef: Word read GetFileRef write SetFileRef; /// Идентификатор элемента в IFC-файле property IFCGuid: string read GetIFCGuid write SetIFCGuid; property IFCQuantity: Double read GetIFCQuantity write SetIFCQuantity; constructor Create(const FR: Integer; const Guid: string; const Qty: Double=0.0); /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; ///Список ссылок TEstLinkFilesV3 = class(TInterfacedObject, IEstLinkFilesV3) private function GetLinkFiles: TLinkFileDynArray; protected FFiles: TStringDynArray; FIndexes: TIntegerDynArray; FPages: TIntegerDynArray; function IndexOfFile(const FileName: TFileName): Integer; function GetFileName(const Index: Integer): TFileName; inline; public property LinkFiles: TLinkFileDynArray read GetLinkFiles; constructor Create; /// Функция добавляет Ссылку на файл function AddLinkFile(const Link: TLinkFile): Integer; overload; /// Функция добавляет Ссылку на файл function AddLinkFile(const FileName: TFileName; const PageNo: Integer=0): Integer; overload; /// Процедура очищает список ссылок procedure Clear; /// Функция возвращает количество файлов хранящихся в списке ссылок function FileCount: Integer; /// Функция возвращает количество ссылок в списке function LinkCount: Integer; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; /// Класс реализующий работу со сметными датами TEstDateV3 = class(TInterfacedObject, IEstDateV3) private class var FZeroToFirstDay: Boolean; private FYear, FMonth, FDay: Word; FNote: string; /// Получить значение дня месяца function GetDay: Word; /// Получить значение Даты function GetDate: TDateTime; /// полдучить значение месяца function GetMonth: Word; /// Получить значение комментария к сметной дате function GetNote: string; /// Получить значение года function GetYear: Word; /// Получсить значение флага дополнения нуля до единицы function GetZeroToFirstDay: Boolean; /// Задать сметную дату с помощью DateTime procedure SetDate(const Value: TDateTime); /// Задать комментарий к сметной дате procedure SetNote(const Value: string); /// Задать значение флага дополнения нуля до единицы procedure SetZeroToFirstDay(const Value: Boolean); function GetQuarter: Word; public /// Представление сметной даты в виде TDateTime property Date: TDateTime read GetDate write SetDate; /// Год (должен быть больше 0 property Year: Word read GetYear; /// Номер месяца (может быть 0) property Month: Word read GetMonth; /// Номер квартала property Quarter: Word read GetQuarter; /// День месяца (может быть 0) property Day: Word read GetDay; /// Замечание к дате property Note: string read GetNote write SetNote; /// Флаг дополнения нуля до единицы. Если значение установлено, то в случае если день равен 0, // то дата приводится к началу месяца или к началу года (если месяц равен 0) property ZeroToFirstDay: Boolean read GetZeroToFirstDay write SetZeroToFirstDay; /// Конструктор constructor Create(const aYear: Word; const aMonth: Word=0; const aDay: Word=0; const aNote: string=''); overload; constructor Create(const dt: TDateTime); overload; constructor Create(const PDoc: PDocVariantData); overload; class function CompareQuarters(const Date1, Date2: IEstDateV3): Integer; class function Compare(const Date1, Date2: IEstDateV3; const CompareDay: Boolean=False): Integer; overload; /// Очистить информацию procedure Clear; /// функция сравнивает с другой сметной датой function Compare(OtherDate: IEstDateV3): Integer; overload; /// Функция возращает true, если счетная дата может быть представлена в виде TDateTime function isValidDate: Boolean; /// Функция возвращает дату в виде текста function TextDate(const Iso: Boolean=False): RawUtf8; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-представление сметной даты function ToDoc: Variant; end; /// Класс, реализующий интерфейс для работы с информацией о сметно-нормативном документе TEstLegalV3 = class(TInterfacedObject, IEstLegalV3) private function GetAddNum: Integer; function GetDate: IEstDateV3; function GetIsFederal: Boolean; function GetName: RawUtf8; function GetNormType: TEstimateNormativeType; function GetNum: Integer; function GetOrder(const Index: Integer): RawUtf8; function GetOrders: RawUtf8; function GetVersion: RawUtf8; procedure SetAddNum(Value: Integer); procedure SetDate(Value: IEstDateV3); procedure SetIsFederal(Value: Boolean); procedure SetName(Value: RawUtf8); procedure SetNormType(Value: TEstimateNormativeType); procedure SetNum(Value: Integer); procedure SetOrder(const Index: Integer; Value: RawUtf8); procedure SetOrders(Value: RawUtf8); procedure SetVersion(Value: RawUtf8); protected FAddNum: Integer; FisFederal: Boolean; FName: RawUtf8; FNum: Integer; FNormType: TEstimateNormativeType; FDate: IEstDateV3; FOrders: TRawUtf8DynArray; FVersion: RawUtf8; public /// Номер дополнения property AddNum: Integer Read GetAddNum write SetAddNum; /// Дата утверждающего документа property Date: IEstDateV3 read GetDate write SetDate; /// Признак федеральных нормативов property IsFederal: Boolean read GetIsFederal write SetIsFederal; /// Наименование сметно-нормативной документа property Name: RawUtf8 read GetName write SetName; /// Регистрационный номер документа в федеральном реестре сметных нормативов property Num: Integer read GetNum write SetNum; /// Тип сметно-нормативной документа из федерального реестра сметных нормативов property NormType: TEstimateNormativeType read GetNormType write SetNormType; /// Список реквизитов приказов об утверждении property Orders: RawUtf8 read GetOrders write SetOrders; /// Реквизиты приказа об утверждении property Order[const Index: Integer]: RawUtf8 read GetOrder write SetOrder; /// Версия сметно-нормативной базы property Version: RawUtf8 read GetVersion write SetVersion; /// Конструктор constructor Create; overload; /// Конструктор constructor Create(const aNormType: TEstimateNormativeType; const aNum: Integer; const aDate: IEstDateV3; const aOrders: RawUtf8; const aName: RawUtf8=''); overload; class function NormTypeS(const aNormType: TEstimateNormativeType): string; class function NormTypeU(const aNormType: TEstimateNormativeType): RawUtf8; /// Функция добавляет приказ в список function AddOrder(const aOrder: RawUtf8): Integer; /// Процедура удаляет из списка все приказы procedure ClearOrders; /// Функция возвращает количество приказов в списке function Count: Integer; /// Функция возвращает True, если документ имеет одинаковые реквизиты function isEqual(const Other: IEstLegalV3): Boolean; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; TEstMethodicLegalV3=class(TEstLegalV3) public constructor Create(ADate: TDateTime); end; /// Класс реализующий интерфейс для работы с информацией о сметно-нормативной базе TEstNormativeV3 = class(TInterfacedObject, IEstNormativeV3) private FName, FVersion, FLegalNum: string; FAddNum: Integer; FLegalDate: IEstDateV3; FNormType: TEstimateNormativeType; FisFederal: Boolean; FOrders, FOrdersIdx, FOrdersSal: string; function GetAddNum: Integer; function GetIsFederal: Boolean; function GetLegalDate: IEstDateV3; function GetLegalNum: string; function GetName: string; function GetNormType: TEstimateNormativeType; function GetOrders: string; function GetOrdersIdx: string; function GetOrdersSal: string; function GetVersion: string; procedure SetAddNum(Value: Integer); procedure SetIsFederal(Value: Boolean); procedure SetLegalDate(Value: IEstDateV3); procedure SetLegalNum(Value: string); procedure SetName(Value: string); procedure SetNormType(Value: TEstimateNormativeType); procedure SetOrders(Value: string); procedure SetOrdersIdx(Value: string); procedure SetOrdersSal(Value: string); procedure SetVersion(Value: string); public /// Номер дополнения property AddNum: Integer Read GetAddNum write SetAddNum; /// Признак федеральных нормативов property IsFederal: Boolean read GetIsFederal write SetIsFederal; /// Наименование сметно-нормативной базы property Name: string read GetName write SetName; /// Тип нормативов из федерального реестра сметных нормативов property NormType: TEstimateNormativeType read GetNormType write SetNormType; /// Приказы об утверждении сметного норматива property Orders: string read GetOrders write SetOrders; /// Приказы об индексах изменения сметной стоимости property OrdersIdx: string read GetOrdersIdx write SetOrdersIdx; /// Нормативный акт об утверждении оплаты труда property OrdersSal: string read GetOrdersSal write SetOrdersSal; /// Версия сметно-нормативной базы property Version: string read GetVersion write SetVersion; /// Номер утверждающего документа property LegalNum: string read GetLegalNum write SetLegalNum; /// Дата утверждающего документа property LegalDate: IEstDateV3 read GetLegalDate write SetLegalDate; /// Конструктор constructor Create; overload; constructor Create(const aName, aVersion, aLegalNum: string; aLegalDate: IEstDateV3); overload; constructor Create(const PDoc: PDocVariantData); overload; class function NormTypeFromString(const nt: string): TEstimateNormativeType; static; class function NormTypeToString(const nt: TEstimateNormativeType): string; static; /// Очистить информацию procedure Clear; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; /// Класс, реализующий интерфейс для работы с информацией о сметно-нормативных документах, используемых при составлении сметы TEstNormativesV3= class(TInterfacedObject, IEstNormativesV3) private function GetIndexes: TEstLegalV3DynArray; function GetIndexNorm(const Index: Integer): IEstLegalV3; function GetMethodics: IEstLegalV3; function GetNorm: IEstLegalV3; function GetOtherNorm(const Index: Integer): IEstLegalV3; function GetOthers: TEstLegalV3DynArray; function GetOverheads: IEstLegalV3; function GetProfits: IEstLegalV3; function GetResource(const Index: Integer): IEstLegalV3; function GetResources: TEstLegalV3DynArray; function GetSalary: IEstLegalV3; procedure SetIndexNorm(const Index: Integer; Value: IEstLegalV3); procedure SetMethodics(Value: IEstLegalV3); procedure SetNorm(Value: IEstLegalV3); procedure SetOverheads(Value: IEstLegalV3); procedure SetProfits(Value: IEstLegalV3); procedure SetResource(const Index: Integer; Value: IEstLegalV3); procedure SetSalary(Value: IEstLegalV3); procedure SetOtherNorm(const Index: Integer; Value: IEstLegalV3); protected FIndexes, FResources, FOthers: TEstLegalV3DynArray; FMethodics, FNorm, FOverheads, FProfits, FSalary: IEstLegalV3; public /// Нормтивный документ на индексы property IndexNorm[const Index: Integer]: IEstLegalV3 read GetIndexNorm write SetIndexNorm; /// Индексы изменения сметной стоимости property Indexes: TEstLegalV3DynArray read GetIndexes; /// Сметные методики расчётов property Methodics: IEstLegalV3 read GetMethodics write SetMethodics; /// Сметные нормативы property Norm: IEstLegalV3 read GetNorm write SetNorm; /// Прочий нормативный документ property OtherNorm[const Index: Integer]: IEstLegalV3 read GetOtherNorm write SetOtherNorm; /// Прочие сметные нормативы и методики property Others: TEstLegalV3DynArray read GetOthers; /// Накладные расходы property Overheads: IEstLegalV3 read GetOverheads write SetOverheads; /// Сметная прибыль property Profits: IEstLegalV3 read GetProfits write SetProfits; /// Нормативный документ на стоимость ресурсов property Resource[const Index: Integer]: IEstLegalV3 read GetResource write SetResource; /// массив нормативных документов на стоимость ресурсов property Resources: TEstLegalV3DynArray read GetResources; /// Оплата труда property Salary: IEstLegalV3 read GetSalary write SetSalary; constructor Create(); /// Функция добавляет документ с индексами в список function AddIndex(const aIndex: IEstLegalV3): Integer; /// Функция добавляет документы с прочими нормативами function AddOtherNorm(const aOther: IEstLegalV3): Integer; /// Функция добавляет документ с нормативом к ценам ресурсов function AddResource(const aResource: IEstLegalV3): Integer; /// Процедура очишает информацию procedure Clear; /// Функция проверяет в списке Индексов изменения сметной стоимости заданный документ и возвращает его позицию function FindIndex(const aIndex: IEstLegalV3): Integer; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; /// Класс реализующий интерфейс списка реквизитов TEstRequisitesListV3 = class(TInterfacedObject, IEstRequisitesListV3) private FOptions: TEstListOptions; FRequisites: TEstRequisiteV3DynArray; function GetOptions: TEstListOptions; function GetRequisite(Index: Integer): IEstRequisiteV3; function GetRequisites: TEstRequisiteV3DynArray; procedure SetOptions(Value: TEstListOptions); function CompareNames(const N1, N2: string): Integer; public /// Опции списка property Options: TEstListOptions read GetOptions write SetOptions; /// Реквизиты в списке property Requisite[Index: Integer]: IEstRequisiteV3 read GetRequisite; /// Массив реквизитов property Requisites: TEstRequisiteV3DynArray read GetRequisites; /// Конструктор constructor Create(const aOptions: TEstListOptions); /// Деструктор destructor Destroy; override; /// Добавляет реквизит в список. Если реквизит с именем уже в списке, то реквизит заменяется function Add(aRequisite: IEstRequisiteV3): Integer; /// Функция фозвращает true, если список пуст function isEmpty: Boolean; /// Очистить список procedure Clear; /// Функция возвращает количество элементов в списке function Count: Integer; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; /// Функция возвращает реквизит по его имени. Если имя не найдено то результат функции устанавливается в false function GetRequisiteByName(const Name: string; out oRequisite: IEstRequisiteV3): Boolean; /// Функция возвращает индекс реквизита function IndexByName(const Name: string): Integer; /// массив имён реквизитов в списке end; /// Класс реализующий интерфейс для представления реквизита TEstRequisiteV3 = class(TInterfacedObject, IEstRequisiteV3) private FKind: TEstRequisiteKind; FName, FValue, FDescription: string; function GetKind: TEstRequisiteKind; /// Получить описание реквизита function GetDescription: string; /// Получить наименование реквизита function GetName: string; /// Получить значение реквизита function GetValue: string; /// Задать описание реквизита procedure SetDescription(const NewValue: string); /// Задать наименование реквизита procedure SetName(const NewValue: string); /// Задать значение реквизита procedure SetValue(const NewValue: string); public /// Тип реквизита property Kind: TEstRequisiteKind read GetKind; /// Наименование реквизита property Name: string read GetName write SetName; /// Значение реквизита property Value: string read GetValue write SetValue; /// Описание реквизита property Description: string read GetDescription write SetDescription; /// Конструктор constructor Create(const aKind: TEstRequisiteKind; const aName: string=''; const aValue:string=''; const aDescription: string=''); destructor Destroy; override; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ с информацией о стоимости работ function ToDoc: Variant; /// Вывести информацию в строку function ToJSON: RawUTF8; inline; end; /// Класс реализующий интерфейс подписи TEstSignatureV3 = class(TInterfacedObject, IEstSignatureV3) private function GetCode: TEstJobCode; function GetDepartment: string; function GetEmpty: Boolean; function GetFIO: string; function GetJob: string; function GetRole: string; procedure SetCode(Value: TEstJobCode); procedure SetDepartment(Value: string); procedure SetEmpty(Value: Boolean); procedure SetFIO(Value: string); procedure SetJob(Value: string); procedure SetRole(Value: string); protected FCode: TEstJobCode; FFIO, FJob, FDepartment, FRole: string; public /// Код подписанта property Code: TEstJobCode read GetCode write SetCode; /// Признак отсутствия данных property Empty: Boolean read GetEmpty write SetEmpty; /// ФИО подписанта property FIO: string read GetFIO write SetFIO; /// Должность подписанта property Job: string read GetJob write SetJob; /// Наименование подразделения property Department: string read GetDepartment write SetDepartment; /// Роль property Role: string read GetRole write SetRole; constructor Create(const aCode: TEstJobCode; const aFIO: string); /// функция удаляет начальные тексты в строки с описанием должности class function TrimPost(const txt: string): string; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; overload; /// Функция возвращает JSON-документ function ToDoc: Variant; end; /// Класс реализующий интерфейс для работы сос списком подписей TEstSignaturesV3 = class(TInterfacedObject, IEstSignaturesV3) private function GetAllowDuplicates: Boolean; function GetCode(Index: TEstJobCode): IEstSignatureV3; function GetFIO(Index: TEstJobCode): string; inline; function GetRole(Index: string): IEstSignatureV3; function GetSignatures: TEstSignatureV3DynArray; function GetSignature(Index: Integer): IEstSignatureV3; procedure SetSignature(Index: Integer; Value: IEstSignatureV3); protected FAllowDuplicate: Boolean; FSignatures: TEstSignatureV3DynArray; public {свойства} /// Признак разрешающий повторяющиеся коды (Code) и роли (Role) в списке подписей property AllowDuplicates: Boolean read GetAllowDuplicates; /// Подписант имеющий код, если один код имеется несколько подписей, то выбирается первая property Code[Index: TEstJobCode]: IEstSignatureV3 read GetCode; /// Фамилия подписанта имеющего код, если один код имеется несколько подписей, то выбирается первая property FIO[Index: TEstJobCode]: string read GetFIO; /// Подписант исполняющий роль, если на одну роль приходится несколько подписей, то выбирается первая property Role[Index: string]: IEstSignatureV3 read GetRole; /// Массив подписей property Signatures: TEstSignatureV3DynArray read GetSignatures; /// Подписи property Signature[Index: Integer]: IEstSignatureV3 read GetSignature write SetSignature; /// конструктор constructor Create(const aDup: Boolean=False); /// функция добавляет подпись // пустая подпись (nil) не добавляется, функция возвращает -1 // function AddSignature(aSignature: IEstSignatureV3): Integer; /// Очистить список procedure Clear; /// Количество подписей function Count: Integer; /// Функция возвращает массив подписантов с одинаковым кодом function GetSignaturesByCode(const aCode: TEstJobCode): TEstSignatureV3DynArray; /// Функция возвращает массив подписантов с одинаковой ролью function GetSignaturesByRole(const aRole: string): TEstSignatureV3DynArray; /// CSV-список кодов function ListCodes: string; /// CSV-список ролей function ListRoles: string; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; TEstOrganisationV3 = class(TInterfacedObject, IEstOrganisationV3) private function GetKind: TEstOrganisationKind; function GetName: string; function GetOKPO: string; function GetSignatures: IEstSignaturesV3; procedure SetKind(Value: TEstOrganisationKind); procedure SetName(Value: string); procedure SetOKPO(Value: string); protected FKind: TEstOrganisationKind; FName: string; FOKPO: string; FSignatures: IEstSignaturesV3; public property Kind: TEstOrganisationKind read GetKind write SetKind; /// Наименование организации property Name: string read GetName write SetName; /// ОКПО организации property OKPO: string read GetOKPO write SetOKPO; /// Представители организации property Signatures: IEstSignaturesV3 read GetSignatures; /// Конструктор constructor Create(const aKind: TEstOrganisationKind; const aName: string; const aOKPO: string=''); overload; /// Конструктор constructor Create(const PDoc: PDocVariantData); overload; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; TEstCompanyV3 = class(TInterfacedObject, IEstCompanyV3) private function GetKind: TEstOrganisationKind; function GetName: RawUtf8; function GetINN: RawUtf8; function GetKPP: RawUtf8; function GetOKPO: RawUtf8; function GetRegion: RawUtf8; function GetRegionCode: Integer; function GetWebSite: RawUtf8; function GetSignatures: IEstSignaturesV3; procedure SetKind(const Value: TEstOrganisationKind); procedure SetName(const Value: RawUtf8); procedure SetINN(const Value: RawUtf8); procedure SetKPP(const Value: RawUtf8); procedure SetOKPO(const Value: RawUtf8); procedure SetRegion(const Value: RawUtf8); procedure SetRegionCode(const Value: Integer); procedure SetWebSite(const Value: RawUtf8); function GetNote: RawUtf8; procedure SetNote(const Value: RawUtf8); function GetEmail: RawUtf8; function GetFirstname: RawUtf8; procedure SetEmail(const Value: RawUtf8); procedure SetFirstname(const Value: RawUtf8); function GetOGRN: RawUtf8; procedure SetOGRN(const Value: RawUtf8); function GetPatronimic: RawUtf8; procedure SetPatronimic(const Value: RawUtf8); function GetSurname: RawUtf8; procedure SetSurname(const Value: RawUtf8); protected FKind: TEstOrganisationKind; FName, FNote, FINN, FKPP, FOGRN, FOKPO, FRegion, FWebSite, FEmail: RawUtf8; FRegionCode: Integer; FSignatures: IEstSignaturesV3; public /// Адрес электронной почты property Email: RawUtf8 read GetEmail write SetEmail; /// Имя индивидуального предпринимателя property Firstname: RawUtf8 read GetFirstname write SetFirstname; property Kind: TEstOrganisationKind read GetKind write SetKind; /// Наименование организации property Name: RawUtf8 read GetName write SetName; /// Примечания property Note: RawUtf8 read GetNote write SetNote; /// ИНН property INN: RawUtf8 read GetINN write SetINN; /// КПП property KPP: RawUtf8 read GetKPP write SetKPP; /// Основной государственный регистрационный номер юридического лица property OGRN: RawUtf8 read GetOGRN write SetOGRN; /// ОКПО организации property OKPO: RawUtf8 read GetOKPO write SetOKPO; /// Отчество (второе имя) property Patronimic: RawUtf8 read GetPatronimic write SetPatronimic; /// property Region: RawUtf8 read GetRegion write SetRegion; /// property RegionCode: Integer read GetRegionCode write SetRegionCode; /// property WebSite: RawUtf8 read GetWebSite write SetWebSite; /// Представители организации property Signatures: IEstSignaturesV3 read GetSignatures; /// Фамилия индивидуального предпринимателя property Surname: RawUtf8 read GetSurname write SetSurname; constructor Create(const aKind: TEstOrganisationKind=eokOther); /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; TEstRegionV3 = class(TInterfacedObject, IEstRegionV3) private function GetRailwayName: RawUtf8; function GetRegionName: RawUtf8; function GetRegionCode: Integer; function GetZoneName: RawUtf8; function GetZoneID: Integer; procedure SetRailwayName(const Value: RawUtf8); procedure SetRegionCode(const Value: Integer); procedure SetRegionName(const Value: RawUtf8); procedure SetZoneID(const Value: Integer); procedure SetZoneName(const Value: RawUtf8); function GetState: RawUtf8; procedure SetState(const Value: RawUtf8); protected const RegionIDFieldName: RawUTF8 = 'ri'; RegionNameFieldName: RawUTF8 = 'rn'; ZoneIDFiledName: RawUTF8 = 'zi'; ZoneNameFiledName: RawUTF8 = 'zn'; RailwayNameFiledName: RawUTF8 = 'wn'; StateFieldName: RawUtf8 = 'st'; protected FRegionCode: Integer; FZoneID: Integer; FRegionName, FRailwayName, FZoneName: RawUtf8; public {свойства} property RailwayName: RawUtf8 read GetRailwayName write SetRailwayName; /// Цифровой код субъекта РФ (региона) property RegionCode: Integer read GetRegionCode write SetRegionCode; /// Наименование региона property RegionName: RawUtf8 read GetRegionName write SetRegionName; /// Название государства property State: RawUtf8 read GetState write SetState; /// Цифровой код идентифицирующий подрайон, ценовая зона в составе основного региона (Субъект РФ), в котором расположен объект строительства property ZoneID: Integer read GetZoneID write SetZoneID; /// Наименование ценовой зоны property ZoneName: RawUtf8 read GetZoneName write SetZoneName; constructor Create(const RCode: Integer; const RName: RawUtf8=''); class function IsRussia(const RName: RawUtf8): Boolean; /// Функция определяет идентификатор региона по его наименованию, используя список регионов РФ, // хранящийся в ресурсах программы или в файле class function RegionIDByName(const RName: string; const Region: string; const FromResource: Boolean=True): Integer; static; /// Функция по коду региона определяет его наименование используя список субъектов РФ class function RegionNameByID(const RCode: Integer): RawUtf8; static; class function Utf8RegionNameByID(const RName: RawUtf8; const Region: Word; const FromResource: Boolean=True): RawUtf8; static; class function RailwayZoneNameByID(const RName: string; const Zone,Subzone: Word; const FromResource: Boolean=True): string; static; /// Функция возвращает строку из RZD_ZONES class function RailwayZoneStr(const RName: string; const Zone,Subzone: Word; const FromResource: Boolean=True): string; static; /// Функция возвращает строку из RZD_ZONES class function RailwayZoneUTF8(const RName: string; const Zone,Subzone: Word; const FromResource: Boolean=True): RawUtf8; static; /// функция корректирует информацию о ценовой зоне РЖД, используя строку из RZD_ZONES function PatchRailwayZoneFromUtf8(const Txt: RawUtf8): Boolean; /// функция корректирует информацию о ценовой зоне РЖД используя ресурсы // Предварительно информация о ценовой зоне РЖД уже получена из сметы (BASES_ZONES и CAPTION) function PatchRailwayZone: Boolean; /// функция корректирует информацию об идентификаторе ценовой зоны РЖД используя ресурсы function PatchRailwayZoneID: Boolean; /// Функция загружает информацию из JSON-документа function FromDoc(const PDoc: PDocVariantData): Boolean; /// Функция возвращает JSON-документ function ToDoc: Variant; end; TEstWinterRiseV3 =class(TInterfacedObject, IEstWinterRiseV3) private function GetCost: Double; function GetMaterial: Double; function GetItemSalary: Double; function GetItemMachines: Double; function GetItemMaterial: Double; function GetItemOverheads: Double; function GetItemProfits: Double; procedure SetCost(const AValue: Double); procedure SetMaterial(const AValue: Double); procedure SetItemMachines(const AValue: Double); procedure SeItemMaterial(const AValue: Double); procedure SetItemOverheads(const AValue: Double); procedure SetItemProfits(const AValue: Double); procedure SetItemSalary(const AValue: Double); protected FCost, FMaterial, FItemSalary, FItemMachines, FItemMaterial, FItemOverheads, FItemProfits: Double; public /// Зимнее удорожание работы property Cost: Double read GetCost write SetCost; ///Зимнее удорожание материалов property Material: Double read GetMaterial write SetMaterial; ///Зимнее удорожание к стоимости заработной плате рабочих для НЦКР property ItemSalary: Double read GetItemSalary write SetItemSalary; ///Зимнее удорожание к стоимости эксплуатации строительных машин для НЦКР property ItemMachines: Double read GetItemMachines write SetItemMachines; ///Зимнее удорожание к стоимости материалов для НЦКР property ItemMaterial: Double read GetItemMaterial write SeItemMaterial; ///Зимнее удорожание к накладным расходам для НЦКР property ItemOverheads: Double read GetItemOverheads write SetItemOverheads; ///Зимнее удорожание к сметной прибыли для НЦКР property ItemProfits: Double read GetItemProfits write SetItemProfits; constructor Create(const ACost, AMaterial: Double); function FromDoc(const PDoc: PDocVariantData): Boolean; function ToDoc: Variant; end; function EstValueFromString(const S: string; out oValue: Double): Boolean; function EstValueFromStringDef(const S: string; const DefValue: Double = 0): Double; function IndexTypeFromString(const S: string; out eit: TEstimateIndexType): Boolean; function ParseGIDColumn(const gid: RawUtf8; out ewt: TEstimateWorkType; out epi: TEstimatePriceItemType): Boolean; function GetAppDeveloper(const SoftName: string): TAppDeveloper; {CompatUnit =0 если единицы u1 u2 несовместны, иначе U1*Result=U2} function CompatUnit(const U1,U2: string): extended; function StringToInt(const S: string): int64; function FloatToStringEx(E: extended): string; inline; function StringToFloat(const S: string): extended; inline; function StringToFloatEx(const S: string): extended; inline; function ExtractUnitK(var U: string): integer; function FilterEDx(const E: string): string; inline; var EmptyEstDate: IEstDateV3; EmptyEstLegal: IEstLegalV3; implementation function StringToInt(const S: string): int64; var E: integer; begin if Length(S)=0 then Result:=0 else begin Val(S,Result,E); if E<>0 then Result:=0; end; end; function FloatToStringEx(E: extended): string; inline; begin Result:=DBDDoubleToStringEx(E, DBD_DOUBLE_PRECISION); end; function StringToFloat(const S: string): extended; inline; var D: Double; begin if DBDStringToDouble(s, D) then Result:=D else Result:=0; end; function StringToFloatEx(const S: string): extended; inline; var D: Double; begin if DBDStringToDouble(s, D) then Result:=D else Result:=0; end; function FilterEDx(const E: string): string; inline; var i,L: integer; C: char; begin Result:=Trim(E); end; function ExtractUnitK(var U: string): integer; var i,L: integer; begin L:= Length(U); i:=1; while (i<=L) and (U[i] in ['0'..'9']) do inc(i); dec(i); if i>0 then begin Result:=StrToInt(copy(U,1,i)); Delete(U,1,i); end else Result:=1; // DeleteSpaces(U); U:=AnsiReplaceText(U, ' ', '') end; {CompatUnit =0 если единицы u1 u2 несовместны, иначе U1*Result=U2} function CompatUnit(const U1,U2: string): extended; var S1,S2,B1,B2: string; K1,K2: integer; T1,P1,T2,P2: integer; F1,F2: extended; begin Result:=0.; S1:=AnsiUpperCase(FilterEdx(U1)); S2:=AnsiUpperCase(FilterEdx(U2)); if S1<>S2 then begin K1:=ExtractUnitK(S1); K2:=ExtractUnitK(S2); if AnsiCompareText(S1, S2) = 0 then Result := K2/K1 else begin B1:=GetBaseFunction(S1,F1); B2:=GetBaseFunction(S2,F2); if (B1=B2) and (B1>'') then Result:=(K2/K1)*(F2/F1); end; end else Result:=1; end; function GetAppDeveloper(const SoftName: string): TAppDeveloper; var s: string; begin Result:=adUndefine; if SoftName='' then Exit; s:=AnsiUpperCase(SoftName); if Pos('СТРОИТЕЛЬНЫЙ ЭКСПЕРТ',s)>0 then begin Result:=adDatabasis end else if Pos('WINРИК',s)>0 then begin Result:=adWinRik end else if Pos('ППРОГРАММНЫЙ КОМПЛЕКС АВС',s)>0 then begin Result:=adABC end else if Pos('SMETA.RU',s)>0 then begin Result:=adSmetaRu end else if Pos('ГРАНД-СМЕТА',s)>0 then begin Result:=adGrand end; end; function EstValueFromString(const S: string; out oValue: Double): Boolean; var s1: string; begin if EstimateFormatSettings.DecimalSeparator='.' then s1:=ReplaceStr(S,',','.') else s1:=ReplaceStr(S,'.',','); Result := TryStrToFloat(s1,oValue); end; function EstValueFromStringDef(const S: string; const DefValue: Double = 0): Double; begin if not EstValueFromString(S,Result) then Result := DefValue; end; function IndexTypeFromString(const S: string; out eit: TEstimateIndexType): Boolean; begin Result:=True; eit:=eitNone; if S='' then Result:=False else if S=rus_eitUnified then eit:=eitUnified else if S=rus_eitCosts then eit:=eitCosts else if S=rus_eitNone then eit:=eitNone else if S=rus_eitItems then eit:=eitItems else Result:=False; end; function ParseGIDColumn(const gid: RawUtf8; out ewt: TEstimateWorkType; out epi: TEstimatePriceItemType): Boolean; var p,p1: PUtf8Char; gl,gr: RawUtf8; s: string; begin if gid='' then Result:=False else begin p:=@gid[1]; p1:=dbdutf8utils.DBDFindChar(p,Ord('.')); if not DBDSplitTxt(gid,'.',gl,gr) then begin gl:=gid; gr:=''; end; if (Utf8ToString(gl)=rusTrans) then begin gl:=gid; end else if (Utf8ToString(gl)=rusEqu) then begin gl:=gid; end else if (Utf8ToString(gl)=rusMR) then begin gl:=gid; end; Result:=True; ewt:=ewtTotals; epi:=epiUndefine; s:=Utf8ToString(gl); if s=rusConsr then ewt:=ewtConstruction else if s=rusInstl then ewt:=ewtInstallation else if s=rusOthr then ewt:=ewtStartup else if s=rusEquCur then epi:=epiEquipmentNotENB else if s=rusEquEx then epi:=epiPortageEqmnt else if s=rusEquPrtgAdd then epi:=epiPortageEqmnt else if s=rusEqu then epi:=epiEquipmentTotal else if s=rusTotal then ewt:=ewtTotals else if s=rusPZ then epi:=epiDirect else if s=rusZP then epi:=epiSalary //MNB else if s=rusOT then epi:=epiWorkersSalary else if s=rusEMEx then epi:=epiMachines else if s=rusEM then epi:=epiMachinesTotal else if s=rusZPm_ then epi:=epiMachinistSalary else if s=rusOTm_ then epi:=epiMachinistSalary else if s=rusMRCur then epi:=epiMaterialNotENB else if s=rusMREx then epi:=epiMaterial else if s=rusMR then epi:=epiMaterialTotal else if s=rusTransEx then epi:=epiPortageMaterial else if s=rusTrans then epi:=epiPortage else if s=rusFOT then epi:=epiSalary else if s=rusNR then epi:=epiOverhead else if s=rusSP then epi:=epiProfit else if s=rusWinter then epi:=epiWinter else if s=rusTmpr then epi:=epiTemporary else if s=rusReturn then epi:=epiReturn else if s=rusNRZPM then epi:=epiOverheadMachSalary else if s=rusSPZPM then epi:=epiProfitMachSalary else if s=rusNRSPZPM then epi:=epiOPMachSalary ; if epi in [epiEquipment, epiEquipmentTotal, epiEquipmentNotENB, epiPortageEqmnt] then ewt:=ewtEquipment; if epi<>epiUndefine then Exit; s:=Utf8ToString(gr); if s='' then epi:=epiTotalPrice else if s=rusPZ then epi:=epiDirect else if s=rusOthrZT then epi:=epiOtherExpenses else if s=rusOthrST then epi:=epiOtherWorks else if s=rusOthrIdle then epi:=epiStartupOnIdle else if s=rusOthrLoad then epi:=epiStartupOnLoad else if s=rusZP then epi:=epiSalary //MNB else if s=rusOT then epi:=epiWorkersSalary else if s=rusEMEx then epi:=epiMachines else if s=rusEM then epi:=epiMachinesTotal else if s=rusZPm_ then epi:=epiMachinistSalary else if s=rusOTm_ then epi:=epiWorkersSalary else if s=rusMRCur then epi:=epiMaterialNotENB else if s=rusMREx then epi:=epiMaterial else if s=rusMR then epi:=epiMaterialTotal else if s=rusTransEx then epi:=epiPortageMaterial else if s=rusTrans then epi:=epiPortage else if s=rusFOT then epi:=epiSalary else if s=rusNR then epi:=epiOverhead else if s=rusSP then epi:=epiProfit // else if s=rusZT then epi:=epiLaborWorker // else if s=rusZTM then epi:=epiLaborMachinist else if s=rusNRSPZPM then epi:=epiOPMachSalary else if s=rusWinter then epi:=epiWinter else if s=rusTmpr then epi:=epiTemporary else if s=rusReturn then epi:=epiReturn ; end; // if (ewt=ewtOther) and (epi<>epiTotalPrice) then ewt:=ewtStartup; end; { TEstDateV3 } constructor TEstDateV3.Create(const aYear, aMonth, aDay: Word; const aNote: string); begin if aYear<50 then FYear:=aYear+2000 else if aYear<100 then FYear:=aYear+1900 else FYear:=aYear; if aMonth>12 then FMonth:=0 else FMonth:=aMonth; if (FMonth>0) and (aDay>0) then begin try EncodeDate(FYear, FMonth, aDay); FDay:=aDay; except FDay:=0; end; end else FDay:=0; FNote:=aNote; end; constructor TEstDateV3.Create(const dt: TDateTime); var y,m,d: Word; begin DecodeDate(dt, y,m,d); Create(y,m,d); end; procedure TEstDateV3.Clear; begin FYear:=0; FMonth:=0; FDay:=0; FNote:=''; end; function TEstDateV3.Compare(OtherDate: IEstDateV3): Integer; begin Result:=CompareInteger(FYear, OtherDate.Year); if Result=0 then Result:=CompareInteger(FMonth, OtherDate.Month); if Result=0 then Result:=CompareInteger(FDay, OtherDate.Day); end; class function TEstDateV3.Compare(const Date1, Date2: IEstDateV3; const CompareDay: Boolean=False): Integer; begin if Date1.Year>Date2.Year then Result:= 1 else if Date1.Year<Date2.Year then Result:=-1 else if Date1.Month>Date2.Month then Result:= 1 else if Date1.Month<Date2.Month then Result:=-1 else Result:= 0; if CompareDay and (Result=0) then begin if Date1.Day>Date2.Day then Result:= 1 else if Date1.Day<Date2.Day then Result:=-1; end; end; class function TEstDateV3.CompareQuarters(const Date1, Date2: IEstDateV3): Integer; begin if Date1.Year>Date2.Year then Result:= 1 else if Date1.Year<Date2.Year then Result:=-1 else if Date1.Quarter>Date2.Quarter then Result:= 1 else if Date1.Quarter<Date2.Quarter then Result:=-1 else Result:= 0; end; constructor TEstDateV3.Create(const PDoc: PDocVariantData); begin if (PDoc<>nil) and (PDoc.Kind=dvObject) then FromDoc(PDoc) else Create(Now); end; function TEstDateV3.GetDate: TDateTime; var m,d: Word; begin Result:=0; if FYear=0 then Exit else if FZeroToFirstDay then begin if FMonth=0 then begin m:=1; d:=1; end else begin m:=FMonth; if FDay=0 then d:=1 else d:=FDay; end; Result:=EncodeDate(FYear,m,d); end else begin if FMonth=0 then begin Result:=EndOfAYear(FYear); end else begin m:=FMonth; if FDay=0 then Result:=EndOfAMonth(FYear,m) else Result:=EncodeDate(FYear,FMonth,FDay); end; end; end; function TEstDateV3.GetDay: Word; begin Result:=FDay; end; function TEstDateV3.GetMonth: Word; begin Result:=FMonth; end; function TEstDateV3.GetNote: string; begin Result:=FNote; end; function TEstDateV3.GetQuarter: Word; begin if (FMonth=0) or (not isValidDate) then Result:=0 else begin Result:=((Month-1) div 3)+1; end; end; function TEstDateV3.GetYear: Word; begin Result:=FYear; end; function TEstDateV3.GetZeroToFirstDay: Boolean; begin Result:=FZeroToFirstDay end; function TEstDateV3.isValidDate: Boolean; begin Result:=(FYear>1900) and (FMonth<13) and (FDay<32); end; procedure TEstDateV3.SetDate(const Value: TDateTime); begin DecodeDate(Value, FYear, FMonth, FDay); end; procedure TEstDateV3.SetNote(const Value: string); begin FNote := Value; end; procedure TEstDateV3.SetZeroToFirstDay(const Value: Boolean); begin FZeroToFirstDay := Value; end; function TEstDateV3.FromDoc(const PDoc: PDocVariantData): Boolean; var i: Integer; r: RawUtf8; begin {$IFDEF DEBUG} Assert(PDoc<>nil, 'Указатель на JSON-нод не может быт nil'); {$ENDIF} Result := True; if PDoc^.GetAsInteger('y',i) then FYear:=i; if PDoc^.GetAsInteger('m',i) then FMonth:=i; if PDoc^.GetAsInteger('d',i) then FDay:=i; if not PDoc^.GetAsBoolean('z', FZeroToFirstDay) then FZeroToFirstDay := True; if PDoc^.GetAsRawUtf8('n',r) then FNote := Utf8ToString(r); end; function TEstDateV3.TextDate(const Iso: Boolean): RawUtf8; var d: TDateTime; begin d:=GetDate; if Iso then Result:=DateToIso8601(d, True) else Result:=StringToUtf8(DateToStr(d)); end; function TEstDateV3.ToDoc: Variant; begin TDocVariant.New(Result); TDocVariantData(Result).AddValue('y',FYear); TDocVariantData(Result).AddValue('m',FMonth); TDocVariantData(Result).AddValue('d',FDay); TDocVariantData(Result).AddValue('z',FZeroToFirstDay); TDocVariantData(Result).AddValue('n',StringToUTF8(FNote)); end; { TEstNormative } constructor TEstNormativeV3.Create; begin inherited Create; FName:=''; FVersion:=''; FLegalNum:=''; FLegalDate:=TEstDateV3.Create(0.0); end; constructor TEstNormativeV3.Create(const aName, aVersion, aLegalNum: string; aLegalDate: IEstDateV3); begin inherited Create; SetName(aName); SetVersion(aVersion); SetLegalNum(aLegalNum); SetLegalDate(aLegalDate); SetAddNum(0); end; procedure TEstNormativeV3.Clear; begin FName:=''; FVersion:=''; FLegalNum:=''; FAddNum:=0; FLegalDate.Clear; end; constructor TEstNormativeV3.Create(const PDoc: PDocVariantData); begin Create('','','',nil); if PDoc<>nil then FromDoc(PDoc); end; class function TEstNormativeV3.NormTypeFromString(const nt: string): TEstimateNormativeType; begin if nt='ГСН' then Result:=entGSN else if nt='ОСН' then Result:=entOSN else if nt='ТЕР' then Result:=entTER else if nt='ИСН' then Result:=entISN else if nt='Справочная информация' then Result:=entRef else if nt='Сплит-форма' then Result:=entSplit else Result:=entRef ; end; class function TEstNormativeV3.NormTypeToString(const nt: TEstimateNormativeType): string; begin case nt of entGSN: Result:='ГСН'; entOSN: Result:='ОСН'; entTER: Result:='ТЕР'; entISN: Result:='ИСН'; entRef: Result:='Справочная информация'; entSplit: Result:='Сплит-форма'; else Result:='Справочная информация'; end; end; function TEstNormativeV3.GetAddNum: Integer; begin Result:=FAddNum; end; function TEstNormativeV3.GetIsFederal: Boolean; begin Result:=FisFederal; end; function TEstNormativeV3.GetLegalDate: IEstDateV3; begin Result:=FLegalDate; end; function TEstNormativeV3.GetLegalNum: string; begin Result:=FLegalNum; end; function TEstNormativeV3.GetName: string; begin Result:=FName; end; function TEstNormativeV3.GetNormType: TEstimateNormativeType; begin Result:=FNormType; end; function TEstNormativeV3.GetOrders: string; begin Result:=FOrders; end; function TEstNormativeV3.GetOrdersIdx: string; begin Result:=FOrdersIdx; end; function TEstNormativeV3.GetOrdersSal: string; begin Result:=FOrdersSal; end; function TEstNormativeV3.GetVersion: string; begin Result:=FVersion; end; procedure TEstNormativeV3.SetAddNum(Value: Integer); begin FAddNum:=Value; end; procedure TEstNormativeV3.SetIsFederal(Value: Boolean); begin FIsFederal:=Value; end; procedure TEstNormativeV3.SetLegalDate(Value: IEstDateV3); begin if Value<>nil then FLegalDate:=Value else FLegalDate:=TEstDateV3.Create(Now); end; procedure TEstNormativeV3.SetLegalNum(Value: string); begin FLegalNum:=Value; end; procedure TEstNormativeV3.SetName(Value: string); begin FName:=Value; end; procedure TEstNormativeV3.SetNormType(Value: TEstimateNormativeType); begin FNormType:=Value; end; procedure TEstNormativeV3.SetOrders(Value: string); begin FOrders:=Value; end; procedure TEstNormativeV3.SetOrdersIdx(Value: string); begin FOrdersIdx:=Value; end; procedure TEstNormativeV3.SetOrdersSal(Value: string); begin FOrdersSal:=Value; end; procedure TEstNormativeV3.SetVersion(Value: string); begin FVersion:=Value; end; function TEstNormativeV3.FromDoc(const PDoc: PDocVariantData): Boolean; var iNrm: Integer; r,rNam,rVer,rLgl: RawUtf8; p: PDocVariantData; begin Result := PDoc^.GetAsInteger('NormType',iNrm) and PDoc^.GetAsRawUtf8('Name',rNam) and PDoc^.GetAsRawUtf8('Ver',rVer) and PDoc^.GetAsRawUtf8('Num',rlgl) ; if Result then begin FNormType := TEstimateNormativeType(iNrm); FName := Utf8ToString(rNam); FVersion := Utf8ToString(rVer); FLegalNum := Utf8ToString(rLgl); if not PDoc^.GetAsInteger('Add', FAddNum) then FAddNum:=0; if not PDoc^.GetAsBoolean('Fed', FisFederal) then FisFederal := False; if PDoc^.GetAsDocVariant('Date',p) then begin if FLegalDate=nil then FLegalDate := TEstDateV3.Create(p); Result := FLegalDate.FromDoc(p); end; if PDoc^.GetAsRawUtf8('ord',r) then FOrders:=Utf8ToSTring(r) else FOrders:=''; if PDoc^.GetAsRawUtf8('idx',r) then FOrdersIdx:=Utf8ToSTring(r) else FOrdersIdx:=''; if PDoc^.GetAsRawUtf8('sal',r) then FOrdersSal:=Utf8ToSTring(r) else FOrdersSal:=''; end; end; function TEstNormativeV3.ToDoc: Variant; var r: RawUTF8; v:Variant; begin Result:=_Obj(['NormType',Ord(FNormType)]); r:=PRttiInfo(TypeInfo(TEstimateNormativeType))^.EnumBaseType.GetEnumNameTrimed(FNormType); TDocVariantData(Result).AddValue('ntName', r); TDocVariantData(Result).AddValue('Name', StringToUTF8(FName)); TDocVariantData(Result).AddValue('Ver', StringToUTF8(FVersion)); TDocVariantData(Result).AddValue('Num', StringToUTF8(FLegalNum)); if FAddNum>0 then TDocVariantData(Result).AddValue('Add', FAddNum); if FLegalDate<> nil then begin v:=FLegalDate.ToDoc; TDocVariantData(Result).AddValue('Date', v); TDocVariantData(v).Clear; end; TDocVariantData(Result).AddValue('Fed', FisFederal); if FOrders<>'' then begin r:=StringToUtf8(FOrders); TDocVariantData(Result).AddValue('ord', FOrders); end; if FOrdersIdx<>'' then begin r:=StringToUtf8(FOrdersIdx); TDocVariantData(Result).AddValue('idx', FOrders); end; if FOrdersSal<>'' then begin r:=StringToUtf8(FOrdersSal); TDocVariantData(Result).AddValue('sal', FOrders); end; end; { ЕEstSignatureV3 } function TEstSignatureV3.GetCode: TEstJobCode; begin Result:=FCode; end; function TEstSignatureV3.GetDepartment: string; begin Result:=FDepartment; end; function TEstSignatureV3.GetEmpty: Boolean; begin Result:=(FFIO=''); end; function TEstSignatureV3.GetFIO: string; begin Result:=FFIO; end; function TEstSignatureV3.GetJob: string; begin Result:=FJob; end; function TEstSignatureV3.GetRole: string; begin Result:=FRole; end; procedure TEstSignatureV3.SetCode(Value: TEstJobCode); begin FCode:=Value; end; procedure TEstSignatureV3.SetDepartment(Value: string); begin FDepartment:=DBDTrim(Value); end; procedure TEstSignatureV3.SetEmpty(Value: Boolean); begin if Value then begin FFIO:=''; FCode:=ejcUndefine; FRole:=''; FJob:=''; FDepartment:=''; end; end; procedure TEstSignatureV3.SetFIO(Value: string); begin if Value<>'' then FFIO:=DBDTrim(Value) else SetEmpty(True); end; procedure TEstSignatureV3.SetJob(Value: string); begin FJob:=DBDTrim(Value); end; procedure TEstSignatureV3.SetRole(Value: string); begin FRole:=DBDTrim(Value); end; constructor TEstSignatureV3.Create(const aCode: TEstJobCode; const aFIO: string); begin inherited Create; SetEmpty(True); FCode:=aCode; SetFIO(aFIO); end; function TEstSignatureV3.FromDoc(const PDoc: PDocVariantData): Boolean; var iCode: Integer; rFio,r: RawUtf8; begin Result := PDoc^.GetAsInteger('code',iCode) and PDoc^.GetAsRawUtf8('fio',rFio) ; if Result then begin fCode:=TEstJobCode(iCode); SetFIO(Utf8ToString(rFio)); if PDoc^.GetAsRawUtf8('job', r) then SetJob(Utf8ToString(r)) else FJob:=''; if PDoc^.GetAsRawUtf8('role', r) then SetRole(Utf8ToString(r)) else FRole:=''; if PDoc^.GetAsRawUtf8('dep', r) then SetDepartment(Utf8ToString(r)) else FDepartment:=''; end; end; function TEstSignatureV3.ToDoc: Variant; var r: RawUTF8; begin Result:=_Obj(['code', Ord(FCode)]); r:=PRttiInfo(TypeInfo(TEstJobCode))^.EnumBaseType.GetEnumNameTrimed(FCode); TDocVariantData(Result).AddValue('codn', r); TDocVariantData(Result).AddValue('fio', StringToUtf8(FFIO)); TDocVariantData(Result).AddValue('job', StringToUtf8(FJob)); TDocVariantData(Result).AddValue('role', StringToUtf8(FRole)); TDocVariantData(Result).AddValue('dep', StringToUtf8(FDepartment)); end; class function TEstSignatureV3.TrimPost(const txt: string): string; var r,r0: RawUtf8; begin Result:=txt; r:= StringToUtf8(txt); r0:=r; if r0=r then r:=DBDTrimSubstr(r,'Составил ', dbdSPLeft); if r0=r then r:=DBDTrimSubstr(r,'Проверил ', dbdSPLeft); if r0=r then r:=DBDTrimSubstr(txt,'Начальник отдела ', dbdSPLeft); if r0=r then r:=DBDTrimSubstr(txt,'Начальник сметного отдела ', dbdSPLeft); Result:=r; end; { TEstSignaturesV3 } function TEstSignaturesV3.AddSignature(aSignature: IEstSignatureV3): Integer; var i: Integer; s:IEstSignatureV3; begin if aSignature=nil then Result:=-1 else begin Result:=0; if not FAllowDuplicate then for i:=Low(FSignatures) to High(FSignatures) do begin s:=FSignatures[i]; if (s.Code<>ejcUndefine) and (aSignature.Code<>ejcUndefine) and (s.Code=aSignature.Code) then Result:=-2 else if (aSignature.Role<>'') and (s.Role=aSignature.Role) then Result:=-3; if Result<0 then Exit; end; Result:=Length(FSignatures); SetLength(FSignatures, Result+1); FSignatures[Result]:=aSignature; end; end; procedure TEstSignaturesV3.Clear; begin SetLength(FSignatures,0); end; function TEstSignaturesV3.Count: Integer; begin Result:=Length(FSignatures); end; constructor TEstSignaturesV3.Create(const aDup: Boolean); begin inherited Create; FAllowDuplicate:=aDup; SetLength(FSignatures,0); end; function TEstSignaturesV3.GetAllowDuplicates: Boolean; begin Result:=FAllowDuplicate; end; function TEstSignaturesV3.GetCode(Index: TEstJobCode): IEstSignatureV3; var i: Integer; begin Result:=nil; for i := Low(FSignatures) to High(FSignatures) do if FSignatures[i].Code=Index then begin Result:=FSignatures[i]; Break; end; end; function TEstSignaturesV3.GetFIO(Index: TEstJobCode): string; var i: IEstSignatureV3; begin i:=GetCode(Index); if i<>nil then Result:=i.FIO else Result:=''; end; function TEstSignaturesV3.GetRole(Index: string): IEstSignatureV3; var i: Integer; begin Result:=nil; for i := Low(FSignatures) to High(FSignatures) do if FSignatures[i].Role=Index then begin Result:=FSignatures[i]; Break; end; end; function TEstSignaturesV3.GetSignature(Index: Integer): IEstSignatureV3; begin if (Index>=Low(FSignatures)) and (Index<=High(FSignatures)) then Result:=FSignatures[Index] else Result:=nil; end; function TEstSignaturesV3.GetSignatures: TEstSignatureV3DynArray; begin Result:=FSignatures; end; function TEstSignaturesV3.GetSignaturesByCode(const aCode: TEstJobCode): TEstSignatureV3DynArray; var i,j: Integer; begin SetLength(Result, Length(FSignatures)); j:=0; for i := Low(FSignatures) to High(FSignatures) do if FSignatures[i].Code=aCode then begin Result[j]:=FSignatures[i]; Inc(j); end; SetLength(Result,j); end; function TEstSignaturesV3.GetSignaturesByRole(const aRole: string): TEstSignatureV3DynArray; var i,j: Integer; begin SetLength(Result, Length(FSignatures)); j:=0; for i := Low(FSignatures) to High(FSignatures) do if FSignatures[i].Role=aRole then begin Result[j]:=FSignatures[i]; Inc(j); end; SetLength(Result,j); end; function TEstSignaturesV3.ListCodes: string; var i: Integer; begin Result:=''; if Length(FSignatures)=0 then Exit; Result:=IntToStr(Ord(FSignatures[0].Code)); for i := 1 to High(FSignatures) do Result := Result + ';' + IntToStr(Ord(FSignatures[i].Code)); end; function TEstSignaturesV3.ListRoles: string; var i: Integer; begin Result:=''; if Length(FSignatures)=0 then Exit; Result:=FSignatures[0].Role; for i := 1 to High(FSignatures) do Result := Result + ';' + FSignatures[i].Role; end; procedure TEstSignaturesV3.SetSignature(Index: Integer; Value: IEstSignatureV3); begin if (Index>=Low(FSignatures)) and (Index<=High(FSignatures)) then FSignatures[Index]:=Value; end; function TEstSignaturesV3.FromDoc(const PDoc: PDocVariantData): Boolean; var p: PDocVariantData; i: Integer; s: IEstSignatureV3; begin Clear; Result := PDoc^.GetAsBoolean('dup',FAllowDuplicate) and PDoc^.GetAsDocVariant('sig', p) and (p^.Kind=dvArray); if Result then begin for i := 0 to p^.Count-1 do begin s:=TEstSignatureV3.Create(ejcUndefine,''); if s.FromDoc(p^._[i]) then Result := (AddSignature(s)>=0) and Result else Result :=False; end; end; end; function TEstSignaturesV3.ToDoc: Variant; var a,v:Variant; i: Integer; begin Result:=_Obj(['dup', FAllowDuplicate]); a:=_Arr([]); v:=_Obj([]); for I := Low(FSignatures) to High(FSignatures) do begin v:=FSignatures[i].ToDoc; TDocVariantData(a).AddItem(v); TDocVariantData(v).Reset; end; TDocVariantData(Result).AddValue('sig', a); TDocVariantData(v).Clear; end; { TEstBIMDataV3 } constructor TEstBIMDataV3.Create(const FR: Integer; const Guid: string; const Qty: Double); begin inherited Create; FFileRef:=FR; FIFCGuid:=Guid; FIFCQuantity:=Qty; end; function TEstBIMDataV3.GetFileRef: Word; begin Result:=FFileRef; end; function TEstBIMDataV3.GetIFCGuid: string; begin Result:=FIFCGuid; end; function TEstBIMDataV3.GetIFCQuantity: Double; begin Result:=FIFCQuantity; end; procedure TEstBIMDataV3.SetFileRef(const Value: Word); begin FFileRef:=Value; end; procedure TEstBIMDataV3.SetIFCGuid(const Value: string); begin FIFCGuid:=Value; end; procedure TEstBIMDataV3.SetIFCQuantity(const Value: Double); begin FIFCQuantity:=Value; end; function TEstBIMDataV3.FromDoc(const PDoc: PDocVariantData): Boolean; var i: Integer; r: RawUtf8; begin FFileRef:= 0; FIFCGuid:=''; FIFCQuantity:=0; Result:= (PDoc<>nil) and (PDoc^.Kind=dvObject) and (PDoc^.Count>=3) and PDoc^.GetAsInteger('ref', i) and (i>=0) and (i<=65535) and PDoc^.GetAsRawUtf8('guid', r) and PDoc^.GetAsDouble('qty', FIFCQuantity) ; if Result then begin FFileRef:= i; FIFCGuid:=Utf8ToString(r); end; end; function TEstBIMDataV3.ToDoc: Variant; var i: Integer; r: RawUtf8; begin i:=FFileRef; r:=StringToUtf8(FIFCGuid); Result:=_Obj(['ref', i, 'guid', r, 'qty', FIFCQuantity]); end; { TEstOrganisationV3 } constructor TEstOrganisationV3.Create(const aKind: TEstOrganisationKind; const aName, aOKPO: string); begin inherited Create; SetKind(aKind); SetName(aName); SetOKPO(aOKPO); FSignatures:=TEstSignaturesV3.Create(True); end; function TEstOrganisationV3.GetKind: TEstOrganisationKind; begin Result:=FKind; end; function TEstOrganisationV3.GetName: string; begin Result:=FName; end; function TEstOrganisationV3.GetOKPO: string; begin Result:=FOKPO; end; function TEstOrganisationV3.GetSignatures: IEstSignaturesV3; begin Result:=FSignatures; end; procedure TEstOrganisationV3.SetKind(Value: TEstOrganisationKind); begin FKind:=Value; end; procedure TEstOrganisationV3.SetName(Value: string); begin FName:=Value; end; procedure TEstOrganisationV3.SetOKPO(Value: string); begin FOKPO:=Value; end; constructor TEstOrganisationV3.Create(const PDoc: PDocVariantData); begin if not FromDoc(PDoc) then begin FName:=''; FOKPO:=''; FKind:=eokOther; end; end; function TEstOrganisationV3.FromDoc(const PDoc: PDocVariantData): Boolean; var i: Integer; r: RawUtf8; p: PDocVariantData; begin FName:=''; FOKPO:=''; FKind:=eokOther; Result:= (PDoc<>nil) and (PDoc^.Kind=dvObject) and (PDoc^.Count>1) and PDoc^.GetAsInteger('knd',i) and (i>=0) and (i<=Ord(eokOther)) and PDoc^.GetAsRawUtf8('nam',r) and (r<>'') ; if Result then begin SetKind(TEstOrganisationKind(i)); FName:= Utf8ToString(r); if PDoc^.GetAsRawUtf8('okpo', r) then FOKPO:=Utf8ToString(r); if PDoc^.GetAsDocVariant('sig',p) then Result:=FSignatures.FromDoc(p); end; end; function TEstOrganisationV3.ToDoc: Variant; var r: RawUtf8; v: Variant; begin Result:=_Obj([]); TDocVariantData(Result).AddValue('knd', Ord(FKind)); r:=PRttiInfo(TypeInfo(TEstOrganisationKind))^.EnumBaseType.GetEnumNameTrimed(FKind); TDocVariantData(Result).AddValue('nkn', r); r:=StringToUtf8(FName); TDocVariantData(Result).AddValue('nam', r); r:=StringToUtf8(FOKPO); TDocVariantData(Result).AddValue('okpo', r); v:=FSignatures.ToDoc; TDocVariantData(Result).AddValue('sig', v); TDocVariantData(v).Clear; end; { TEstRequisiteV3 } constructor TEstRequisiteV3.Create(const aKind: TEstRequisiteKind; const aName, aValue, aDescription: string); begin inherited Create; FKind:=aKind; SetName(aName); SetValue(aValue); SetDescription(aDescription); end; destructor TEstRequisiteV3.Destroy; begin FName:=''; FValue:=''; FDescription:=''; inherited; end; function TEstRequisiteV3.GetDescription: string; begin Result:=FDescription; end; function TEstRequisiteV3.GetKind: TEstRequisiteKind; begin Result:=FKind; end; function TEstRequisiteV3.GetName: string; begin Result:=FName; end; function TEstRequisiteV3.GetValue: string; begin Result:=FValue; end; procedure TEstRequisiteV3.SetDescription(const NewValue: string); begin FDescription:=NewValue; end; procedure TEstRequisiteV3.SetName(const NewValue: string); begin FName:=NewValue; end; procedure TEstRequisiteV3.SetValue(const NewValue: string); begin FValue:=NewValue; end; function TEstRequisiteV3.FromDoc(const PDoc: PDocVariantData): Boolean; var i: Integer; rN, rV, rD: rawUTF8; begin {$IFDEF DEBUG} Assert(PDoc<>nil, 'Параметр не может быть nil'); {$ENDIF} Result := pDoc^.GetAsInteger('k', i) and pDoc^.GetAsRawUtf8('n', rN) and pDoc^.GetAsRawUtf8('v', rV) ; if Result then begin FKind := TEstRequisiteKind(i); FName := Utf8ToString(rN); FValue := Utf8ToString(rV); if pDoc^.GetAsRawUtf8('d', rD) then FDescription := Utf8ToString(rD) else FDescription := ''; end else begin FKind := erkCustom; FName:=''; FValue:=''; FDescription:=''; end; end; function TEstRequisiteV3.ToDoc: Variant; begin Result:=_Obj(['k',Ord(FKind), 'n',StringToUTF8(FName), 'v',StringToUTF8(FValue), 'd',StringToUTF8(FDescription)]); end; function TEstRequisiteV3.ToJSON: RawUTF8; var v: Variant; begin v:=ToDoc; Result:=TDocVariantData(v).ToJSON('','', jsonHumanReadable); end; { TEstRequisitesListV3 } function TEstRequisitesListV3.Add(aRequisite: IEstRequisiteV3): Integer; begin if aRequisite<>nil then begin Result:=Length(FRequisites); SetLength(FRequisites, Result+1); FRequisites[Result]:=aRequisite; end else Result:=-1; end; procedure TEstRequisitesListV3.Clear; var i: Integer; begin for i := Low(FRequisites) to High(FRequisites) do FRequisites[i]:=nil; SetLength(FRequisites,0); end; function TEstRequisitesListV3.CompareNames(const N1, N2: string): Integer; begin Result:=CompareText(N1,N2); end; function TEstRequisitesListV3.Count: Integer; begin Result:=Length(FRequisites); end; constructor TEstRequisitesListV3.Create(const aOptions: TEstListOptions); begin inherited Create; FOptions:=aOptions; SetLength(FRequisites,0); end; destructor TEstRequisitesListV3.Destroy; begin Clear; inherited; end; function TEstRequisitesListV3.GetOptions: TEstListOptions; begin Result:=FOptions; end; function TEstRequisitesListV3.GetRequisite(Index: Integer): IEstRequisiteV3; begin if (Low(FRequisites)<=Index) and (High(FRequisites)>=Index) then Result:=FRequisites[Index] else Result:=nil; end; function TEstRequisitesListV3.GetRequisiteByName(const Name: string; out oRequisite: IEstRequisiteV3): Boolean; var i: Integer; begin i:=IndexByName(Name); if i>=0 then oRequisite:=FRequisites[i] else oRequisite:=nil; Result:=oRequisite<>nil; end; function TEstRequisitesListV3.GetRequisites: TEstRequisiteV3DynArray; begin Result:=FRequisites; end; function TEstRequisitesListV3.IndexByName(const Name: string): Integer; var i: Integer; begin Result:=-2; if Length(FRequisites)<1 then Result:=-1 else for i := Low(FRequisites) to High(FRequisites) do if CompareNames(FRequisites[i].Name, Name)=0 then begin Result:=i; Break; end; end; function TEstRequisitesListV3.isEmpty: Boolean; begin Result:=Length(FRequisites)=0; end; procedure TEstRequisitesListV3.SetOptions(Value: TEstListOptions); begin FOptions:=Value; end; function TEstRequisitesListV3.FromDoc(const PDoc: PDocVariantData): Boolean; var rq: IEstRequisiteV3; a,v: Variant; r: RawUtf8; en: TRttiEnumType; i: Integer; p: PDocVariantData; b:Byte; opt: TEstListOptions absolute b; begin {$IFDEF DEBUG} Assert(PDoc<>nil, 'Параметр не может быть nil'); {$ENDIF} Result:= PDoc^.GetAsInteger('opt',i) and (i>=0) and (i<256) and PDoc^.GetAsDocVariant('Requisite', p) and (p.Kind=dvArray); if Result then begin b:=i; FOptions:=opt; for i := 0 to p^.Count-1 do begin if VarIsEmptyOrNull(p^.Values[i]) then Continue; rq:= TEstRequisiteV3.Create(erkCustom); Result:= rq.FromDoc(p^._[i]) and (Add(rq)>=0); if not Result then Break; end; end; end; function TEstRequisitesListV3.ToDoc: Variant; var b: Byte; rq: IEstRequisiteV3; a,v: Variant; r: RawUtf8; en: TRttiEnumType; begin b:=Byte(FOptions); Result:=_Obj(['opt',b]); if Length(FRequisites)>0 then begin a:=_Arr([]); for rq in FRequisites do begin v:=rq.ToDoc; TDocVariantData(a).AddItem(v); TDocVariantData(v).Clear; end; TDocVariantData(Result).AddValue('Requisite',a); TDocVariantData(a).Clear; end; end; { TEstMethodicLegalV3 } constructor TEstMethodicLegalV3.Create(ADate: TDateTime); var dt,dt0: IEstDateV3; rn,rp: RawUtf8; s: string; begin s:= 'Методика определения сметной стоимости строительства, реконструкции капитального ремонта, ' + 'сноса объектов капитального строительства, работ по сохранению объектов культурного наследия ' + '(памятников истории и культуры) народов Российской Федерации на территории Российской Федерации' ; rn:=StringToUtf8(s); rn:=StringToUtf8('Приказ Минстроя России от 04.08.2020 № 421/пр'); { 3 квартал 2020 : 2 квартал 2022 Приказ Минстроя России от 04.08.2022 N 421/пр 3 квартал 2022 : 4 квартал 2023 Приказ Минстроя России от 07.07.2022 N 557/пр 1 квартал 2024 : 4 квартал 2024 Приказ Минстроя России от 30.01.2024 N 55/пр 1 квартал 2025 : 4 квартал 2025 Приказ Минстроя России от 23.01.2025 N 30/пр 1 квартал 2026 и далее Приказ Минстроя России от 30.01.2026 N 42/пр } dt0:=TEstDateV3.Create(ADate); dt:=TEstDateV3.Create(2026,2,1); // TEstDateV3.CompareQuarters(dt0,dt) if TEstDateV3.CompareQuarters(dt0,dt)>=0 then begin dt:=TEstDateV3.Create(2026,2,10); rp:=StringToUtf8('Приказ Минстроя России от 30.01.2026 N 42/пр'); inherited Create(entGSN, 539, dt, rp, rn); SetIsFederal(True); Exit; end; dt:=TEstDateV3.Create(2025,1,23); if TEstDateV3.CompareQuarters(dt0,dt)>=0 then begin dt:=TEstDateV3.Create(2025,5,5); rp:=StringToUtf8('Приказ Минстроя России от 23.01.2025 N 30/пр'); inherited Create(entGSN, 532, dt, rp, rn); SetIsFederal(True); Exit; end; dt:=TEstDateV3.Create(2024,1,30); if TEstDateV3.CompareQuarters(dt0,dt)>=0 then begin dt:=TEstDateV3.Create(2024,4,4); rp:=StringToUtf8('Приказ Минстроя России от 30.01.2024 N 55/пр'); inherited Create(entGSN, 500, dt, rp, rn); SetIsFederal(True); Exit; end; dt:=TEstDateV3.Create(2022,7,1); if TEstDateV3.CompareQuarters(dt0,dt)>=0 then begin dt:=TEstDateV3.Create(2022,2,9); rp:=StringToUtf8('Приказ Минстроя России от 07.07.2022 N 557/пр'); inherited Create(entGSN, 429, dt, rp, rn); SetIsFederal(True); Exit; end; dt:=TEstDateV3.Create(2020,7,1); if TEstDateV3.CompareQuarters(dt0,dt)>=0 then begin dt:=TEstDateV3.Create(2020,9,29); rp:=StringToUtf8('Приказ Минстроя России от 04.08.2022 N 421/пр'); inherited Create(entGSN, 348, dt, '', rn); SetIsFederal(True); Exit; end; inherited Create; end; { TEstLegalV3 } function TEstLegalV3.AddOrder(const aOrder: RawUtf8): Integer; begin if aOrder='' then Result:=-1 else begin Result:=Length(FOrders); SetLength(FOrders, Result+1); FOrders[Result]:=aOrder; end; end; procedure TEstLegalV3.ClearOrders; begin SetLength(FOrders,0); end; function TEstLegalV3.Count: Integer; begin Result:=Length(FOrders); end; constructor TEstLegalV3.Create; begin inherited Create; SetLength(FOrders,0); FNormType:=entUndefine; FNum:=0; FDate:=EmptyEstDate; FName:=''; end; constructor TEstLegalV3.Create(const aNormType: TEstimateNormativeType; const aNum: Integer; const aDate: IEstDateV3; const aOrders: RawUtf8; const aName: RawUtf8); begin Create; SetNormType(aNormType); SetNum(aNum); SetDate(aDate); SetOrders(aOrders); SetName(aName) end; function TEstLegalV3.GetAddNum: Integer; begin Result:=FAddNum end; function TEstLegalV3.GetDate: IEstDateV3; begin Result:=FDate; end; function TEstLegalV3.GetIsFederal: Boolean; begin Result:=FisFederal; end; function TEstLegalV3.GetName: RawUtf8; begin Result:=FName; end; function TEstLegalV3.GetNormType: TEstimateNormativeType; begin Result:=FNormType; end; function TEstLegalV3.GetNum: Integer; begin Result:=FNum; end; function TEstLegalV3.GetOrder(const Index: Integer): RawUtf8; begin if (Index>=Low(FOrders)) and (Index<=High(FOrders)) then Result:=FOrders[Index] else Result:=''; end; function TEstLegalV3.GetOrders: RawUtf8; var i: Integer; begin if Length(FOrders)<1 then Result:='' else begin Result:=FOrders[0]; for i := Low(FOrders)+1 to High(FOrders) do Result:=Result+EstOrdersSeparator+FOrders[i]; end; end; function TEstLegalV3.GetVersion: RawUtf8; begin Result:=FVersion; end; function TEstLegalV3.isEqual(const Other: IEstLegalV3): Boolean; begin Result:= (Other<>nil) and (Other.NormType=FNormType) and ((Other.Num=FNum) or ((Other.Num=1) and (Other.Name=FName))); end; class function TEstLegalV3.NormTypeS(const aNormType: TEstimateNormativeType): string; begin case aNormType of entGSN: Result:='ГСН'; entOSN: Result:='ОСН'; entTER: Result:='ТЕР'; entISN: Result:='ИСН'; entRef: Result:='Справочник'; entSplit: Result:='Сплит-форма'; entUndefine: Result:=''; end; end; class function TEstLegalV3.NormTypeU(const aNormType: TEstimateNormativeType): RawUtf8; begin Result:=StringToUtf8(NormTypeS(aNormType)); end; procedure TEstLegalV3.SetAddNum(Value: Integer); begin FAddNum:=Value; end; procedure TEstLegalV3.SetDate(Value: IEstDateV3); begin FDate:=Value; end; procedure TEstLegalV3.SetIsFederal(Value: Boolean); begin FisFederal:=Value; end; procedure TEstLegalV3.SetName(Value: RawUtf8); begin FName:=Value; end; procedure TEstLegalV3.SetNormType(Value: TEstimateNormativeType); begin FNormType:=Value; end; procedure TEstLegalV3.SetNum(Value: Integer); begin FNum:=Value; end; procedure TEstLegalV3.SetOrder(const Index: Integer; Value: RawUtf8); begin if (Index>=Low(FOrders)) and (Index<=High(FOrders)) then FOrders[Index]:=Value; end; procedure TEstLegalV3.SetOrders(Value: RawUtf8); var p: PUtf8Char; begin if Value='' then SetLength(FOrders,0) else begin p:=@Value[1]; CsvToRawUtf8DynArray(p,FOrders,EstOrdersSeparator,True); end; end; procedure TEstLegalV3.SetVersion(Value: RawUtf8); begin FVersion:=Value; end; function TEstLegalV3.FromDoc(const PDoc: PDocVariantData): Boolean; var i: Integer; r: RawUtf8; v: Variant; p: PDocVariantData; begin Result:= (PDoc<>nil) and (PDoc^.Kind=dvObject) and PDoc^.GetAsInteger('typ',i) and (i>=0) and (i<=Ord(entUndefine)) and PDoc^.GetAsInteger('num', FNum); if Result then begin FNormType:=TEstimateNormativeType(i); if PDoc^.GetAsRawUtf8('ver', r) then SetVersion(r) else SetVersion(''); if not PDoc^.GetAsInteger('add', FAddNum) then FAddNum:=0; if not PDoc^.GetAsBoolean('fed', FisFederal) then FisFederal:=True; if PDoc^.GetAsDocVariant('dt', p) then Result:=FDate.FromDoc(p); if Result then begin if PDoc^.GetAsRawUtf8('ord', r) then SetOrders(r) else SetOrders(''); if PDoc^.GetAsRawUtf8('nm', r) then SetName(r) else SetName(''); end; end; end; function TEstLegalV3.ToDoc: Variant; var i: Integer; r: RawUtf8; v: Variant; begin r:=PRttiInfo(TypeInfo(TEstimateNormativeType))^.EnumBaseType.GetEnumNameTrimed(FNormType); Result:=_Obj(['typ',Ord(FNormType), 'ntyp',r, 'ver', FVersion, 'num',FNum, 'add',FAddNum, 'fed', FisFederal]); if FDate<>EmptyEstDate then begin v:=FDate.ToDoc; TDocVariantData(Result).AddValue('dt', v); TDocVariantData(v).Clear; end; r:=GetOrders; if r<>'' then TDocVariantData(Result).AddValue('ord', r); if FName<>'' then TDocVariantData(Result).AddValue('nm', FName); end; { TEstNormativesV3 } function TEstNormativesV3.AddIndex(const aIndex: IEstLegalV3): Integer; begin if aIndex=nil then Result:=-1 else if aIndex.NormType=entUndefine then Result:=-2 else begin Result:=Length(FIndexes); SetLength(FIndexes,Result+1); FIndexes[Result]:=aIndex; end; end; function TEstNormativesV3.AddOtherNorm(const aOther: IEstLegalV3): Integer; begin if aOther=nil then Result:=-1 else if aOther.NormType=entUndefine then Result:=-2 else begin Result:=Length(FOthers); SetLength(FOthers,Result+1); FOthers[Result]:=aOther; end; end; function TEstNormativesV3.AddResource(const aResource: IEstLegalV3): Integer; begin if aResource=nil then Result:=-1 else if aREsource.NormType=entUndefine then Result:=-2 else begin Result:=Length(FResources); SetLength(FResources,Result+1); FResources[Result]:=aResource; end; end; procedure TEstNormativesV3.Clear; var i: Integer; begin for i := Low(FIndexes) to High(FIndexes) do FIndexes[i]:=nil; for i := Low(FOthers) to High(FOthers) do FOthers[i]:=nil; for i := Low(FResources) to High(FResources) do FResources[i]:=nil; SetLength(FIndexes,0); SetLength(FResources,0); SetLength(FOthers,0); FMethodics:=EmptyEstLegal; FNorm:=EmptyEstLegal; FProfits:=EmptyEstLegal; FOverheads:=EmptyEstLegal; FSalary:=EmptyEstLegal; end; constructor TEstNormativesV3.Create; begin inherited Create; SetLength(FIndexes,0); SetLength(FResources,0); SetLength(FOthers,0); Clear; end; function TEstNormativesV3.GetIndexes: TEstLegalV3DynArray; begin Result:=FIndexes; end; function TEstNormativesV3.GetIndexNorm(const Index: Integer): IEstLegalV3; begin if (Index>=Low(FIndexes)) and (Index<=High(FIndexes)) then Result:=FIndexes[Index] else Result:=EmptyEstLegal; end; function TEstNormativesV3.GetMethodics: IEstLegalV3; begin Result:=FMethodics; end; function TEstNormativesV3.GetNorm: IEstLegalV3; begin Result:=FNorm; end; function TEstNormativesV3.GetOtherNorm(const Index: Integer): IEstLegalV3; begin if (Index>=Low(FOthers)) and (Index<=High(FOthers)) then Result:=FOthers[Index] else Result:=EmptyEstLegal; end; function TEstNormativesV3.GetOthers: TEstLegalV3DynArray; begin Result:=FOthers; end; function TEstNormativesV3.GetOverheads: IEstLegalV3; begin Result:=FOverheads; end; function TEstNormativesV3.GetProfits: IEstLegalV3; begin Result:=FProfits; end; function TEstNormativesV3.GetResource(const Index: Integer): IEstLegalV3; begin if (Index>=Low(FResources)) and (Index<=High(FResources)) then Result:=FResources[Index] else Result:=EmptyEstLegal; end; function TEstNormativesV3.GetResources: TEstLegalV3DynArray; begin Result:=FResources; end; function TEstNormativesV3.GetSalary: IEstLegalV3; begin Result:=FSalary; end; procedure TEstNormativesV3.SetIndexNorm(const Index: Integer; Value: IEstLegalV3); begin if (Index>=Low(FIndexes)) and (Index<=High(FIndexes)) and (Value<>nil) then FIndexes[Index]:=Value; end; procedure TEstNormativesV3.SetMethodics(Value: IEstLegalV3); begin FMethodics:=Value; end; procedure TEstNormativesV3.SetNorm(Value: IEstLegalV3); begin FNorm:=Value; end; procedure TEstNormativesV3.SetOtherNorm(const Index: Integer; Value: IEstLegalV3); begin if (Index>=Low(FOthers)) and (Index<=High(FOthers)) and (Value<>nil) then FOthers[Index]:=Value; end; procedure TEstNormativesV3.SetOverheads(Value: IEstLegalV3); begin FOverheads:=Value; end; procedure TEstNormativesV3.SetProfits(Value: IEstLegalV3); begin FProfits:=Value; end; procedure TEstNormativesV3.SetResource(const Index: Integer; Value: IEstLegalV3); begin if (Index>=Low(FResources)) and (Index<=High(FResources)) and (Value<>nil) then FResources[Index]:=Value; end; procedure TEstNormativesV3.SetSalary(Value: IEstLegalV3); begin FSalary:=Value; end; function TEstNormativesV3.FindIndex(const aIndex: IEstLegalV3): Integer; var i: Integer; begin Result:=-1; for i := Low(FIndexes) to High(Indexes) do if FIndexes[i].isEqual(aIndex) then begin Result:=i; Break; end; end; function TEstNormativesV3.FromDoc(const PDoc: PDocVariantData): Boolean; var p: PDocVariantData; i: Integer; idx, res,oth: IEstLegalV3; begin Result:= (PDoc<>nil) and (PDoc^.Kind=dvObject) and PDoc^.GetAsDocVariant('main', p) and FNorm.FromDoc(p) and PDoc^.GetAsDocVariant('metd', p) and FMethodics.FromDoc(p) and PDoc^.GetAsDocVariant('ovh', p) and FOverheads.FromDoc(p) and PDoc^.GetAsDocVariant('prf', p) and FProfits.FromDoc(p); if Result and PDoc^.GetAsDocVariant('sal', p) then Result:=FSalary.FromDoc(p); if Result and PDoc^.GetAsDocVariant('idx', p) then begin Result:=p^.Kind=dvArray; if Result and (p^.Count>0) then for i := 0 to p^.Count-1 do begin idx:=TEstLegalV3.Create; Result:=idx.FromDoc(p^._[i]); if Result and (idx.NormType<>entUndefine) then Result:=AddIndex(idx)>=0; if not Result then Break; end; end; if Result and PDoc^.GetAsDocVariant('oth', p) then begin Result:=p^.Kind=dvArray; if Result and (p^.Count>0) then for i := 0 to p^.Count-1 do begin oth:=TEstLegalV3.Create; Result:=oth.FromDoc(p^._[i]); if Result and (oth.NormType<>entUndefine) then Result:=AddOtherNorm(oth)>=0; if not Result then Break; end; end; if Result and PDoc^.GetAsDocVariant('res', p) then begin Result:=p^.Kind=dvArray; if Result and (p^.Count>0) then for i := 0 to p^.Count-1 do begin res:=TEstLegalV3.Create; Result:=res.FromDoc(p^._[i]); if Result and (res.NormType<>entUndefine) then Result:=AddResource(res)>=0; if not Result then Break; end; end; end; function TEstNormativesV3.ToDoc: Variant; var v,a: Variant; i: Integer; begin Result:=_Obj([]); v:=FNorm.ToDoc; TDocVariantData(Result).AddValue('main', v); TDocVariantData(v).Clear; v:=FMethodics.ToDoc; TDocVariantData(Result).AddValue('metd', v); TDocVariantData(v).Clear; v:=FOverheads.ToDoc; TDocVariantData(Result).AddValue('ovh', v); TDocVariantData(v).Clear; v:=FProfits.ToDoc; TDocVariantData(Result).AddValue('prf', v); TDocVariantData(v).Clear; if FSalary.NormType<>entUndefine then begin v:=FSalary.ToDoc; TDocVariantData(Result).AddValue('sal', v); TDocVariantData(v).Clear; end; if Length(FIndexes)>0 then begin a:=_Arr([]); for i := Low(FIndexes) to High(FIndexes) do begin v:=FIndexes[i].ToDoc; TDocVariantData(a).AddItem(v); TDocVariantData(v).Clear; end; TDocVariantData(Result).AddValue('idx',a); end; if Length(FOthers)>0 then begin a:=_Arr([]); for i := Low(FOthers) to High(FOthers) do begin v:=FOthers[i].ToDoc; TDocVariantData(a).AddItem(v); TDocVariantData(v).Clear; end; TDocVariantData(Result).AddValue('oth',a); end; TDocVariantData(a).Clear; if Length(FResources)>0 then begin a:=_Arr([]); for i := Low(FResources) to High(FResources) do begin v:=FResources[i].ToDoc; TDocVariantData(a).AddItem(v); TDocVariantData(v).Clear; end; TDocVariantData(Result).AddValue('res',a); end; TDocVariantData(a).Clear; end; { TEstCompanyV3 } function TEstCompanyV3.GetEmail: RawUtf8; begin Result:=FEmail; end; function TEstCompanyV3.GetFirstname: RawUtf8; begin end; function TEstCompanyV3.GetINN: RawUtf8; begin Result:=FINN; end; function TEstCompanyV3.GetKind: TEstOrganisationKind; begin Result:=FKind; end; function TEstCompanyV3.GetKPP: RawUtf8; begin Result:=FKPP; end; function TEstCompanyV3.GetName: RawUtf8; begin Result:=FName; end; function TEstCompanyV3.GetNote: RawUtf8; begin Result:=FNote; end; function TEstCompanyV3.GetOGRN: RawUtf8; begin Result:=FOGRN; end; function TEstCompanyV3.GetOKPO: RawUtf8; begin Result:=FOKPO; end; function TEstCompanyV3.GetPatronimic: RawUtf8; begin end; function TEstCompanyV3.GetRegion: RawUtf8; begin Result:=FRegion end; function TEstCompanyV3.GetRegionCode: Integer; begin Result:=FRegionCode; end; function TEstCompanyV3.GetSignatures: IEstSignaturesV3; begin Result:=FSignatures; end; function TEstCompanyV3.GetSurname: RawUtf8; begin end; function TEstCompanyV3.GetWebSite: RawUtf8; begin Result:=FWebSite; end; procedure TEstCompanyV3.SetEmail(const Value: RawUtf8); begin FEmail:=Value; end; procedure TEstCompanyV3.SetFirstname(const Value: RawUtf8); begin end; procedure TEstCompanyV3.SetINN(const Value: RawUtf8); begin FInn:=Value; end; procedure TEstCompanyV3.SetKind(const Value: TEstOrganisationKind); begin FKind:=Value; end; procedure TEstCompanyV3.SetKPP(const Value: RawUtf8); begin FKPP:=Value; end; procedure TEstCompanyV3.SetName(const Value: RawUtf8); begin FName:=Value; end; procedure TEstCompanyV3.SetNote(const Value: RawUtf8); begin FNote:=Value; end; procedure TEstCompanyV3.SetOGRN(const Value: RawUtf8); begin FOGRN:=Value; end; procedure TEstCompanyV3.SetOKPO(const Value: RawUtf8); begin FOKPO:=Value; end; procedure TEstCompanyV3.SetPatronimic(const Value: RawUtf8); begin end; procedure TEstCompanyV3.SetRegion(const Value: RawUtf8); begin FRegion:=Value; end; procedure TEstCompanyV3.SetRegionCode(const Value: Integer); begin FRegionCode:=Value; end; procedure TEstCompanyV3.SetSurname(const Value: RawUtf8); begin end; procedure TEstCompanyV3.SetWebSite(const Value: RawUtf8); begin FWebSite:=Value; end; constructor TEstCompanyV3.Create(const aKind: TEstOrganisationKind); begin inherited Create; FKind:=aKind; end; function TEstCompanyV3.FromDoc(const PDoc: PDocVariantData): Boolean; begin end; function TEstCompanyV3.ToDoc: Variant; begin Result:=_Obj(['Kind', Ord(FKind), 'Name', FName, 'Note', FNote, 'INN', FINN, 'KPP',FKPP, 'OKPO', FOKPO, 'Www', FWebSite, 'Region', FRegion, 'RCode', FRegionCode]); end; { TEstRegionV3 } function TEstRegionV3.GetRailwayName: RawUtf8; begin Result:=FRailwayName; end; function TEstRegionV3.GetRegionCode: Integer; begin Result:=FRegionCode; end; function TEstRegionV3.GetRegionName: RawUtf8; begin Result:=FRegionName; end; function TEstRegionV3.GetState: RawUtf8; begin if FRegionCode>0 then Result:=StringToUtf8(rusRosFed) else Result:=FRegionName; end; function TEstRegionV3.GetZoneID: Integer; begin Result:=FZoneID; end; function TEstRegionV3.GetZoneName: RawUtf8; begin Result:=FZoneName; end; var Upper_RF, UPPER_ROS, UPPER_ROSFED: RawUtf8; class function TEstRegionV3.IsRussia(const RName: RawUtf8): Boolean; var r: RawUtf8; begin r:=DBDTextNormalization(RName,dbdTNODefault); Result := (r='') or (r=Upper_RF) or (r=UPPER_ROS) or (r=UPPER_ROSFED); end; function TEstRegionV3.PatchRailwayZone: Boolean; begin end; function TEstRegionV3.PatchRailwayZoneFromUtf8(const Txt: RawUtf8): Boolean; var ri, zi: Integer; r,wn, rn: RawUtf8; i: Integer; ra: TRawUtf8List; begin ra:=TRawUtf8List.Create; try ra.SetText(Txt,'#'); r:=ra[ra.Count-1]; //XXX. Railway: Region if Split(r,':',wn,rn) then begin FRegionName:=rn; ri:=FRegionCode; FRegionCode:=RegionIDByName(RES_RF_REGIONS, FRegionName, True); if FRegionCode=0 then FRegionCode:=ri; FRailwayName:=Utf8ToString(wn); end; finally ra.Free; end; end; function TEstRegionV3.PatchRailwayZoneID: Boolean; begin end; class function TEstRegionV3.RailwayZoneNameByID(const RName: string; const Zone, Subzone: Word; const FromResource: Boolean): string; var r,rz: RawUtf8; ra: TRawUtf8List; i,j: Integer; rr: RawByteString; begin Result:=''; if Zone=0 then Result:='' else if FromResource then begin ResourceToRawByteString(RName, PChar(10), rr); r:=rr; end else begin if FileExists(RName) then r:=StringFromFile(RName) else Result:=''; end; if r<>'' then begin ra:=TRawUtf8List.Create; try ra.Text:=r; if Subzone>0 then rz:=Format('#%3.3d#%3.3d#',[Zone,SubZone]) else rz:=Format('#%3.3d#',[Zone]); r:=''; for i:=0 to ra.Count-1 do begin j:=PosEx(rz,ra[i]); if (j=7) or (j=8) then begin r:=ra[i]; Break; end; end; if r='' then Exit; ra.Clear; ra.SetText(r, '#'); r:=ra[ra.Count-1]; r:=Trim(r); Result:=Utf8ToString(r); finally ra.Free; end; end; end; class function TEstRegionV3.RailwayZoneStr(const RName: string; const Zone, Subzone: Word; const FromResource: Boolean): string; begin Result:=RailwayZoneUTF8(RName,Zone,Subzone,FromResource); end; class function TEstRegionV3.RailwayZoneUTF8(const RName: string; const Zone, Subzone: Word; const FromResource: Boolean): RawUtf8; var r,rz: RawUtf8; ra: TRawUtf8List; i,j: Integer; rr: RawByteString; begin Result:=''; if (Zone=0) or (Subzone=0) then Exit; if FromResource then begin ResourceToRawByteString(RName, PChar(10), rr); r:=rr; end else begin if FileExists(RName) then r:=StringFromFile(RName) else Result:=''; end; if r<>'' then begin ra:=TRawUtf8List.Create; try ra.Text:=r; if Subzone>0 then rz:=Format('#%3.3d#%3.3d#',[Zone,SubZone]) else rz:=Format('#%3.3d#',[Zone]); for i:=0 to ra.Count-1 do begin j:=PosEx(rz,ra[i]); if (j=7) or (j=8) then begin Result:=ra[i]; Break; end; end; finally ra.Free; end; end; end; class function TEstRegionV3.RegionIDByName(const RName, Region: string; const FromResource: Boolean): Integer; var r,rn: RawUtf8; i,l: Integer; rr: RawByteString; ls: TStringList; s,sn, sr: string; begin Result:=0; if RName='' then Result:=-1 else if Region=rusRosFed then Exit else if FromResource then begin ResourceToRawByteString(RName, PChar(10), rr); r:=rr; if r='' then Result:=-4; end else begin if FileExists(RName) then r:=StringFromFile(RName) else Result:=-2; if r='' then Result:=-3; end; if Result=0 then begin rn:=StringToUtf8(Region); rn:=UpperCaseUnicode(rn)+'#'; sn:=Utf8ToString(rn); l:=Length(sn); ls:=TStringList.Create; try sr:=''; ls.Text:=Utf8ToString(r); for i:=0 to ls.Count-1 do begin s:=ls[i]; if (s='') or (s[1]=';') then Continue; s:=AnsiUpperCase(s); if Copy(s,1,l)=sn then begin sr:=Copy(s, l+1, 2); Break; end; end; if sr<>'' then begin Result:=StrToIntDef(sr,0); end; finally ls.Free; end; end; end; class function TEstRegionV3.RegionNameByID(const RCode: Integer): RawUtf8; var r: RawUtf8; rl: TRawUtf8List; i,c: Integer; rr: RawByteString; s: string; sa: TStringDynArray; ra: TRawUtf8DynArray; begin Result:=''; if RCode<=0 then Exit; ResourceToRawByteString(RES_RF_REGIONS, PChar(10), rr); if rr='' then Exit; r:=rr; rl:=TRawUtf8List.Create; try rl.Text:=r; for i:=0 to rl.Count-1 do begin ra:=DBDTextToDynArray(rl[i],'#'); if (Length(ra)<3) then Continue; if ToInteger(ra[1],c) and (c=RCode) then begin Result:=ra[0]; Break; end else if (Int32ToUtf8(rCode)=ra[2]) or (PosEx(','+Int32ToUtf8(rCode), ra[2])>0) then begin Result:=ra[0]; Break; end; end; finally rl.Free; end; end; procedure TEstRegionV3.SetRailwayName(const Value: RawUtf8); begin FRailwayName:=Value; end; procedure TEstRegionV3.SetRegionCode(const Value: Integer); begin FRegionCode:=Value; end; procedure TEstRegionV3.SetRegionName(const Value: RawUtf8); begin FRegionName:=Value; end; procedure TEstRegionV3.SetState(const Value: RawUtf8); begin if not IsRussia(Value) then begin FRegionCode:=0; FRegionName:=Value; end; end; procedure TEstRegionV3.SetZoneID(const Value: Integer); begin FZoneID:=Value; end; procedure TEstRegionV3.SetZoneName(const Value: RawUtf8); begin FZoneName:=Value; end; constructor TEstRegionV3.Create(const RCode: Integer; const RName: RawUtf8); begin inherited Create; FRegionCode:=RCode; if RName<>'' then FRegionName:=RName else if RCode>0 then FRegionName:=RegionNameByID(RCode); FZoneID:=0; FRailwayName:=''; FZoneName:=''; end; function TEstRegionV3.FromDoc(const PDoc: PDocVariantData): Boolean; var wR, wZ: Integer; r: RawUtf8; begin Result:=(PDoc<>nil) and (PDoc^.Kind=dvObject) and (PDoc^.Count>1) and PDoc^.GetAsInteger(RegionIDFieldName, wR) and (wR>=0) and PDoc^.GetAsInteger(ZoneIDFiledName, wZ) and (wZ>=0) ; if Result then begin FRegionCode:=wR; FZoneID:=wZ; if PDoc^.GetAsRawUtf8(RegionNameFieldName, r) then FRegionName:=Utf8ToString(r) else FRegionName:=''; if PDoc^.GetAsRawUtf8(ZoneNameFiledName, r) then FZoneName:=Utf8ToString(r) else FZoneName:=''; if PDoc^.GetAsRawUtf8(RailwayNameFiledName, r) then FRailwayName:=Utf8ToString(r) else FRailwayName:=''; end; end; function TEstRegionV3.ToDoc: Variant; begin Result:=_obj([RegionIDFieldName,FRegionCode, ZoneIDFiledName,FZoneID]); TDocVariantData(Result).AddValue(RegionNameFieldName, StringToUtf8(FRegionName)); TDocVariantData(Result).AddValue(ZoneNameFiledName, StringToUtf8(FZoneName)); TDocVariantData(Result).AddValue(RailwayNameFiledName, StringToUtf8(FRailwayName)); end; class function TEstRegionV3.Utf8RegionNameByID(const RName: RawUtf8; const Region: Word; const FromResource: Boolean): RawUtf8; var r: RawUtf8; ra: TRawUtf8List; i: Integer; rr: RawByteString; s: string; rb: TRawUtf8DynArray; begin Result:=''; if Region=0 then Result:='' else if FromResource then begin ResourceToRawByteString(Utf8ToString(RName), PChar(10), rr); r:=rr; end else begin s:=Utf8ToString(RName); if FileExists(s) then r:=StringFromFile(s) else Result:=''; end; if r<>'' then begin ra:=TRawUtf8List.Create; try ra.Text:=r; for i:=0 to ra.Count-1 do begin r:=ra[i]; if r='' then Continue; SetLength(rb,0); CsvToRawUtf8DynArray(@r[1], rb, '#'); if (Length(rb)>1) and (StrToIntDef(rb[1],0)=Region) then begin Result:=rb[0]; Break; end; end; finally ra.Free; end; end; end; { TEstLinkFilesV3 } function TEstLinkFilesV3.AddLinkFile(const Link: TLinkFile): Integer; begin Result:=AddLinkFile(Link.FileName, Link.PageNo); end; function TEstLinkFilesV3.AddLinkFile(const FileName: TFileName; const PageNo: Integer): Integer; var i: Integer; begin Result:=-1; if FileName='' then Exit; i:=IndexOfFile(FileName); if i<0 then begin i:=Length(FFiles); SetLength(FFiles, i+1); FFiles[i]:=FileName; end; Result:=Length(FPages); SetLength(FPages,Result+1); FPages[Result]:=PageNo; SetLength(FIndexes,Result+1); FIndexes[Result]:=i; end; procedure TEstLinkFilesV3.Clear; begin SetLength(FFiles,0); SetLength(FPages,0); SetLength(FIndexes,0); end; constructor TEstLinkFilesV3.Create; begin inherited; Clear; end; function TEstLinkFilesV3.FileCount: Integer; begin Result:= Length(FFiles); end; function TEstLinkFilesV3.GetFileName(const Index: Integer): TFileName; begin if (Index>=Low(FIndexes)) and (Index<=High(FIndexes)) then Result:=FFiles[Index] else Result:=''; end; function TEstLinkFilesV3.GetLinkFiles: TLinkFileDynArray; var i,j: Integer; begin SetLength(Result, Length(FPages)); for i := Low(FPages) to High(FPages) do begin Result[i].PageNo:=FPages[i]; j:=FIndexes[i]; Result[i].FileName:=GetFileName(j); end end; function TEstLinkFilesV3.IndexOfFile(const FileName: TFileName): Integer; var i: Integer; fn: TFileName; begin fn:=AnsiUpperCase(FileName); Result:=-1; for i := Low(FFiles) to High(FFiles) do if fn=AnsiUpperCase(FFiles[i]) then begin Result:=i; Exit; end; end; function TEstLinkFilesV3.LinkCount: Integer; begin Result:= Length(FPages); end; function TEstLinkFilesV3.FromDoc(const PDoc: PDocVariantData): Boolean; begin end; function TEstLinkFilesV3.ToDoc: Variant; var i: Integer; t:TTVarRecDynArray; a,v: Variant; ar: TRawUtf8DynArray; begin Result:=_Obj(['cntF', Length(FFiles), 'cntL', Length(FIndexes)]); // for i := 0 to High(FFiles) do StringDynArrayToRawUtf8DynArray(FFiles,ar); t:= RawUtf8DynArrayToArrayOfConst(ar); a:=_Arr(t); TDocVariantData(Result).AddValue('files',a); TDocVariantData(a).Clear; for i:=0 to High(FIndexes) do begin v:=_Obj(['i', FIndexes[i], 'p', FPages[i]]); TDocVariantData(a).AddItem(v); TDocVariantData(v).Clear; end; TDocVariantData(Result).AddValue('odxs',a); TDocVariantData(a).Clear; end; { TEstLinkDocumentV3 } function TEstLinkDocumentV3.GetDescription: RawUtf8; begin if IsProps then Result:='' else if FDescriptions.Count<1 then Result:='' else Result:=FDescriptions[0]; end; function TEstLinkDocumentV3.GetDocLinkType: Integer; begin Result:=FLinkType; end; function TEstLinkDocumentV3.GetFileID: Integer; begin Result:=FFileID; end; function TEstLinkDocumentV3.GetFileName: TFileName; begin Result:=FFileName; end; function TEstLinkDocumentV3.GetIfcGUIDs: RawUtf8; begin if isGuids and (FValues.Count>0) then Result:=FValues[0] else Result:=''; end; function TEstLinkDocumentV3.GetIfcPropDescr(const Index: Integer): RawUtf8; begin if isProps and (Index>=0) and (Index<FDescriptions.Count) then Result:=FDescriptions[Index] else Result:=''; end; function TEstLinkDocumentV3.GetIfcPropName(const Index: Integer): RawUtf8; begin if isProps and (Index>=0) and (Index<FNames.Count) then Result:=FNames[Index] else Result:=''; end; function TEstLinkDocumentV3.GetIfcPropValue(const Index: Integer): RawUtf8; begin if isProps and (Index>=0) and (Index<FValues.Count) then Result:=FNames[Index] else Result:=''; end; function TEstLinkDocumentV3.GetName: RawUtf8; begin Result:=FName; end; function TEstLinkDocumentV3.GetPages: RawUtf8; begin if isPages and (FValues.Count>0) then Result:=FValues[0] else Result:=''; end; function TEstLinkDocumentV3.IsGuids: Boolean; begin Result:=FLinkType=1; end; function TEstLinkDocumentV3.IsPages: Boolean; begin Result:=FLinkType=0; end; function TEstLinkDocumentV3.IsProps: Boolean; begin Result:=FLinkType=2; end; function TEstLinkDocumentV3.PropsCount: Integer; begin Result:=FValues.Count; end; procedure TEstLinkDocumentV3.SetDescription(const Value: RawUtf8); begin if FDescriptions.Count>0 then FDescriptions[0]:=Value else FDescriptions.Add(Value); end; procedure TEstLinkDocumentV3.SetFileID(const Value: Integer); begin FFileID:=Value; end; procedure TEstLinkDocumentV3.SetFileName(const Value: TFileName); begin FFileName:=Value; end; procedure TEstLinkDocumentV3.SetIfcGUIDs(const Value: RawUtf8); begin if not isGuids then Exit; if FValues.Count>0 then FValues[0]:=Value else FValues.Add(Value); end; procedure TEstLinkDocumentV3.SetIfcPropDescr(const Index: Integer; const Value: RawUtf8); begin if not IsProps then Exit; if (Index>=0) and (Index<FValues.Count) then FDescriptions[Index]:=Value; end; procedure TEstLinkDocumentV3.SetIfcPropName(const Index: Integer; const Value: RawUtf8); begin if not IsProps then Exit; if (Index>=0) and (Index<FValues.Count) then FNames[Index]:=Value; end; procedure TEstLinkDocumentV3.SetIfcPropValue(const Index: Integer; const Value: RawUtf8); begin if not IsProps then Exit; if (Index>=0) and (Index<FValues.Count) then FValues[Index]:=Value; end; procedure TEstLinkDocumentV3.SetName(const Value: RawUtf8); begin FName:=Value; end; procedure TEstLinkDocumentV3.SetPages(const Value: RawUtf8); begin if not isPages then Exit; if FValues.Count>0 then FValues[0]:=Value else FValues.Add(Value); end; function TEstLinkDocumentV3.AddIfcProp(const APropName, APropValue, APropDescr: RawUtf8): Integer; begin FNames.Add(APropName); FValues.Add(APropValue); FDescriptions.Add(APropDescr); end; constructor TEstLinkDocumentV3.Create(const ALinkType: Integer; const AFileListPtr: Pointer); begin inherited Create; FFileListPtr:=AFileListPtr; FLinkType:=ALinkType; FFileID:=-1; FDescriptions:=TRawUtf8List.Create; FNames:=TRawUtf8List.Create; FValues:=TRawUtf8List.Create; end; constructor TEstLinkDocumentV3.CreateGuids(const AGUIDs, ADescription: RawUtf8; const AFileListPtr: Pointer); begin Create(1, AFileListPtr); SetIfcGUIDs(AGUIDs); SetDescription(ADescription); end; constructor TEstLinkDocumentV3.CreatePages(const APages, ADescription: RawUtf8; const AFileListPtr: Pointer); begin Create(0, AFileListPtr); SetPages(APages); SetDescription(ADescription); end; constructor TEstLinkDocumentV3.CreateProps(const APropName, APropValue, APropDescr: RawUtf8; const AFileListPtr: Pointer); begin Create(2, AFileListPtr); SetIfcPropName(0, APropName); SetIfcPropValue(0, APropValue); SetIfcPropDescr(0, APropDescr); end; destructor TEstLinkDocumentV3.Destroy; begin FDescriptions.Free; FNames.Free; FValues.Free; inherited; end; function TEstLinkDocumentV3.FromDoc(const PDoc: PDocVariantData): Boolean; var n,d,t, fn: RawUtf8; p: PDocVariantData; i: Integer; begin Result:= (PDoc<>nil) and (PDoc^.Kind=dvObject) and (PDoc^.Count>=4) and PDoc^.GetAsInteger('type', FLinkType) and (FLinkType>-1) and (FLinkType<3) and PDoc^.GetAsInteger('fid', FFileID) and (FFileID>0) and PDoc^.GetAsRawUtf8('fnm', fn) and PDoc^.GetAsDocVariant('it', p) and (p<>nil) and (p^.Kind=dvArray) and (p^.Count>0) ; if Result then begin FFileName:=fn; for i := 0 to p^.Count-1 do begin Result:= PDoc^.GetAsRawUtf8('nam', n) and PDoc^.GetAsRawUtf8('val', t) and PDoc^.GetAsRawUtf8('desc', d) ; if Result then begin FValues.Add(t); FDescriptions.Add(d); FNames.Add(d); end; end; end; end; function TEstLinkDocumentV3.ToDoc: Variant; var i: Integer; v,a: Variant; n,d,t, fn: RawUtf8; begin fn:=StringToUtf8(FFileName); Result:=_Obj(['typ', FLinkType, 'fid', FFileID, 'fnm', fn]); a:=_Arr([]); for i:=0 to FValues.Count-1 do begin v:=_Obj(['nam',FNames[i], 'val', FValues[i], 'dsc', FDescriptions[i]]); TDocVariantData(a).AddItem(v); TDocVariantData(v).Clear; end; TDocVariantData(Result).AddValue('it', a); TDocVariantData(a).Clear; end; { TEstLinksV3 } function TEstLinksV3.AddOrUpdateDoc(const ADoc: IEstLinkDocumentV3; const AID: Integer): Integer; var i: Integer; begin Result:=-1; if ADoc=nil then Exit; if FAutoID or (AID<1) then begin // for i:=0 to High(FDocs) do // if FDocs[i].FileName=ADoc.FileName then begin // Result:=i; // FDocs[i]:=ADoc; // Exit; // end; Result:=Length(FDocs); SetLength(FDocs, Result+1); FDocs[Result]:=ADoc; end else begin for i:=0 to High(FDocs) do if FDocs[i].FileID=AID then begin Result:=i; FDocs[i]:=ADoc; Exit; end; Result:=Length(FDocs); SetLength(FDocs, Result+1); FDocs[Result]:=ADoc; FDocs[Result].FileID:=AID; end; end; constructor TEstLinksV3.Create(const AAutoID: Boolean); begin inherited Create; FAutoID:=AAutoID; SetLength(FDocs,0); end; destructor TEstLinksV3.Destroy; begin SetLength(FDocs,0); inherited; end; function TEstLinksV3.GetAutoID: Boolean; begin Result:=FAutoID; end; function TEstLinksV3.GetDoc(const ID: Integer): IEstLinkDocumentV3; var i: Integer; begin Result:=nil; if FAutoID and (Length(FDocs)>=ID) then Result:=FDocs[ID-1] else for i:=Low(FDocs) to High(FDocs) do if FDocs[i].FileID=ID then begin Result:=FDocs[i]; Break; end; end; function TEstLinksV3.GetDocs: TEstLinkDocumentV3DynArray; begin Result:=FDocs; end; function TEstLinksV3.FromDoc(const PDoc: PDocVariantData): Boolean; var d: IEstLinkDocumentV3; v, a: Variant; p: PDocVariantData; i,l: Integer; begin Result := (PDoc<>nil) and (PDoc^.Kind=dvObject) and (PDoc^.Count>=2) and PDoc^.GetAsBoolean('aid', FAutoID) and PDoc^.GetAsDocVariant('docs', p) and (p<>nil) and (p^.Kind=dvArray) ; if not Result then Exit; for i := 0 to p^.Count-1 do begin d:=TEstLinkDocumentV3.Create(0,nil); if d.FromDoc(p) then AddOrUpdateDoc(d,i+1); end; end; function TEstLinksV3.ToDoc: Variant; var d: IEstLinkDocumentV3; v, a: Variant; begin Result:=_Obj(['aid', FAutoID]); a:=_Arr([]); for d in FDocs do begin v:=d.ToDoc; TDocVariantData(a).AddItem(v); TDocVariantData(v).Clear; end; TDocVariantData(Result).AddValue('docs', a); TDocVariantData(a).Clear; end; { TEstWinterRiseV3 } constructor TEstWinterRiseV3.Create(const ACost, AMaterial: Double); begin inherited Create; SetCost(ACost); SetMaterial(AMaterial); end; function TEstWinterRiseV3.GetCost: Double; begin Result:=FCost; end; function TEstWinterRiseV3.GetItemMachines: Double; begin Result:=FItemMachines; end; function TEstWinterRiseV3.GetItemMaterial: Double; begin Result:=FItemMaterial; end; function TEstWinterRiseV3.GetItemOverheads: Double; begin Result:=FItemOverheads; end; function TEstWinterRiseV3.GetItemProfits: Double; begin Result:=FItemProfits; end; function TEstWinterRiseV3.GetItemSalary: Double; begin Result:=FItemSalary; end; function TEstWinterRiseV3.GetMaterial: Double; begin Result:=FMaterial; end; procedure TEstWinterRiseV3.SeItemMaterial(const AValue: Double); begin FItemMaterial:=AValue; end; procedure TEstWinterRiseV3.SetCost(const AValue: Double); begin FCost:=AValue; end; procedure TEstWinterRiseV3.SetItemMachines(const AValue: Double); begin FItemMachines:=AValue; end; procedure TEstWinterRiseV3.SetItemOverheads(const AValue: Double); begin FItemOverheads:=AValue; end; procedure TEstWinterRiseV3.SetItemProfits(const AValue: Double); begin FItemProfits:=AValue; end; procedure TEstWinterRiseV3.SetItemSalary(const AValue: Double); begin FItemSalary:=AValue; end; procedure TEstWinterRiseV3.SetMaterial(const AValue: Double); begin FMaterial:=AValue; end; function TEstWinterRiseV3.FromDoc(const PDoc: PDocVariantData): Boolean; begin Result:= (PDoc<>nil) and PDoc^.GetAsDouble('cost', FCost) and PDoc^.GetAsDouble('mat', FMaterial) and PDoc^.GetAsDouble('isal', FItemSalary) and PDoc^.GetAsDouble('imch', FItemMachines) and PDoc^.GetAsDouble('imat', FItemMaterial) and PDoc^.GetAsDouble('iovh', FItemOverheads) and PDoc^.GetAsDouble('iprf', FItemProfits) ; end; function TEstWinterRiseV3.ToDoc: Variant; begin Result:=_Obj(['cost', FCost, 'mat', FMaterial, 'isal', FItemSalary, 'imch', FItemMachines, 'imat', FItemMaterial, 'iovh', FItemOverheads, 'iprf', FItemProfits]) end; initialization EmptyEstDate:=TEstDateV3.Create(1960,7,2); EmptyEstLegal:=TEstLegalV3.Create; Upper_RF:=StringToUtf8('РФ'); UPPER_ROS:=StringToUtf8('РОССИЯ'); UPPER_ROSFED:=StringToUtf8('РОССИЙСКАЯ ФЕДЕРАЦИЯ'); finalization EmptyEstDate:=nil; EmptyEstLegal:=nil; end.