33namespace REWEParser ;
44
55use Carbon \Carbon ;
6+ use REWEParser \Exception \PositionNotFoundException ;
67use REWEParser \Exception \ReceiptParseException ;
78
89class Receipt
910{
1011 private $ raw_receipt ;
12+ private $ expl_receipt ;
1113
1214 function __construct (string $ raw_receipt )
1315 {
1416 $ this ->raw_receipt = $ raw_receipt ;
17+ $ this ->expl_receipt = explode ("\n" , $ raw_receipt );
1518 }
1619
1720 /**
@@ -149,6 +152,20 @@ private function getProductEndLine(): int
149152 throw new ReceiptParseException ();
150153 }
151154
155+ /**
156+ * @param string $name
157+ * @return Position
158+ * @throws PositionNotFoundException|ReceiptParseException
159+ */
160+ public function getPositionByName (string $ name ): Position
161+ {
162+ foreach ($ this ->getPositions () as $ position ) {
163+ if ($ position ->getName () == $ name )
164+ return $ position ;
165+ }
166+ throw new PositionNotFoundException ("Position ' $ name' not found " );
167+ }
168+
152169 /**
153170 * @return array
154171 * @throws ReceiptParseException
@@ -157,74 +174,67 @@ public function getPositions(): array
157174 {
158175 $ positions = [];
159176
160- $ startLine = $ this ->getProductStartLine ();
161- $ endLine = $ this ->getProductEndLine ();
162-
163177 $ rawPos = explode ("\n" , $ this ->raw_receipt );
164- $ lastPos = NULL ;
178+ $ lastPosition = NULL ;
165179
166- for ($ lineNr = $ startLine ; $ lineNr <= $ endLine ; $ lineNr ++) {
180+ for ($ lineNr = $ this -> getProductStartLine () ; $ lineNr <= $ this -> getProductEndLine () ; $ lineNr ++) {
167181 $ line = trim ($ rawPos [$ lineNr ]);
168182
169- if (strpos ( $ line , ' Stk x ' ) !== false && $ lastPos != NULL ) {
183+ if ($ this -> isProductLine ( $ lineNr ) ) {
170184
171- if (preg_match ( ' /(-?\d{1,}) Stk x *(-?\d{1,},\d{2})/ ' , $ line , $ match ) ) {
172- $ lastPos [ ' amount ' ] = ( int ) $ match [ 1 ] ;
173- $ lastPos [ ' price_single ' ] = ( float ) str_replace ( ' , ' , ' . ' , $ match [ 2 ]) ;
185+ if ($ lastPosition !== NULL ) {
186+ $ positions [ ] = $ lastPosition ;
187+ $ lastPosition = NULL ;
174188 }
175189
176- } else if (strpos ($ line , 'kg ' ) !== false && $ lastPos != NULL ) {
190+ if (preg_match ('/(.*) (-?\d{1,},\d{2}) (.{1})/ ' , $ line , $ match )) {
191+ $ lastPosition = new Position ();
192+ $ lastPosition ->setName (trim ($ match [1 ]));
193+ $ lastPosition ->setPriceTotal ((float )str_replace (', ' , '. ' , $ match [2 ]));
194+ $ lastPosition ->setTaxCode ($ match [3 ]);
195+ } else throw new ReceiptParseException ("Error while parsing Product line " );
177196
178- if (preg_match ('/(-?\d{1,},\d{3}) kg x *(-?\d{1,},\d{2}) EUR/ ' , $ line , $ match )) {
179- $ lastPos ['weight ' ] = (float )str_replace (', ' , '. ' , $ match [1 ]);
180- $ lastPos ['price_single ' ] = (float )str_replace (', ' , '. ' , $ match [2 ]);
181- } else if (preg_match ('/Handeingabe E-Bon *(-?\d{1,},\d{3}) kg/ ' , $ line , $ match )) {
182- $ lastPos ['weight ' ] = (float )str_replace (', ' , '. ' , $ match [1 ]);
183- }
197+ } else if ($ this ->isAmountLine ($ lineNr )) {
184198
185- } else {
186- if ($ lastPos != NULL && isset ($ lastPos ['name ' ]) && isset ($ lastPos ['price_total ' ])) {
187- if (!isset ($ lastPos ['price_single ' ]) && isset ($ lastPos ['weight ' ]))
188- $ lastPos ['price_single ' ] = $ lastPos ['price_total ' ] / $ lastPos ['weight ' ];
189- if (!isset ($ lastPos ['price_single ' ]) && isset ($ lastPos ['amount ' ]))
190- $ lastPos ['price_single ' ] = $ lastPos ['price_total ' ] / $ lastPos ['amount ' ];
191- if (!isset ($ lastPos ['price_single ' ])) {
192- $ lastPos ['price_single ' ] = $ lastPos ['price_total ' ];
193- $ lastPos ['amount ' ] = 1 ;
194- }
195-
196- $ positions [] = $ lastPos ;
197- $ lastPos = NULL ;
198- }
199+ if (preg_match ('/(-?\d{1,}) Stk x *(-?\d{1,},\d{2})/ ' , $ line , $ match )) {
200+ $ lastPosition ->setAmount ((int )$ match [1 ]);
201+ $ lastPosition ->setPriceSingle ((float )str_replace (', ' , '. ' , $ match [2 ]));
202+ } else throw new ReceiptParseException ("Error while parsing Amount line " );
199203
204+ } else if ($ this ->isWeightLine ($ lineNr )) {
200205
201- if (preg_match ('/(.*) (-?\d{1,},\d{2}) (.{1})/ ' , $ line , $ match )) {
202- $ lastPos = [
203- 'name ' => trim ($ match [1 ]),
204- 'price_total ' => (float )str_replace (', ' , '. ' , $ match [2 ]),
205- 'tax_code ' => $ match [3 ]
206- ];
207- }
206+ if (preg_match ('/(-?\d{1,},\d{3}) kg x *(-?\d{1,},\d{2}) EUR/ ' , $ line , $ match )) {
207+ $ lastPosition ->setWeight ((float )str_replace (', ' , '. ' , $ match [1 ]));
208+ $ lastPosition ->setPriceSingle ((float )str_replace (', ' , '. ' , $ match [2 ]));
209+ } else if (preg_match ('/Handeingabe E-Bon *(-?\d{1,},\d{3}) kg/ ' , $ line , $ match )) {
210+ $ lastPosition ->setWeight ((float )str_replace (', ' , '. ' , $ match [1 ]));
211+ } else throw new ReceiptParseException ("Error while parsing Weight line " );
208212
209- }
210- }
213+ } else throw new ReceiptParseException ("Error while parsing unknown receipt line " );
211214
212- if ($ lastPos != NULL && isset ($ lastPos ['name ' ]) && isset ($ lastPos ['price_total ' ])) {
213- if (!isset ($ lastPos ['price_single ' ]) && isset ($ lastPos ['weight ' ]))
214- $ lastPos ['price_single ' ] = $ lastPos ['price_total ' ] / $ lastPos ['weight ' ];
215- if (!isset ($ lastPos ['price_single ' ]) && isset ($ lastPos ['amount ' ]))
216- $ lastPos ['price_single ' ] = $ lastPos ['price_total ' ] / $ lastPos ['amount ' ];
217- if (!isset ($ lastPos ['price_single ' ])) {
218- $ lastPos ['price_single ' ] = $ lastPos ['price_total ' ];
219- $ lastPos ['amount ' ] = 1 ;
220- }
221- $ positions [] = $ lastPos ;
222- $ lastPos = NULL ;
223215 }
224216
217+ if ($ lastPosition !== NULL )
218+ $ positions [] = $ lastPosition ;
219+
225220 if (count ($ positions ) == 0 )
226- throw new ReceiptParseException ();
221+ throw new ReceiptParseException (" Cannot parse any products on receipt " );
227222
228223 return $ positions ;
229224 }
225+
226+ private function isWeightLine ($ lineNr )
227+ {
228+ return strpos ($ this ->expl_receipt [$ lineNr ], 'kg ' ) !== false ;
229+ }
230+
231+ private function isAmountLine ($ lineNr )
232+ {
233+ return strpos ($ this ->expl_receipt [$ lineNr ], ' Stk x ' ) !== false ;
234+ }
235+
236+ private function isProductLine ($ lineNr )
237+ {
238+ return !$ this ->isWeightLine ($ lineNr ) && !$ this ->isAmountLine ($ lineNr );
239+ }
230240}
0 commit comments