Make POS batch write more accurate dtransactions
				
					
				
			still not complete by any means, but basics should work correctly now
This commit is contained in:
		
							parent
							
								
									b6e21f52ee
								
							
						
					
					
						commit
						81e5837e10
					
				
					 1 changed files with 156 additions and 15 deletions
				
			
		|  | @ -65,30 +65,67 @@ class POSBatchHandler(base.POSBatchHandler): | |||
| 
 | ||||
|     def normalize_dtransactions(self, batch, rows, progress=None): | ||||
|         dtransactions = [] | ||||
|         self.made_subtotal = False | ||||
| 
 | ||||
|         def add(row, i): | ||||
| 
 | ||||
|             # TODO: row types ugh | ||||
| 
 | ||||
|             if row.row_type == 'sell': | ||||
|             if row.row_type == self.enum.POS_ROW_TYPE_SELL: | ||||
|                 d = self.make_d_item(row) | ||||
|                 dtransactions.append(d) | ||||
| 
 | ||||
|             elif row.row_type == 'badscan': | ||||
|             elif row.row_type == self.enum.POS_ROW_TYPE_BADSCAN: | ||||
|                 d = self.make_d_badscan(row) | ||||
|                 dtransactions.append(d) | ||||
| 
 | ||||
|             elif row.row_type in ('set_customer', 'swap_customer'): | ||||
|             elif row.row_type in (self.enum.POS_ROW_TYPE_SET_CUSTOMER, | ||||
|                                   self.enum.POS_ROW_TYPE_SWAP_CUSTOMER): | ||||
|                 d = self.make_d_customer(row) | ||||
|                 dtransactions.append(d) | ||||
| 
 | ||||
|             elif row.row_type == 'tender': | ||||
|             elif row.row_type == self.enum.POS_ROW_TYPE_TENDER: | ||||
| 
 | ||||
|                 if not self.made_subtotal: | ||||
|                     d = self.make_d_subtotal(row, dtransactions) | ||||
|                     dtransactions.append(d) | ||||
|                     self.made_subtotal = True | ||||
| 
 | ||||
|                 d = self.make_d_tender(row) | ||||
|                 dtransactions.append(d) | ||||
| 
 | ||||
|             elif row.row_type == self.enum.POS_ROW_TYPE_CHANGE_BACK: | ||||
| 
 | ||||
|                 d = self.make_d_change(row) | ||||
|                 dtransactions.append(d) | ||||
| 
 | ||||
|                 d = self.make_d_discount(batch, dtransactions) | ||||
|                 dtransactions.append(d) | ||||
| 
 | ||||
|                 d = self.make_d_tax(batch, dtransactions) | ||||
|                 dtransactions.append(d) | ||||
| 
 | ||||
|         self.progress_loop(add, rows, progress, | ||||
|                            message="Normalizing items for CORE-POS transaction") | ||||
| 
 | ||||
|         # now that we have all records, fill in some more values | ||||
|         session = self.app.get_session(batch) | ||||
|         store = self.config.get_store(session) | ||||
|         store_id = store.corepos_id if store else None | ||||
|         register_number = int(batch.terminal_id) | ||||
|         employee_number = batch.cashier.corepos_number | ||||
|         member = self.app.get_member(batch.customer) | ||||
|         member_type = member.membership_type.number if member else None | ||||
|         pos_row_id = f'corepos_pos_row_id_term_{batch.terminal_id}' | ||||
|         self.app.make_counter(session, pos_row_id) | ||||
|         for i, d in enumerate(dtransactions, 1): | ||||
|             d.store_id = store_id | ||||
|             d.register_number = register_number | ||||
|             d.employee_number = employee_number | ||||
|             d.card_number = batch.customer.number | ||||
|             d.member_type = member_type | ||||
|             d.staff = batch.customer_is_employee | ||||
|             d.transaction_id = i | ||||
|             d.pos_row_id = self.app.next_counter_value(session, pos_row_id) | ||||
| 
 | ||||
