1
00:00:00,230 --> 00:00:01,070
Hey, welcome back.

2
00:00:01,070 --> 00:00:08,870
So as I mentioned, we're going to create a package which allows users to create PDF invoices from Excel

3
00:00:08,870 --> 00:00:10,100
invoices.

4
00:00:10,100 --> 00:00:13,910
And we're going to use this code from app number four.

5
00:00:14,030 --> 00:00:19,760
So you can find this code attached in the previous video if you want it.

6
00:00:19,760 --> 00:00:24,980
And I'm just going to copy the Main.py file.

7
00:00:26,180 --> 00:00:27,870
Which you're looking at.

8
00:00:27,890 --> 00:00:33,710
I'm going to copy that file and go to my app 20 Python package project.

9
00:00:33,710 --> 00:00:35,720
So that's the new project I have.

10
00:00:35,780 --> 00:00:39,530
I'm going to paste that main.py file in here.

11
00:00:39,590 --> 00:00:42,410
The first thing we want to do is we want to rename this.

12
00:00:42,410 --> 00:00:45,770
So right click and go to refactor rename.

13
00:00:45,890 --> 00:00:52,070
We want to give it a more meaningful name because this is going to be a public file and this will be

14
00:00:52,070 --> 00:00:56,720
actually the name that's that people programmers will import.

15
00:00:58,380 --> 00:00:59,880
I'm going to just name it.

16
00:00:59,880 --> 00:01:02,280
Invoice and press on refactor.

17
00:01:03,910 --> 00:01:06,070
Let's install the packages.

18
00:01:06,100 --> 00:01:07,600
We need those.

19
00:01:08,380 --> 00:01:08,830
So.

20
00:01:08,830 --> 00:01:10,690
Pandas and fpdf.

21
00:01:14,260 --> 00:01:14,830
Right.

22
00:01:16,140 --> 00:01:20,070
Successful then, as I mentioned in the previous video.

23
00:01:21,570 --> 00:01:29,640
A package needs functions or classes because the way users will import your package will be something

24
00:01:29,640 --> 00:01:30,480
like this.

25
00:01:30,480 --> 00:01:40,260
So let's say we are in Python in the python console or anything else, so users will import invoice.

26
00:01:40,740 --> 00:01:48,000
I'm not executing it because it will execute this code, but let's say we imported it and then users

27
00:01:48,000 --> 00:01:50,400
are going to look for.

28
00:01:51,480 --> 00:01:55,320
Write a function or a class Write.

29
00:01:55,620 --> 00:01:56,910
Such as?

30
00:01:57,710 --> 00:02:00,110
Generates invoice.

31
00:02:00,800 --> 00:02:04,620
So if you want to keep it simple, you can go with a function.

32
00:02:04,640 --> 00:02:09,410
Otherwise, you could create a class here, which could be something like invoice.

33
00:02:09,410 --> 00:02:12,110
And then you'd say invoice.

34
00:02:12,110 --> 00:02:20,690
Well, it's too many invoices, but let's say invoice instance or PDF invoice is equal to that.

35
00:02:20,690 --> 00:02:29,180
And then later in the next line you do pdf invoice dot generate, but we'll keep it simple and just

36
00:02:29,180 --> 00:02:30,740
use a function.

37
00:02:31,100 --> 00:02:38,360
So a function called something like generate, right?

38
00:02:38,360 --> 00:02:40,130
The generate would do it.

39
00:02:40,280 --> 00:02:47,690
It's a good name because we have invoice for the file name, so invoice dot generate would make sense.

40
00:02:47,930 --> 00:02:49,940
It's a readable name.

41
00:02:50,480 --> 00:02:55,640
And I'm going to select all the code inside Def Generate.

42
00:02:56,430 --> 00:03:00,330
And press tab to indent it under this line.

43
00:03:00,330 --> 00:03:03,900
So now these lines are part of the function.

44
00:03:04,230 --> 00:03:05,640
Make some space here.

45
00:03:05,670 --> 00:03:06,060
Right.

46
00:03:06,060 --> 00:03:09,780
So now let's think of the user of the programmers.

47
00:03:10,740 --> 00:03:15,450
The programmers will have some Excel files as input, right?

48
00:03:15,450 --> 00:03:18,720
And they want some PDF files as output.

49
00:03:18,780 --> 00:03:27,840
Therefore we want to allow them to define the directory where their Excel files are located.

50
00:03:28,230 --> 00:03:31,920
And we do that by using a parameter here.

