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.