Created
October 23, 2025 21:38
-
-
Save Al-Muhandis/4ccea5793ef0e3b2ed4ac6df2d32abbc to your computer and use it in GitHub Desktop.
Revisions
-
Al-Muhandis created this gist
Oct 23, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,186 @@ unit invoice_pdf; {$mode objfpc}{$H+} interface uses Classes, SysUtils, fppdf, cmn_globals ; type { TInvoicePDFGenerator } TInvoicePDFGenerator = class private FCurrency: String; FFontFilePath: String; FFontName: String; FPayeeBankBIC: Int64; FPayeeBankName: String; FPayeeINN: Int64; FPayeeKPP: Int64; FPayerEmail: String; FPayerINN: String; FPayerKPP: String; FPayerName: String; FPayerPhone: String; FPayerTypeEnum: TPayerType; FPrice: Integer; FAcc, FCorrAcc: String; FDocNum: Integer; FPayeeName: String; FPaymentName: String; FPage: TPDFPage; FXBlockIndent, FXBlockIndent2: Integer; FY: Integer; procedure DrawLine(X, Y, L: Integer); function GetPayerType: String; procedure SetPayerType(AValue: String); procedure WriteText(X, Y: Integer; const S: string; aFont, aSize: Integer); procedure WriteBigText(X, Y: Integer; const S: string; aFont: Integer); procedure WriteSmallText(X, Y: Integer; const S: string; aFont: Integer); procedure WriteInfoBlockWithLine(const aInfoValue, aInfoName: String; aFont: Integer); procedure WriteInfoBlockWithLine(const aInfoValue1, aInfoName1, aInfoValue2, aInfoName2: String; aFont: Integer); public function Generate: TMemoryStream; property DocNum: Integer read FDocNum write FDocNum; property PayeeName: String read FPayeeName write FPayeeName; property PayeeINN: Int64 read FPayeeINN write FPayeeINN; property PayeeKPP: Int64 read FPayeeKPP write FPayeeKPP; property PayeeBankName: String read FPayeeBankName write FPayeeBankName; property PayeeBankBIC: Int64 read FPayeeBankBIC write FPayeeBankBIC; property PaymentName: String read FPaymentName write FPaymentName; property PayerType: String read GetPayerType write SetPayerType; property PayerTypeEnum: TPayerType read FPayerTypeEnum write FPayerTypeEnum; property PayerName: String read FPayerName write FPayerName; property PayerEmail: String read FPayerEmail write FPayerEmail; property PayerPhone: String read FPayerPhone write FPayerPhone; property PayerINN: String read FPayerINN write FPayerINN; property PayerKPP: String read FPayerKPP write FPayerKPP; property PayeeBankCorrAcc: String read FCorrAcc write FCorrAcc; property PayeeBankAcc: String read FAcc write FAcc; property Price: Integer read FPrice write FPrice; property Currency: String read FCurrency write FCurrency; property FontFilePath: String read FFontFilePath write FFontFilePath; property FontName: String read FFontName write FFontName; end; function InvoiceFullID(const aText: String; aDocNum: Integer; aDate: TDate): String; implementation function InvoiceFullID(const aText: String; aDocNum: Integer; aDate: TDate): String; begin Result:=Format(aText, [aDocNum, FormatDateTime('dd.mm.yyyy', aDate)]); end; { TInvoicePDFGenerator } procedure TInvoicePDFGenerator.DrawLine(X, Y, L: Integer); begin FPage.MoveTo(X, Y); FPage.DrawLine(X,Y, x+L, Y, 0.5, False); FPage.StrokePath; end; function TInvoicePDFGenerator.GetPayerType: String; begin Result:=PayerTypeToString(FPayerTypeEnum); end; procedure TInvoicePDFGenerator.SetPayerType(AValue: String); begin FPayerTypeEnum:=StringToPayerType(AValue); end; procedure TInvoicePDFGenerator.WriteText(X, Y: Integer; const S: string; aFont, aSize: Integer); begin FPage.SetFont(aFont, aSize); FPage.WriteText(X, Y, S); end; procedure TInvoicePDFGenerator.WriteBigText(X, Y: Integer; const S: string; aFont: Integer); begin WriteText(X, Y, S, aFont, 12); end; procedure TInvoicePDFGenerator.WriteSmallText(X, Y: Integer; const S: string; aFont: Integer); begin WriteText(X, Y, S, aFont, 9); end; procedure TInvoicePDFGenerator.WriteInfoBlockWithLine(const aInfoValue, aInfoName: String; aFont: Integer); begin WriteBigText(FXBlockIndent, FY, aInfoValue, aFont); FY -= 2; DrawLine(FXBlockIndent, FY, 140); FY -= 3; WriteSmallText(FXBlockIndent+5, FY, aInfoName, aFont); FY -= 8; end; procedure TInvoicePDFGenerator.WriteInfoBlockWithLine(const aInfoValue1, aInfoName1, aInfoValue2, aInfoName2: String; aFont: Integer); begin WriteBigText(FXBlockIndent, FY, aInfoValue1, aFont); WriteBigText(FXBlockIndent2, FY, aInfoValue2, aFont); FY -= 2; DrawLine(FXBlockIndent, FY, 60); DrawLine(FXBlockIndent2, FY, 60); FY -= 3; WriteSmallText(FXBlockIndent+5, FY, aInfoName1, aFont); WriteSmallText(FXBlockIndent2+5, FY, aInfoName2, aFont); FY -= 8; end; function TInvoicePDFGenerator.Generate: TMemoryStream; var aDoc: TPDFDocument; aFont: Integer; aSection: TPDFSection; InvoiceNo, aInvoiceNum: string; begin Result := TMemoryStream.Create; aDoc := TPDFDocument.Create(nil); try aDoc.StartDocument; aSection := aDoc.Sections.AddSection; FPage := aDoc.Pages.AddPage; aSection.AddPage(FPage); if FFontFilePath.IsEmpty then aFont := aDoc.AddFont(FFontName) else aFont := aDoc.AddFont(FFontFilePath, FFontName); FY := Round(FPage.GetPaperHeight) - 10; InvoiceNo := InvoiceFullID('Счет на оплату № %d от %s г.', DocNum, Date); WriteBigText(40, FY, InvoiceNo, aFont); FY -= 16; FXBlockIndent:=40; FXBlockIndent2:=120; WriteInfoBlockWithLine(PayeeBankName, 'Банк получателя', aFont); WriteInfoBlockWithLine(PayeeBankBIC.ToString, 'БИК банка получателя', PayeeBankCorrAcc, 'Номер корр.счета банка получателя', aFont); WriteInfoBlockWithLine(PayeeINN.ToString, 'ИНН получателя', PayeeKPP.ToString, 'КПП получателя', aFont); WriteInfoBlockWithLine(PayeeBankAcc, 'Счет получателя платежа', aFont); WriteInfoBlockWithLine(PayeeName, 'Получатель платежа', aFont); aInvoiceNum:=Format(PaymentName, [InvoiceFullID('№ %d от %s г.', DocNum, Date)]); WriteInfoBlockWithLine(aInvoiceNum, 'Наименование платежа', aFont); FY -= 8; WriteBigText(FXBlockIndent+40, FY, Format('Сумма платежа: %s', [CurrencyToStr(FPrice, FCurrency)]), aFont); FY -= 8; WriteBigText(FXBlockIndent+40, FY, 'НДС не облагается', aFont); FY -= 8; FY -= 8; WriteBigText(FXBlockIndent+5, FY, 'Плательщик: ' + PayerName, aFont); FY -= 8; if FPayerTypeEnum=pteEntity then begin WriteBigText(FXBlockIndent+5, FY, 'ИНН плательщика: ' + PayerINN, aFont); FY -= 8; WriteBigText(FXBlockIndent+5, FY, 'КПП плательщика: ' + PayerKPP, aFont); FY -= 8; end; WriteBigText(FXBlockIndent+5, FY, 'Email: ' + PayerEmail, aFont); WriteBigText(FXBlockIndent2+5, FY, 'Тел.: +' + PayerPhone, aFont); FY -= 12; aDoc.SaveToStream(Result); finally aDoc.Free; end; Result.Position := 0; end; end.