|         return dtransactions | ||||
| 
 | ||||
|     def make_d_basic(self, batch=None, row=None): | ||||
|  | @ -108,21 +145,38 @@ class POSBatchHandler(base.POSBatchHandler): | |||
|             # nb. batch.created *should* have a value..if not this would be "now" | ||||
|             d.date_time = self.app.localtime(batch.created, from_utc=True) | ||||
| 
 | ||||
|         if batch.terminal_id and batch.terminal_id.isdigit(): | ||||
|             d.register_number = int(batch.terminal_id) | ||||
| 
 | ||||
|         if batch.customer: | ||||
|             d.card_number = batch.customer.number | ||||
| 
 | ||||
|         d.quantity = 0 | ||||
|         # TODO: i *think* all these are safe defaults, and can | ||||
|         # override per line item as needed | ||||
|         d.transaction_status = '' | ||||
|         d.department_number = 0 | ||||
|         d.unit_price = 0 | ||||
|         d.reg_price = 0 | ||||
|         d.tax_rate_id = 0 | ||||
|         d.food_stamp = False | ||||
|         d.member_discount = 0 | ||||
|         d.discount_type = 0 | ||||
|         d.percent_discount = 0 | ||||
|         d.quantity = 0 | ||||
|         d.item_quantity = 0 | ||||
|         d.volume_discount_type = 0 | ||||
|         d.volume_special = 0 | ||||
|         d.mix_match = 0 | ||||
|         d.upc = '0' | ||||
|         d.num_flag = 0 | ||||
|         d.char_flag = '' | ||||
|         d.cost = 0 | ||||
|         d.discount = 0 | ||||
|         d.discountable = False | ||||
|         d.total = 0 | ||||
|         # d.voided = False        # TODO | ||||
|         d.voided = 0 | ||||
|         d.volume = 0 | ||||
|         d.matched = False | ||||
| 
 | ||||
|         return d | ||||
| 
 | ||||
|     def make_d_badscan(self, row): | ||||
|         d = self.make_d_basic(row=row) | ||||
| 
 | ||||
|         d.description = 'BADSCAN' | ||||
| 
 | ||||
|         d.upc = row.item_entry | ||||
|  | @ -135,17 +189,31 @@ class POSBatchHandler(base.POSBatchHandler): | |||
|         return d | ||||
| 
 | ||||
|     def make_d_customer(self, row): | ||||
|         batch = row.batch | ||||
|         d = self.make_d_basic(row=row) | ||||
| 
 | ||||
|         d.upc = 'MEMENTRY' | ||||
|         d.description = 'CARDNO IN NUMFLAG' | ||||
| 
 | ||||
|         # TODO: what do these mean? are they correct? | ||||
|         d.transaction_type = 'L' | ||||
|         d.transaction_subtype = 'OG' | ||||
|         d.transaction_status = 'D' | ||||
|         d.num_flag = batch.customer.number | ||||
|         d.char_flag = '1' | ||||
| 
 | ||||
|         return d | ||||
| 
 | ||||
|     def make_d_item(self, row): | ||||
|         batch = row.batch | ||||
|         session = self.app.get_session(batch) | ||||
|         d = self.make_d_basic(batch, row) | ||||
| 
 | ||||
|         d.transaction_type = 'I' | ||||
|         d.transaction_subtype = 'NA' | ||||
|         d.upc = row.product.item_id | ||||
|         d.department_number = row.department_number | ||||
|         d.food_stamp = row.foodstamp_eligible | ||||
| 
 | ||||
|         d.description = row.product.description | ||||
|         if d.description and len(d.description) > self.maxlen_description: | ||||
|  | @ -153,18 +221,91 @@ class POSBatchHandler(base.POSBatchHandler): | |||
|                       self.maxlen_description, len(d.description), d.description) | ||||
|             d.description = d.description[:self.maxlen_description] | ||||
| 
 | ||||
