diff --git a/febraban/cnab240/itau/charge/file/header.py b/febraban/cnab240/itau/charge/file/header.py index 53b74ed..589b293 100644 --- a/febraban/cnab240/itau/charge/file/header.py +++ b/febraban/cnab240/itau/charge/file/header.py @@ -1,3 +1,4 @@ +from datetime import datetime from ....row import Row from ....characterType import numeric, alphaNumeric @@ -15,10 +16,13 @@ def defaultValues(self): ] self.content = Row.setStructs(structs=structs, content=self.content) - def setGeneratedFileDate(self, datetime): + def setGeneratedFileDate(self, dateAndTime): + if dateAndTime is None: + dateAndTime = datetime.now() + structs = [ - (143, 151, 8, numeric, datetime.strftime("%d%m%Y")), # Dia que o arquivo foi gerado - (151, 157, 6, numeric, datetime.strftime("%H%M%S")), # Horario que o arquivo foi gerado + (143, 151, 8, numeric, dateAndTime.strftime("%d%m%Y")), # Dia que o arquivo foi gerado + (151, 157, 6, numeric, dateAndTime.strftime("%H%M%S")), # Horario que o arquivo foi gerado ] self.content = Row.setStructs(structs=structs, content=self.content) diff --git a/febraban/cnab240/itau/charge/file/headerLot.py b/febraban/cnab240/itau/charge/file/headerLot.py index 14f74d3..9a54502 100644 --- a/febraban/cnab240/itau/charge/file/headerLot.py +++ b/febraban/cnab240/itau/charge/file/headerLot.py @@ -1,3 +1,4 @@ +from datetime import datetime from ....row import Row from ....characterType import numeric, alphaNumeric @@ -18,10 +19,13 @@ def defaultValues(self): ] self.content = Row.setStructs(structs=structs, content=self.content) - def setGeneratedFileDate(self, datetime): + def setGeneratedFileDate(self, dateAndTime): + if dateAndTime is None: + dateAndTime = datetime.now() + structs = [ - (191, 199, 8, numeric, datetime.strftime("%d%m%Y")), # Data de gravacao - (199, 207, 8, numeric, datetime.strftime("%d%m%Y")), # Data de credito + (191, 199, 8, numeric, dateAndTime.strftime("%d%m%Y")), # Data de gravacao + (199, 207, 8, numeric, dateAndTime.strftime("%d%m%Y")), # Data de credito ] self.content = Row.setStructs(structs=structs, content=self.content) diff --git a/febraban/cnab240/itau/charge/result/parser.py b/febraban/cnab240/itau/charge/result/parser.py index 7565c58..19cd106 100644 --- a/febraban/cnab240/itau/charge/result/parser.py +++ b/febraban/cnab240/itau/charge/result/parser.py @@ -7,6 +7,7 @@ class SlipResponseStatus: registered = "registered" paid = "paid" canceled = "canceled" + updated = "updated" overdue = "overdue" failed = "failed" unknown = "unknown" @@ -34,6 +35,8 @@ def status(self): return SlipResponseStatus.paid if self.occurrence == "09": return SlipResponseStatus.canceled + if self.occurrence in ["04", "14"]: + return SlipResponseStatus.updated return SlipResponseStatus.unknown def contentText(self, breakLine="\n"): diff --git a/febraban/cnab240/itau/charge/slip/segmentP.py b/febraban/cnab240/itau/charge/slip/segmentP.py index 420c364..1130d0e 100644 --- a/febraban/cnab240/itau/charge/slip/segmentP.py +++ b/febraban/cnab240/itau/charge/slip/segmentP.py @@ -90,3 +90,27 @@ def setOverdueLimit(self, overdueLimit): (224, 226, 2, numeric, overdueLimit), # Quantidade de dias após o vencimento para baixa automática ] self.content = Row.setStructs(structs=structs, content=self.content) + + def setNullValues(self): + structs = [ + (109, 117, 8, numeric, "0"), # Data de emissao do boleto nula + (77, 85, 8, numeric, "0"), # Data de vencimento do boleto nula + (223, 224, 1, numeric, "0"), + (224, 226, 2, numeric, "0"), # Quantidade de dias após o vencimento nulo + ] + self.content = Row.setStructs(structs=structs, content=self.content) + + def setOccurrence(self, occurence): + structs = [ + (15, 17, 2, numeric, occurence) + + ] + self.content = Row.setStructs(structs=structs, content=self.content) + + def chargeUpdateDueDate(self, dueDate): + self.setNullValues() + structs = [ + (15, 17, 2, numeric, "06"), # Indica alteracao + (77, 85, 8, numeric, dueDate), # Alteracao vencimento + ] + self.content = Row.setStructs(structs=structs, content=self.content) diff --git a/febraban/cnab240/itau/charge/slip/segmentQ.py b/febraban/cnab240/itau/charge/slip/segmentQ.py index e9f6ad7..d88b52f 100644 --- a/febraban/cnab240/itau/charge/slip/segmentQ.py +++ b/febraban/cnab240/itau/charge/slip/segmentQ.py @@ -55,8 +55,28 @@ def setPayerAddress(self, address): def setGuarantor(self, user): structs = [ - (153, 154, 1, numeric, "1" if len(user.identifier) == 11 else "2"), # 1 - CPF/ 2 - CNPJ - (154, 169, 15, numeric, user.identifier), # CPF/CNPJ do Sacador Avalista - (169, 199, 30, alphaNumeric, user.name) # Nome do Sacador Avalista + (153, 154, 1, numeric, "1" if len(user.identifier) == 11 else "2"), # 1 - CPF/ 2 - CNPJ + (154, 169, 15, numeric, user.identifier), # CPF/CNPJ do Sacador Avalista + (169, 199, 30, alphaNumeric, user.name) # Nome do Sacador Avalista + ] + self.content = Row.setStructs(structs=structs, content=self.content) + + def setNullValues(self): + structs = [ + (17, 18, 1, numeric, "0"), # 1 - CPF/ 2 - CNPJ nulo + (18, 33, 15, numeric, "0"), # CPF/CNPJ do Pagador nulo + (33, 63, 30, alphaNumeric, " "), # Nome do Pagador nulo + (73, 113, 40, alphaNumeric, " "), # Endereco pagador nulo + (113, 128, 15, alphaNumeric, " "), + (128, 136, 8, numeric, "0"), + (136, 151, 15, alphaNumeric, " "), + (151, 153, 2, alphaNumeric, " ") + ] + self.content = Row.setStructs(structs=structs, content=self.content) + + def setOccurrence(self, occurence): + structs = [ + (15, 17, 2, numeric, occurence) + ] self.content = Row.setStructs(structs=structs, content=self.content) diff --git a/febraban/cnab240/itau/charge/slip/segmentR.py b/febraban/cnab240/itau/charge/slip/segmentR.py index 9ea74d3..bbbe91d 100644 --- a/febraban/cnab240/itau/charge/slip/segmentR.py +++ b/febraban/cnab240/itau/charge/slip/segmentR.py @@ -44,3 +44,9 @@ def setFine(self, date, fine): ] self.content = Row.setStructs(structs=structs, content=self.content) + def setOccurrence(self, ocurrence): + structs = [ + (15, 17, 2, numeric, ocurrence), + ] + self.content = Row.setStructs(structs=structs, content=self.content) + diff --git a/febraban/cnab240/itau/charge/slip/slip.py b/febraban/cnab240/itau/charge/slip/slip.py index 294fbc4..e8c6128 100644 --- a/febraban/cnab240/itau/charge/slip/slip.py +++ b/febraban/cnab240/itau/charge/slip/slip.py @@ -41,7 +41,10 @@ def setExpirationDate(self, datetime): self.segmentP.setExpirationDate(datetime.strftime("%d%m%Y")) def setIssueDate(self, datetime): - self.segmentP.setIssueDate(datetime.strftime("%d%m%Y")) + date = "00000000" + if datetime is not None: + date = datetime.strftime("%d%m%Y") + self.segmentP.setIssueDate(date) def setBankIdentifier(self, identifier, branch, accountNumber, wallet): dac = DAC.calculate( @@ -66,3 +69,15 @@ def setCancel(self): self.segmentP.setCancel() self.segmentQ.setCancel() self.segmentR.setCancel() + + def chargeUpate(self, amount=None, dueDate=None): + if amount: + self.segmentP.setOccurrence(occurence="31") + self.segmentP.setNullValues() + self.segmentP.setAmountInCents(amount=amount) + self.segmentQ.setNullValues() + if dueDate: + self.segmentP.setNullValues() + self.segmentP.setOccurrence(occurence="06") + self.segmentP.chargeUpdateDueDate(dueDate.strftime("%d%m%Y")) + self.segmentQ.setNullValues() diff --git a/febraban/cnab240/tests/itau/charge/updateTest.py b/febraban/cnab240/tests/itau/charge/updateTest.py new file mode 100644 index 0000000..4170ea1 --- /dev/null +++ b/febraban/cnab240/tests/itau/charge/updateTest.py @@ -0,0 +1,166 @@ +from unittest.case import TestCase +from febraban.cnab240.itau.charge import SegmentP, SegmentQ, SegmentR +from febraban.cnab240.user import User, UserBank, UserAddress +from febraban.cnab240.itau.charge import Slip, File +from datetime import datetime, timedelta + +orignalDate = datetime(day=20, month=07, year=2019) +now = datetime.now() +expiration = now + timedelta(days=1) + +bank = UserBank( + bankId="341", + branchCode="1234", + accountNumber="1234567", + accountVerifier="8" +) + +address = UserAddress( + streetLine1="AV PAULISTA 1000", + city="SAO PAULO", + stateCode="SP", + zipCode="01310000" +) + +payer = User( + name="ARYA STARK", + identifier="12345678901", + address=UserAddress( + streetLine1="AV PAULISTA 1234", + district="BELA VISTA", + city="SAO PAULO", + stateCode="SP", + zipCode="01348002" + ) +) + +guarantor = User( + name="SACADOR", + identifier="09876543210", + bank=UserBank( + bankId="341", + branchCode="7307", + accountNumber="14446", + accountVerifier="4", + bankName="BANCO ITAU SA" + ), + address=UserAddress( + streetLine1="AV PAULISTA 1000", + streetLine2="CJ 601", + city="SAO PAULO", + stateCode="SP", + zipCode="01310000" + ) +) + + +class UpdateTest(TestCase): + + def testSegmentPlengh(self): + string = SegmentP().content + self.assertEqual(len(string), 240) + + def testSegmentPdefaultValues(self): + content = SegmentP().content + self.assertEqual(content[3:7], "0001") + self.assertEqual(content[7:8], "3") + self.assertEqual(content[13:14], "P") + self.assertEqual(content[15:17], "01") + self.assertEqual(content[37:40], "109") + self.assertEqual(content[106:108], "99") + self.assertEqual(content[108:109], "A") + + def testSegmentPsets(self): + segment = SegmentP() + segment.setPositionInLot(1) + segment.setSenderBank(bank) + segment.setAmountInCents(22500) + segment.setExpirationDate("14062019") + segment.setIssueDate("12062019") + segment.setBankIdentifier(identifier="99999", dac="7") + segment.setIdentifier("VITAO") + segment.setOverdueLimit(overdueLimit=59) + print(segment.content) + response = "3410001300001P 0101234 000001234567 8109000999997 00000 1406201900000000002250000000099A12062019000000000000000000000000000000000000000000000000000000000000000000000000000000VITAO 0001590000000000000 " + self.assertEquals(segment.content, response) + + def testSegmentQsets(self): + segment = SegmentQ() + segment.setPositionInLot(1) + segment.setSenderBank(bank) + segment.setPayer(payer) + segment.setPayerAddress(address) + segment.setGuarantor(guarantor) + segment.setCancel() + response = "3410001300001Q 021000012345678901ARYA STARK AV PAULISTA 1000 01310000SAO PAULO SP1000009876543210SACADOR 000 " + self.assertEquals(segment.content, response) + + def testSegmentRsets(self): + segment = SegmentR() + segment.setPositionInLot(1) + segment.setSenderBank(bank) + segment.setCancel() + segment.setFine(date="14062019", fine=2) # Tests with fine + response = "3410001300001R 02000000000000000000000000000000000000000000000000214062019000000000000002 0000000000000000 000000000000 0 " + self.assertEqual(segment.content, response) + + def testUpdateAmount(self): + # Update Amount Test + file = File() + file.setSender(guarantor) + file.setIssueDate(now) + slip = Slip() + slip.setSender(guarantor) + slip.setPayer(payer) + slip.setExpirationDate(orignalDate) + slip.setBankIdentifier( + identifier="2613", + branch=bank.branchCode, + accountNumber=bank.accountNumber, + wallet="109" + ) + slip.setIdentifier("PRD-5701383420379136") + slip.chargeUpate(amount=125) + file.add(register=slip) + + responseP = "3410001300001P 3107307 000000014446 4109000026130 00000 0000000000000000000012500000099A16072019000000000000000000000000000000000000000000000000000000000000000000000000000000PRD-5701383420379136 0000000000000000000 " + responseQ = "3410001300002Q 010000000000000000 00000000 0000000000000000 000 " + responseR = "3410001300003R 010000000000000000000000000000000000000000000000000 0000000000000000 000000000000 0 " + + print(file.toString()) + print("") + print(responseP) + + self.assertIn(responseP, file.toString()) + self.assertIn(responseQ, file.toString()) + self.assertIn(responseR, file.toString()) + + def testUpdatedueDate(self): + # Update dueDate Test + file = File() + file.setSender(guarantor) + file.setIssueDate(now) + slip = Slip() + slip.setSender(guarantor) + slip.setAmountInCents("100") + slip.setPayer(payer) + slip.setIssueDate(now) + slip.setExpirationDate(orignalDate) + slip.setBankIdentifier( + identifier="2643", + branch=bank.branchCode, + accountNumber=bank.accountNumber, + wallet="109" + ) + slip.setIdentifier("PRD-5207112409939968") + slip.setFineAndInterest(datetime=expiration, fine="0", interest="0") + slip.setOverdueLimit("3") + slip.chargeUpate(dueDate=expiration) + file.add(register=slip) + responseP = "3410001300001P 0607307 000000014446 4109000026437 00000 1707201900000000000010000000099A16072019017072019000000000000000000000000000000000000000000000000000000000000000000000PRD-5207112409939968 0000000000000000000 " + responseQ = "3410001300002Q 010000000000000000 00000000 0000000000000000 000 " + responseR = "3410001300003R 01000000000000000000000000000000000000000000000000017072019000000000000000 0000000000000000 000000000000 0 " + print(file.toString()) + self.assertIn(responseP, file.toString()) + self.assertIn(responseQ, file.toString()) + self.assertIn(responseR, file.toString()) diff --git a/sample-slip-charge-update.py b/sample-slip-charge-update.py new file mode 100644 index 0000000..5edd5dc --- /dev/null +++ b/sample-slip-charge-update.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +from datetime import datetime, timedelta +from febraban.cnab240.itau.charge import Slip, File +from febraban.cnab240.user import User, UserAddress, UserBank + + +myself = User( + name="YOUR COMPANY NAME", + identifier="123456789012345", + bank=UserBank( + bankId="341", + branchCode="1234", + accountNumber="33333", + accountVerifier="4", + bankName="BANCO ITAU SA" + ), + address=UserAddress( + streetLine1="AV PAULISTA 1000", + streetLine2="CJ 601", + city="SAO PAULO", + stateCode="SP", + zipCode="01310000" + ) +) + +payer = User( + name="PAYER NAME", + identifier="12345678901", + address=UserAddress( + streetLine1="AV PAULISTA 1000", + district="BELA VISTA", + city="SAO PAULO", + stateCode="SP", + zipCode="01310000" + ) +) +now = datetime.now() +#expiration = now + timedelta(days=1) +expiration = datetime(day=25, month=07, year=2019) +interestDate = datetime(day=26, month=07, year=2019) +orignalDate = datetime(day=20, month=07, year=2019) +file = File() +file.setSender(myself) +file.setIssueDate(datetime=None) + + +# Update dueDate +slip1 = Slip() +slip1.setSender(myself) +slip1.setAmountInCents("133") +#slip1.setExpirationDate(expiration) +slip1.setBankIdentifier( + identifier="2644", + branch=myself.bank.branchCode, + accountNumber=myself.bank.accountNumber, + wallet="109" +) +slip1.setIdentifier("1917955804102656") +slip1.chargeUpate(dueDate=expiration) + + +# Update Fine +slip2 = Slip() +slip2.setSender(myself) +slip2.setAmountInCents("133") +#slip2.setExpirationDate(orignalDate) +slip2.setBankIdentifier( + identifier="2644", + branch=myself.bank.branchCode, + accountNumber=myself.bank.accountNumber, + wallet="109" +) +slip2.setIdentifier("1917955804102656") +slip2.chargeUpate(fine=300, fineDate=expiration) # 3% + +# Update Interest +slip3 = Slip() +slip3.setSender(myself) +slip3.setAmountInCents("133") +#slip2.setExpirationDate(orignalDate) +slip3.setBankIdentifier( + identifier="2644", + branch=myself.bank.branchCode, + accountNumber=myself.bank.accountNumber, + wallet="109" +) +slip3.setIdentifier("1917955804102656") +slip3.chargeUpate(interest=10, interestDate=interestDate) # 10 cents/day + + +# Update amount +# slip4 = Slip() +# # slip4.setSender(myself) +# # slip3.setIssueDate(now) +# # slip3.setExpirationDate(orignalDate) +# slip4.setBankIdentifier( +# identifier="2644", +# branch=myself.bank.branchCode, +# accountNumber=myself.bank.accountNumber, +# wallet="109" +# ) +# slip4.setIdentifier("PRD-5917955804102656") +# slip4.chargeUpate(amount=135) + +# Create slips +file.add(register=slip1) +file.add(register=slip2) +file.add(register=slip3) +#file.add(register=slip4) + +print(file.toString()) + +file.output(fileName="update10.REM", path="/../../")