51
00:03:33,390 --> 00:03:34,950
Let's say invoice.

52
00:03:35,620 --> 00:03:41,650
Path or invoices path since we are working with multiple invoices.

53
00:03:42,410 --> 00:03:44,110
PDFs path.

54
00:03:44,500 --> 00:03:52,000
So this would be the folder where the PDF files will be generated and this will be the folder.

55
00:03:52,000 --> 00:03:56,740
So the directory of the path, it could be a sub directory or anything.

56
00:03:56,740 --> 00:03:58,720
So it's a relative path.

57
00:03:58,720 --> 00:04:04,180
So these are relative paths to where the user is working currently.

58
00:04:04,630 --> 00:04:08,350
We'll see more clear when we use this as a user.

59
00:04:08,350 --> 00:04:11,500
When we use the package after we upload it to pi pi.

60
00:04:12,280 --> 00:04:16,959
So we need to to let the user specify these two.

61
00:04:16,959 --> 00:04:23,860
And then of course you need to replace this, maybe make it an F string.

62
00:04:23,890 --> 00:04:26,800
You could also use the path lib library.

63
00:04:26,800 --> 00:04:36,730
But I'm going to keep it simple here and just focus on creating the package So f invoices underscore

64
00:04:36,730 --> 00:04:37,540
path.

65
00:04:38,260 --> 00:04:40,690
So that's parameter goes here.

66
00:04:40,690 --> 00:04:49,870
So whatever the user uses when they call the function like generate or more accurately invoice dot generate

67
00:04:49,870 --> 00:04:56,890
and they will pass here, oh my xls x folder or something like that.

68
00:04:56,920 --> 00:05:02,720
That string is going to go here and then it's going to go here and we expect that the user has XLS X

69
00:05:02,800 --> 00:05:04,960
files inside that directory.

70
00:05:04,960 --> 00:05:13,210
So file paths will be a list of Excel files and then we iterate over that list of Excel files.

71
00:05:13,210 --> 00:05:16,240
We create a PDF document.

72
00:05:16,240 --> 00:05:20,500
So for each iteration we create one separate PDF document.

73
00:05:20,500 --> 00:05:26,860
So in the first iteration we create the first document, we add the page to that PDF.

74
00:05:28,390 --> 00:05:40,750
Then we add all the data and now we assume at this step that the user has some columns with these names,

75
00:05:40,750 --> 00:05:45,160
their right product ID, product name amount purchased.

76
00:05:45,250 --> 00:05:54,550
So currently this package will work only if the user has these exact names in their XLS X files.

77
00:05:54,880 --> 00:05:56,670
Otherwise it will not work.

78
00:05:56,680 --> 00:06:04,210
So if we want to make that more dynamic, so to allow users to have different names for their columns

79
00:06:04,210 --> 00:06:15,220
in the Excel files, we want to also give them the possibility to provide here the names of their columns

80
00:06:15,220 --> 00:06:17,140
as argument values.

81
00:06:17,140 --> 00:06:25,360
So when they call the function, let's say that was the input folder, the output folder perhaps, and

82
00:06:25,360 --> 00:06:27,850
then they will give the names of the columns here.

83
00:06:27,850 --> 00:06:36,080
So for example, if their product ID is not product ID, but its perhaps ID, they will give that column

84
00:06:36,080 --> 00:06:43,430
name in here, followed by product name, which could be perhaps just name Et-cetera.

85
00:06:43,820 --> 00:06:50,420
So let's provide those in here as argument names.

86
00:06:50,420 --> 00:06:54,710
So product ID, you can choose any variable names here.

87
00:06:55,340 --> 00:07:00,200
So product ID, product name.

88
00:07:00,200 --> 00:07:05,720
So that's then I'll get product ID and I'll replace it with this string.

89
00:07:05,720 --> 00:07:11,090
So it's not hardcoded, but we get the value that the user prefers.

90
00:07:11,090 --> 00:07:22,520
So in this case it will be ID and therefore Python will try to access that column with that name from

91
00:07:22,520 --> 00:07:23,720
the Excel file.

92
00:07:23,930 --> 00:07:25,670
So that would be product name.

93
00:07:25,670 --> 00:07:29,500
Again, a variable and amount purchase date.

94
00:07:29,540 --> 00:07:31,760
I'll go for this name again here.

95
00:07:31,790 --> 00:07:36,980
Amount purchased and I'll split it into another line next.