|         # TODO: should item_quantity ever differ?  see also | ||||
|         # https://github.com/CORE-POS/IS4C/wiki/Office-Transaction-Database#dtransactions | ||||
|         d.quantity = row.quantity | ||||
|         d.item_quantity = row.quantity | ||||
| 
 | ||||
|         if row.product.cost: | ||||
|             d.cost = row.product.cost.unit_cost | ||||
| 
 | ||||
|         d.unit_price = row.txn_price | ||||
|         d.reg_price = row.reg_price | ||||
|         d.discountable = row.product.discountable | ||||
| 
 | ||||
|         d.tax_rate_id = 0 | ||||
|         if row.tax_code: | ||||
|             tax = self.get_tax(session, row.tax_code) | ||||
|             d.tax_rate_id = tax.corepos_id | ||||
|             if not d.tax_rate_id: | ||||
|                 log.error("tax not found in CORE-POS: %s", row.tax_code) | ||||
|                 d.tax_rate_id = 0 | ||||
| 
 | ||||
|         d.total = row.sales_total | ||||
|         # d.voided = False        # TODO | ||||
|         # TODO: if void, should the above change too? | ||||
|         d.voided = 1 if row.void else 0 | ||||
| 
 | ||||
|         return d | ||||
| 
 | ||||
|     def make_d_subtotal(self, row, dtransactions): | ||||
|         batch = row.batch | ||||
|         d = self.make_d_basic(batch, row) | ||||
| 
 | ||||
|         d.transaction_type = 'C' | ||||
|         d.transaction_status = 'D' | ||||
|         d.voided = 3            # TODO (?) | ||||
| 
 | ||||
|         d.unit_price = sum([detail.total | ||||
|                             for detail in dtransactions]) | ||||
| 
 | ||||
|         # TODO | ||||
|         tax = 0 | ||||
| 
 | ||||
|         d.description = f"Subtotal {d.unit_price:0.2f}, Tax{tax:0.2f} #{batch.customer.number}" | ||||
| 
 | ||||
|         return d | ||||
| 
 | ||||
|     def make_d_tender(self, row): | ||||
|         batch = row.batch | ||||
|         d = self.make_d_basic(batch, row) | ||||
| 
 | ||||
|         d.transaction_type = 'T' | ||||
|         d.transaction_subtype = row.item_entry | ||||
|         d.description = row.description | ||||
|         d.total = row.tender_total | ||||
| 
 | ||||
|         return d | ||||
| 
 | ||||
|     def make_d_change(self, row): | ||||
|         batch = row.batch | ||||
|         d = self.make_d_basic(batch, row) | ||||
| 
 | ||||
|         d.transaction_type = 'T' | ||||
|         d.transaction_subtype = row.item_entry | ||||
|         d.description = "Change" | ||||
|         d.total = row.tender_total | ||||
| 
 | ||||
|         if not d.total: | ||||
|             d.voided = 8        # TODO (?) | ||||
| 
 | ||||
|         return d | ||||
| 
 | ||||
|     def make_d_discount(self, batch, dtransactions): | ||||
|         d = self.make_d_basic(batch) | ||||
| 
 | ||||
|         d.transaction_type = 'S' | ||||
|         d.upc = 'DISCOUNT' | ||||
|         d.quantity = 1 | ||||
|         d.item_quantity = 1 | ||||
|         d.description = "Discount" | ||||
| 
 | ||||
|         return d | ||||
| 
 | ||||
|     def make_d_tax(self, batch, dtransactions): | ||||
|         d = self.make_d_basic(batch) | ||||
| 
 | ||||
|         d.transaction_type = 'A' | ||||
|         d.upc = 'TAX' | ||||
|         d.description = "Tax" | ||||
| 
 | ||||
|         return d | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar