Jose Pedro 0 Posted September 9, 2020 Report Share Posted September 9, 2020 Caros. a legislaçao AT Angolana implementou a legislaçao semelhante a de Portugal sobre o lincenciamento de softweres de faturaçao Desenvolvi um softwere de faturaçao usando a linguagem Pascal ( Delphi 10.3), ha necesidades de licenciar o mesmo junto a AT, em contrapartida nunca tinha ouvido nada sobre a geraçao de ficheiro saft. alguem ja implementou isso no Delphi preciso de ajuda. Link to post Share on other sites
nunopicado 1,247 Posted September 9, 2020 Report Share Posted September 9, 2020 1 hora atrás, Jose Pedro disse: Caros. a legislaçao AT Angolana implementou a legislaçao semelhante a de Portugal sobre o lincenciamento de softweres de faturaçao Desenvolvi um softwere de faturaçao usando a linguagem Pascal ( Delphi 10.3), ha necesidades de licenciar o mesmo junto a AT, em contrapartida nunca tinha ouvido nada sobre a geraçao de ficheiro saft. alguem ja implementou isso no Delphi preciso de ajuda. Qual a tua dúvida ao certo? Como fazer o ficheiro? "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to post Share on other sites
Jose Pedro 0 Posted September 10, 2020 Author Report Share Posted September 10, 2020 Sim a minha duvida é como construir o ficheiro e extrair os dados do banco Link to post Share on other sites
nunopicado 1,247 Posted September 10, 2020 Report Share Posted September 10, 2020 Para construir um ficheiro SAFT (ou qualquer ficheiro XML) existem várias formas, mas a mais correta é mapear todas as características do ficheiro em um ou mais objetos. Felizmente o Delphi tem uma ferramenta que faz isso de forma automatica. Para isso basta teres o ficheiro XSD correspondente à estrutura do SAFT (aqui) e dentro do Delphi, escolheres criar novo ficheiro e lá dentro escolher a opção XML Data Binding. Seguindo os passos que se apresentam nessa janela, o Delphi irá criar uma unit com um conjunto de objetos que mapeiam o SAFT (aqui). Uma vez criada essa unit, e acrescentada ao teu projeto, usarás de forma semelhante a esta: var SAFT: IXMLAuditFile; begin SAFT := NewAuditFile; // Cria um objeto com a estrutura do SAFT SAFT.Header.CompanyName := 'blablabla'; // Atribui dados ao objeto. SAFT.Header.TaxRegistrationNumber := '555555550'; // Em vez de valores fixos, adicionarias a partir do local onde tenhas esses dados (ficheiro, banco, etc) ... ... ... SAFT.OwnerDocument.SaveToFile('SAFT.XML'); // Grava o resultado final num ficheiro .XML end; Lembrando é claro que tens campos que são arrays. Por exemplo, para adicionar clientes (terás mais do que um, à partida), terias de usar um ciclo FOR ou algo do género a percorrer a tabela de clientes na base de dados, e a adicionar um a um ao ficheiro, tipo isto: for i := 1 to qEntidades.RecordCount do begin qEntidades.RecNo := i; // Percorre a tabela with SAFT.MasterFiles.Customer.Add do // O objeto inclui este método para criar um novo cliente begin { 2. 2. 1. . . } CustomerID := qEntidades.FieldByName('EntidadeID').AsString; { 2. 2. 2. . . } AccountID := 'Desconhecido'; { 2. 2. 3. . . } CustomerTaxID := qEntidades.FieldByName('NIF').AsString; { 2. 2. 4. . . } CompanyName := qEntidades.FieldByName('Nome').AsString; { 2. 2. 6. 3. . } BillingAddress.AddressDetail := StrDefault(qEntidades.FieldByName('Morada').AsString, 'Desconhecido'); { 2. 2. 6. 4. . } BillingAddress.City := StrDefault(qEntidades.FieldByName('City').AsString, 'Desconhecido'); { 2. 2. 6. 5. . } BillingAddress.PostalCode := StrDefault(qEntidades.FieldByName('PostalCode').AsString, 'Desconhecido'); { 2. 2. 6. 7. . } BillingAddress.Country := StrDefault(qEntidades.FieldByName('Country').AsString, 'Desconhecido'); { 2. 2. 8. . . } if not qEntidades.FieldByName('Telefone').IsNull and not qEntidades.FieldByName('Telefone').AsString.IsEmpty then Telephone := qEntidades.FieldByName('Telefone').AsString; { 2. 2. 9. . . } if not qEntidades.FieldByName('Fax').IsNull and not qEntidades.FieldByName('Fax').AsString.IsEmpty then Fax := qEntidades.FieldByName('Fax').AsString; { 2. 2.10. . . } if not qEntidades.FieldByName('Email').IsNull and not qEntidades.FieldByName('Email').AsString.IsEmpty then Email := qEntidades.FieldByName('Email').AsString; { 2. 2.12. . . } SelfBillingIndicator := qEntidades.FieldByName('SelfBillingIndicator').AsInteger; end; end; 1 Report "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to post Share on other sites
Jose Pedro 0 Posted September 10, 2020 Author Report Share Posted September 10, 2020 Muito obrigado pela dica vou começar a criar o mesmo em caso de duvido volto a lhe contactar. Link to post Share on other sites
Jose Pedro 0 Posted September 14, 2020 Author Report Share Posted September 14, 2020 (edited) Caro Nuno a variavel SAFT nao reconhece o paramentro NewAuditFile SAFT := NewAuditFile da erro criei uma unit e fiz o uses da unit que desponibilizaste na unit criada adicionei um buttom(gerar), no evento deste buttom é que criei a variavel, abaixo o metodo empregado. uses; XML procedure TFrmGerar.btnGerarClick(Sender: TObject); var SAFT : IXMLAuditFile; begin SAFT := NewAuditFile; SAFT.Header.AuditFileVersion := '1.04_01'; SAFT.Header.CompanyID := '000484535LA036'; SAFT.Header.TaxRegistrationNumber := '000484535ULA36'; SAFT.Header.TaxAccountingBasis := 'A'; SAFT.Header.CompanyName := 'Kiangy'; SAFT.Header.BusinessName:= 'Comercio_e_Prestaçao_de_Serviço'; SAFT.Header.CompanyAddress:= 'Rua_3_Bairro_Caop_B_Viana'; SAFT.Header.FiscalYear := anoFiscal.Date; SAFT.Header.StartDate := dataInicial.Date; SAFT.Header.EndDate := dataFinal.Date; SAFT.Header.CurrencyCode := 'AO'; SAFT.Header.DateCreated := DateToStr(Date); SAFT.Header.TaxEntity := 'Global'; SAFT.Header.ProductCompanyTaxID := '54173354'; SAFT.Header.SoftwareCertificateNumber := '0/AGT/2020'; SAFT.Header.ProductID := 'AGT/AGT'; SAFT.Header.ProductVersion := '1.1.4'; SAFT.OwnerDocument.SaveToFile('SAFT.XML'); end; Edited September 14, 2020 by nunopicado Syntax Highlight Link to post Share on other sites
nunopicado 1,247 Posted September 14, 2020 Report Share Posted September 14, 2020 NewAuditFile é uma função global na nova unit criada pelo Data Binding. Há 3 funções globais, uma para criar novo, outra para carregar a partir de um ficheiro e uma terceira para carregar a partir de uma variável do tipo IXMLDocument. Terás de adicionar o nome da unit autogerada à unit onde vais usar isso. "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to post Share on other sites
Jose Pedro 0 Posted September 14, 2020 Author Report Share Posted September 14, 2020 ja adicionei a unit autogerada na unit aonde pretendo montar o ficheiro mas mesmo assim a variavel continua nao reconhendo esta funçao Link to post Share on other sites
nunopicado 1,247 Posted September 14, 2020 Report Share Posted September 14, 2020 Tens de verificar na unit quais as funções globais disponíveis. Pode a tua versão do Delphi ter-lhe dado um nome diferente. À partida tens de lá ter 3 funções globais, em que uma delas é para criar um novo ficheiro. NOTA: Ao gerar a unit no XML Data Binding, para o caso específico do SAFT, tens de colocar o visto na opção Document Element Type. A necessidade disto varia consoante o XSD que se está a importar, mas no caso concreto do SAFT, é necessário. Pode ser este o problema, pelo que convém verificar e se for preciso, voltar a importar. "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to post Share on other sites
Jose Pedro 0 Posted September 15, 2020 Author Report Share Posted September 15, 2020 (edited) O problema estava mesmo ao gerar XML Data Binding nao estava a deixar marcado o Document Element Type, ja consegui gerar o ficheiro, vou agora ver como passo os dados do banco ao ficheiro e gostaria tambem de incluir na unit um memo. muito obrigado pela ajuda. Edited September 15, 2020 by Jose Pedro Link to post Share on other sites
Jose Pedro 0 Posted September 15, 2020 Author Report Share Posted September 15, 2020 (edited) Caro Nuno estou com dificuldades de percorre uma tabela referente as compras a fornecedores abaixo o codigo dm.tb_compras.Open(); for I := 1 to dm.tb_compras.RecordCount do begin dm.tb_compras.RecNo := I; with SAFT.SourceDocuments.PurchaseInvoices.Invoice.Add do InvoiceNo := dm.tb_compras.FieldByName('ftnumero').AsString; References Hash SourceID InvoiceDate PurchaseType SupplierID DocumentTotals WithholdingTax end; au passar o paramentros a references da erro. como posso empregar o Hash. Edited September 16, 2020 by nunopicado Syntax Highlight Link to post Share on other sites
nunopicado 1,247 Posted September 16, 2020 Report Share Posted September 16, 2020 Falta-te aí o Begin...End pertencentes ao With. Sem isso, o InvoiceNo é o único que vai bater certo, tudo o resto vai dar erro. 9 horas atrás, Jose Pedro disse: como posso empregar o Hash. Como assim? Já o tens gerado não? É só adicionar ao campo, como fizeste com o InvoiceNo. "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to post Share on other sites
Jose Pedro 0 Posted September 18, 2020 Author Report Share Posted September 18, 2020 Caro Nuno. quanto a tabela de fornecedores ficou resolvido era mesmo a falta do bigin do with. muito obrigo pelo reparo. quanto ao Hash nao consigo compreender em que dados devo gerar o Hash.no meu caso so vou trabalhar com 3 tabelas uma das com as informacoes da empresa, uma tabela de vendas e a utima de compras. sobre a tabela de compras esta concluido, restando apenas o Hash, agora estou com dificuldades de gerar as vendas (SalesInvoices). nao consigo completar tipo "DocumentStatus'', ''Reason'', ''SourceID'', ''Hash'', ''HashControl'', "Period" ,"SourceID", "TransactionID", que informacao devo passar. sera que estou a trabalhar na tag certa sobre vendas? aguardo o teu parecer Link to post Share on other sites
nunopicado 1,247 Posted September 18, 2020 Report Share Posted September 18, 2020 (edited) Só para confirmar, pelo que percebi ainda não estás a gerar o hash para os documentos, é isso? O Hash tem de ser gerado documento a documento. Não estou por dentro da legislação angolana, mas se for semelhante à portuguesa tens de, ao gerar o documento e antes de o imprimires, gerar o hash (especificações para o criar são dadas pela legislação), pois uma parte do hash será impresso no documento, e o hash completo é depois enviado no SAFT. Ou seja, tens de ter algum lugar na base de dados onde guardes o hash na hora de criar o documento. Ao gerar o SAFT depois basta ir buscar a esse campo. Quanto à forma de criar o hash, em PT há uma portaria do governo que determina quais os campos a assinar (o hash é no fundo uma assinatura) e como devem ser encriptados. Para o caso angolano, terás de ver na legislação o que há. Se for igual a PT, poderás encontrar mais info aqui: https://dre.pt/application/conteudo/25703782 Edited September 18, 2020 by nunopicado "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to post Share on other sites
Jose Pedro 0 Posted September 18, 2020 Author Report Share Posted September 18, 2020 A legislaçao é a mesma tanto é que a ASSOFT é que montaram o ficheiro xsd para a AT. vulgo (AGT). se eu percebi toda a factura ou seja documento semelhante antes de ser impresso deve-se criar uma rotina para que gere um Hash que será salvo no Banco de dados? e o Hash Control, no Header.FiscalYear := DateTimeToFileDate(anoFiscal.Date); e o resultado é um numero muito grande aplicando o formatDate('yyyy/mm/dd') da erro. qual é a sequencia. Link to post Share on other sites
nunopicado 1,247 Posted September 18, 2020 Report Share Posted September 18, 2020 (edited) 2 horas atrás, Jose Pedro disse: se eu percebi toda a factura ou seja documento semelhante antes de ser impresso deve-se criar uma rotina para que gere um Hash que será salvo no Banco de dados? Isso mesmo. 2 horas atrás, Jose Pedro disse: e o Hash Control, no Header.FiscalYear := DateTimeToFileDate(anoFiscal.Date); e o resultado é um numero muito grande aplicando o formatDate('yyyy/mm/dd') da erro. qual é a sequencia. Não percebi... O HashControl é o número de versão da chave privada usada para criar o hash. Geralmente será simplesmente '1'. Há casos excepcionais, como faturas recuperadas e/ou de outros programas, em que o HashControl é acrescentado de outros valores, mas geralmente é só mesmo um dígito. FiscalYear é somente o ano a que diz respeito o SAFT. Um SAFT deste mês teria o FiscalYear = 2020. São dois campos separados, completamente distintos um do outro. Tens aqui um SAFT de exemplo, para verificares mais ou menos como são os campos: <?xml version="1.0"?> <AuditFile xmlns="urn:OECD:StandardAuditFile-Tax:PT_1.04_01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:OECD:StandardAuditFile-Tax:PT_1.04_01 SAF-T-PT.XSD" xmlns:doc="urn:schemas-basda-org:schema-extensions:documentation"> <Header> <AuditFileVersion>1.04_01</AuditFileVersion> <CompanyID>555555550</CompanyID> <TaxRegistrationNumber>555555550</TaxRegistrationNumber> <TaxAccountingBasis>F</TaxAccountingBasis> <CompanyName>Loja Das Coisas Que Se Vendem</CompanyName> <BusinessName>Loja Das Coisas Que Se Vendem LDA</BusinessName> <CompanyAddress> <AddressDetail>Cascos de Rolha</AddressDetail> <City>Fim do Mundo</City> <PostalCode>9999-000</PostalCode> <Region>Crosta Terrestre</Region> <Country>PT</Country> </CompanyAddress> <FiscalYear>2020</FiscalYear> <StartDate>2020-08-01</StartDate> <EndDate>2020-08-31</EndDate> <CurrencyCode>EUR</CurrencyCode> <DateCreated>2020-09-14</DateCreated> <TaxEntity>Loja</TaxEntity> <ProductCompanyTaxID>555555550</ProductCompanyTaxID> <SoftwareCertificateNumber>0000</SoftwareCertificateNumber> <ProductID>Programa Bom Que Tira Faturas</ProductID> <ProductVersion>1.0</ProductVersion> <Telephone>210555666</Telephone> <Fax>210555777</Fax> <Email>bate@porta.pt</Email> </Header> <MasterFiles> <Customer> <CustomerID>1</CustomerID> <AccountID>Desconhecido</AccountID> <CustomerTaxID>999999990</CustomerTaxID> <CompanyName>Consumidor Final</CompanyName> <BillingAddress> <AddressDetail>Desconhecido</AddressDetail> <City>Desconhecido</City> <PostalCode>0000-000</PostalCode> <Country>PT</Country> </BillingAddress> <SelfBillingIndicator>0</SelfBillingIndicator> </Customer> <TaxTable> <TaxTableEntry> <TaxType>IVA</TaxType> <TaxCountryRegion>PT</TaxCountryRegion> <TaxCode>ISE</TaxCode> <Description>Isenta Artigo 9.º do CIVA</Description> <TaxPercentage>0</TaxPercentage> </TaxTableEntry> <TaxTableEntry> <TaxType>IVA</TaxType> <TaxCountryRegion>PT</TaxCountryRegion> <TaxCode>ISE</TaxCode> <Description>Isenta Regime Particular do Tabaco</Description> <TaxPercentage>0</TaxPercentage> </TaxTableEntry> <TaxTableEntry> <TaxType>IVA</TaxType> <TaxCountryRegion>PT</TaxCountryRegion> <TaxCode>RED</TaxCode> <Description>Reduzida </Description> <TaxPercentage>6</TaxPercentage> </TaxTableEntry> <TaxTableEntry> <TaxType>IVA</TaxType> <TaxCountryRegion>PT</TaxCountryRegion> <TaxCode>INT</TaxCode> <Description>Intermédia </Description> <TaxPercentage>13</TaxPercentage> </TaxTableEntry> <TaxTableEntry> <TaxType>IVA</TaxType> <TaxCountryRegion>PT</TaxCountryRegion> <TaxCode>NOR</TaxCode> <Description>Normal </Description> <TaxPercentage>23</TaxPercentage> </TaxTableEntry> </TaxTable> </MasterFiles> <SourceDocuments> <SalesInvoices> <NumberOfEntries>1</NumberOfEntries> <TotalDebit>0.00</TotalDebit> <TotalCredit>2.83</TotalCredit> <Invoice> <InvoiceNo>FR AM1/2609</InvoiceNo> <ATCUD>0</ATCUD> <DocumentStatus> <InvoiceStatus>N</InvoiceStatus> <InvoiceStatusDate>2020-08-18T16:54:29</InvoiceStatusDate> <SourceID>Zé Trabalhador</SourceID> <SourceBilling>P</SourceBilling> </DocumentStatus> <Hash>UWHDsjo8eZHNs1HhqcHFGR0TPd/rrzWHwTjTF3UalC4rCsPUEzu3PjD/M8wY8e891lvkU6Yc76/gVcfnY1NZlrOt2n1H6bIVNNKFfsIMddvYMBekggoukbMMwy0JdCSgBx2YDrMKYJzFWxPF4eD34nvJuvXL+QeXr2pF0S1D9zk=</Hash> <HashControl>1</HashControl> <Period>8</Period> <InvoiceDate>2020-08-18</InvoiceDate> <InvoiceType>FR</InvoiceType> <SpecialRegimes> <SelfBillingIndicator>0</SelfBillingIndicator> <CashVATSchemeIndicator>0</CashVATSchemeIndicator> <ThirdPartiesBillingIndicator>0</ThirdPartiesBillingIndicator> </SpecialRegimes> <SourceID>Zé Trabalhador</SourceID> <SystemEntryDate>2020-08-18T16:54:29</SystemEntryDate> <CustomerID>1</CustomerID> <Line> <LineNumber>1</LineNumber> <ProductCode>20</ProductCode> <ProductDescription>Tele Novelas</ProductDescription> <Quantity>1</Quantity> <UnitOfMeasure>Un</UnitOfMeasure> <UnitPrice>0.0000000000</UnitPrice> <TaxPointDate>2020-08-18</TaxPointDate> <Description>Tele Novelas</Description> <CreditAmount>0.0000000000</CreditAmount> <Tax> <TaxType>IVA</TaxType> <TaxCountryRegion>PT</TaxCountryRegion> <TaxCode>RED</TaxCode> <TaxPercentage>6</TaxPercentage> </Tax> </Line> <Line> <LineNumber>2</LineNumber> <ProductCode>14</ProductCode> <ProductDescription>Visão</ProductDescription> <Quantity>1</Quantity> <UnitOfMeasure>Un</UnitOfMeasure> <UnitPrice>2.8301886792</UnitPrice> <TaxPointDate>2020-08-18</TaxPointDate> <Description>Visão</Description> <CreditAmount>2.8301886792</CreditAmount> <Tax> <TaxType>IVA</TaxType> <TaxCountryRegion>PT</TaxCountryRegion> <TaxCode>RED</TaxCode> <TaxPercentage>6</TaxPercentage> </Tax> </Line> <DocumentTotals> <TaxPayable>0.17</TaxPayable> <NetTotal>2.83</NetTotal> <GrossTotal>3.00</GrossTotal> <Payment> <PaymentMechanism>NU</PaymentMechanism> <PaymentAmount>3.00</PaymentAmount> <PaymentDate>2020-08-18</PaymentDate> </Payment> </DocumentTotals> </Invoice> </SalesInvoices> <Payments> <NumberOfEntries>1</NumberOfEntries> <TotalDebit>0.00</TotalDebit> <TotalCredit>5.27</TotalCredit> <Payment> <PaymentRefNo>RC AM1/35</PaymentRefNo> <ATCUD>RC AM1/35</ATCUD> <Period>8</Period> <TransactionDate>2020-08-18</TransactionDate> <PaymentType>RG</PaymentType> <Description>Recibo RC AM1/35</Description> <SystemID>56350</SystemID> <DocumentStatus> <PaymentStatus>N</PaymentStatus> <PaymentStatusDate>2020-08-18T15:38:49</PaymentStatusDate> <SourceID>Zé Trabalhador</SourceID> <SourcePayment>P</SourcePayment> </DocumentStatus> <SourceID>Zé Trabalhador</SourceID> <SystemEntryDate>2020-08-18T15:38:49</SystemEntryDate> <CustomerID>2</CustomerID> <Line> <LineNumber>1</LineNumber> <SourceDocumentID> <OriginatingON>FT AM1/395</OriginatingON> <InvoiceDate>2020-08-18</InvoiceDate> <Description>FT AM1/395 - 6%</Description> </SourceDocumentID> <CreditAmount>2.83</CreditAmount> </Line> <Line> <LineNumber>2</LineNumber> <SourceDocumentID> <OriginatingON>FT AM1/395</OriginatingON> <InvoiceDate>2020-08-18</InvoiceDate> <Description>FT AM1/395 - 23%</Description> </SourceDocumentID> <CreditAmount>2.44</CreditAmount> </Line> <DocumentTotals> <TaxPayable>0.73</TaxPayable> <NetTotal>5.27</NetTotal> <GrossTotal>6.00</GrossTotal> </DocumentTotals> </Payment> </Payments> </SourceDocuments> </AuditFile> Tens também no forum um tópico exclusivamente dedicado ao SAFT, onde tens muita informação que te poderá ajudar: https://www.portugal-a-programar.pt/forums/topic/57541-saft-pt-debate-de-dúvidas-e-ideias/?tab=comments#comment-484754 Edited September 18, 2020 by nunopicado "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum. Link to post Share on other sites
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now