96
00:07:37,220 --> 00:07:41,960
So let's remove the quotes from that price per unit.

97
00:07:46,550 --> 00:07:50,060
Remove the quotes and total price.

98
00:07:53,220 --> 00:07:55,890
Remove the quotes from total price.

99
00:07:55,890 --> 00:07:59,370
So now these columns are not hard coded anymore.

100
00:07:59,520 --> 00:08:00,750
And also here, yeah.

101
00:08:00,780 --> 00:08:04,110
DF So this is to calculate the total price.

102
00:08:04,110 --> 00:08:06,030
So our code is also.

103
00:08:08,000 --> 00:08:15,020
Going through the last column and making the sum of all the numbers here and displaying that in the

104
00:08:15,020 --> 00:08:15,860
PDF.

105
00:08:15,890 --> 00:08:18,980
As you saw in the app for.

106
00:08:19,370 --> 00:08:22,790
So for example, that's the total price, right?

107
00:08:25,350 --> 00:08:26,530
So what else?

108
00:08:26,550 --> 00:08:29,210
What else do we have hardcoded in here?

109
00:08:29,220 --> 00:08:30,340
Let's check.

110
00:08:30,360 --> 00:08:37,049
So usually you should look for quotes and things that smell like python.

111
00:08:37,049 --> 00:08:38,280
Hello dot png.

112
00:08:38,370 --> 00:08:42,419
This is also hardcoded and so let's.

113
00:08:43,700 --> 00:08:45,680
Let's say image path here.

114
00:08:45,680 --> 00:08:52,700
So then we add that here image path as the third argument.

115
00:08:52,700 --> 00:08:55,910
So we're going to expect from the user as the third argument.

116
00:08:57,040 --> 00:08:57,880
Like.

117
00:08:59,170 --> 00:09:01,150
My company dot PNG.

118
00:09:01,180 --> 00:09:04,450
They'll have a file somewhere in their directory.

119
00:09:04,450 --> 00:09:06,610
In their root directory.

120
00:09:07,210 --> 00:09:11,930
Now you'd ask, well, how does the user know what arguments to pass here?

121
00:09:11,950 --> 00:09:18,250
Well, for that we're going to have a docstring here where we will explain this generate function.

122
00:09:18,250 --> 00:09:26,050
So that will be like the help string that the users can then access using something like help invoice

123
00:09:26,050 --> 00:09:29,980
dot generate, you know, something like that.

124
00:09:30,010 --> 00:09:37,750
And that will display the help function for them where we describe to them how they can use the package

125
00:09:38,530 --> 00:09:41,740
or the generate function more specifically here.

126
00:09:43,670 --> 00:09:48,320
And there's one more hardcoded value here, and that is the PDFs.

127
00:09:48,590 --> 00:09:54,110
That is the directory where the PDFs will be generated.

128
00:09:54,530 --> 00:09:58,490
So let's make it a placeholder like that.

129
00:09:58,610 --> 00:10:03,350
And inside here goes PDFs Path.

130
00:10:03,350 --> 00:10:03,890
Right?

131
00:10:03,920 --> 00:10:05,150
PDFs.

132
00:10:05,330 --> 00:10:06,320
Path.

133
00:10:07,400 --> 00:10:12,530
Now this path is supposed to exist.

134
00:10:12,530 --> 00:10:18,920
So therefore we want to access os dot make dares to create that pdf path.

135
00:10:18,920 --> 00:10:27,560
So whatever the user enters here like PDFs, we will generate that directory for the users.

136
00:10:27,560 --> 00:10:29,360
So make sure to import os.

137
00:10:29,400 --> 00:10:30,320
Import os.

138
00:10:30,320 --> 00:10:33,050
So now it will be imported in here.

139
00:10:33,050 --> 00:10:34,490
So os make this.

140
00:10:34,490 --> 00:10:40,040
We create that directory and then we place the pdf files in that directory.

141
00:10:41,940 --> 00:10:49,020
And that's how you can create a function which is now ready and it's package compatible.

142
00:10:49,350 --> 00:10:52,680
So the code now can be used as a package.

143
00:10:52,920 --> 00:10:59,460
Let's finish this video in here and then try the package in the next video as a user.

144
00:10:59,460 --> 00:11:01,590
So to test the package.

145
00:11:01,590 --> 00:11:08,610
So before we upload it to py py, we can test it locally to see if things work.

146
00:11:08,610 --> 00:11:10,350
Let's do the testing in the next video.

