Add core-office import-self command, to fix custdata.blueLine
				
					
				
			This commit is contained in:
		
							parent
							
								
									5e1afa2c5c
								
							
						
					
					
						commit
						80084e13da
					
				
					 8 changed files with 237 additions and 4 deletions
				
			
		|  | @ -3,4 +3,6 @@ include *.txt | |||
| include *.rst | ||||
| include *.md | ||||
| 
 | ||||
| recursive-include rattail_corepos/corepos/office/scripts *.php | ||||
| 
 | ||||
| recursive-include rattail_corepos/db/alembic *.py | ||||
|  |  | |||
|  | @ -131,6 +131,12 @@ class RattailCOREPOSExtension(ConfigExtension): | |||
|         config.setdefault('rattail.importing', 'to_corepos_db_lane_op.from_corepos_db_office_op.export.legacy_setting', | ||||
|                           'corepos.lane.importing, office.handler') | ||||
| 
 | ||||
|         # core-office import-self | ||||
|         config.setdefault('rattail.importing', 'to_self.from_corepos_db_office_op.import.default_handler', | ||||
|                           'rattail_corepos.corepos.office.importing.db.local:FromCoreOfficeToSelf') | ||||
|         config.setdefault('rattail.importing', 'to_self.from_corepos_db_office_op.import.default_cmd', | ||||
|                           'core-office import-self') | ||||
| 
 | ||||
|         # crepes export-core | ||||
|         config.setdefault('rattail.importing', 'to_corepos_db_office_op.from_corepos_db_office_op.export.default_handler', | ||||
|                           'rattail_corepos.corepos.importing.db.corepos:FromCoreToCoreExport') | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2021 Lance Edgar | ||||
| #  Copyright © 2010-2023 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
|  | @ -29,6 +29,7 @@ import sys | |||
| from rattail import commands | ||||
| from rattail_corepos import __version__ | ||||
| from rattail.util import load_object | ||||
| from rattail_corepos.corepos.office.util import get_fannie_config_value | ||||
| 
 | ||||
| 
 | ||||
| def main(*args): | ||||
|  | @ -76,3 +77,29 @@ class ExportLaneOp(commands.ImportSubcommand): | |||
|         if 'args' in kwargs: | ||||
|             kwargs['dbkey'] = kwargs['args'].dbkey | ||||
|         return kwargs | ||||
| 
 | ||||
| 
 | ||||
| class GetConfigValue(commands.Subcommand): | ||||
|     """ | ||||
|     Get a value from CORE Office `fannie/config.php` | ||||
|     """ | ||||
|     name = 'get-config-value' | ||||
|     description = __doc__.strip() | ||||
| 
 | ||||
|     def add_parser_args(self, parser): | ||||
|         parser.add_argument('name', metavar='NAME', | ||||
|                             help="Name of the config value to get.  " | ||||
|                             "Prefix of `FANNIE_` is not required.") | ||||
| 
 | ||||
|     def run(self, args): | ||||
|         value = get_fannie_config_value(self.config, args.name) | ||||
|         self.stdout.write(f"{value}\n") | ||||
| 
 | ||||
| 
 | ||||
| class ImportSelf(commands.ImportSubcommand): | ||||
|     """ | ||||
|     Import data from CORE Office ("op" DB) to "self" | ||||
|     """ | ||||
|     name = 'import-self' | ||||
|     description = __doc__.strip() | ||||
|     handler_key = 'to_self.from_corepos_db_office_op.import' | ||||
|  |  | |||
							
								
								
									
										99
									
								
								rattail_corepos/corepos/office/importing/db/local.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								rattail_corepos/corepos/office/importing/db/local.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,99 @@ | |||
| # -*- coding: utf-8; -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2023 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
| #  Rattail is free software: you can redistribute it and/or modify it under the | ||||
| #  terms of the GNU General Public License as published by the Free Software | ||||
| #  Foundation, either version 3 of the License, or (at your option) any later | ||||
| #  version. | ||||
| # | ||||
| #  Rattail is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
| #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
| #  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more | ||||
| #  details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public License along with | ||||
| #  Rattail.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| ################################################################################ | ||||
| """ | ||||
| CORE-POS -> "self" data import | ||||
| """ | ||||
| 
 | ||||
| from collections import OrderedDict | ||||
| 
 | ||||
| from corepos.db.office_op import model as corepos | ||||
| 
 | ||||
| from rattail import importing | ||||
| from rattail_corepos.corepos.office.importing import db as corepos_importing | ||||
| from rattail_corepos.corepos.office.importing.db.corepos import FromCoreHandler | ||||
| from rattail_corepos.corepos.office.util import get_fannie_config_value | ||||
| 
 | ||||
| 
 | ||||
| class FromCoreOfficeToSelf(FromCoreHandler, corepos_importing.model.ToCoreHandler): | ||||
|     """ | ||||
|     Common base class for import handlers which read data from the | ||||
|     CORE Office DB for the sake of updating misc. other tables in that | ||||
|     same DB. | ||||
|     """ | ||||
|     local_key = 'self' | ||||
| 
 | ||||
|     def begin_local_transaction(self): | ||||
|         self.session = self.host_session | ||||
| 
 | ||||
|     def rollback_transaction(self): | ||||
|         self.rollback_host_transaction() | ||||
| 
 | ||||
|     def commit_transaction(self): | ||||
|         self.commit_host_transaction() | ||||
| 
 | ||||
|     def get_importers(self): | ||||
|         importers = OrderedDict() | ||||
|         importers['CustData'] = CustDataImporter | ||||
|         return importers | ||||
| 
 | ||||
| 
 | ||||
| class FromCoreOffice(importing.FromSQLAlchemy): | ||||
|     """ | ||||
|     Common base class for the "host" side of importers which read data | ||||
|     from the CORE Office DB for the sake of updating misc. other | ||||
|     tables in that same DB. | ||||
|     """ | ||||
| 
 | ||||
| 
 | ||||
| class CustDataImporter(FromCoreOffice, corepos_importing.model.CustDataImporter): | ||||
|     """ | ||||
|     custdata -> custdata | ||||
| 
 | ||||
|     Primarily used to update the ``blueLine`` field. | ||||
|     """ | ||||
|     host_model_class = corepos.CustData | ||||
|     supported_fields = [ | ||||
|         'id', | ||||
|         'blue_line', | ||||
|     ] | ||||
|     allow_create = False | ||||
|     allow_delete = False | ||||
| 
 | ||||
|     def setup(self): | ||||
|         super().setup() | ||||
|         self.blueline_template = get_fannie_config_value(self.config, | ||||
|                                                          'BLUELINE_TEMPLATE') | ||||
| 
 | ||||
|     def normalize_host_object(self, customer): | ||||
|         blueline = self.blueline_template | ||||
|         blueline = blueline.replace('{{ACCOUNTNO}}', str(customer.card_number)) | ||||
|         blueline = blueline.replace('{{ACCOUNTTYPE}}', customer.member_type.description) | ||||
|         blueline = blueline.replace('{{FIRSTNAME}}', customer.first_name or '') | ||||
|         blueline = blueline.replace('{{FIRSTINITIAL}}', customer.first_name[0] if customer.first_name else '') | ||||
|         blueline = blueline.replace('{{LASTNAME}}', customer.last_name or '') | ||||
|         blueline = blueline.replace('{{LASTINITIAL}}', customer.last_name[0] if customer.last_name else '') | ||||
| 
 | ||||
|         return { | ||||
|             'id': customer.id, | ||||
|             'blue_line': blueline, | ||||
|         } | ||||
|  | @ -198,12 +198,13 @@ class MemberInfoImporter(ToCore): | |||
|             data['first_name'] = customer.first_name | ||||
|             data['last_name'] = customer.last_name | ||||
| 
 | ||||
|         if self.normalize_phone_numbers: | ||||
|         if self.normalize_phone_numbers and 'phone' in self.fields: | ||||
|             data['phone'] = self.app.normalize_phone_number(data['phone']) | ||||
| 
 | ||||
|         if self.strip_address_street or self.strip_address_all: | ||||
|         if ((self.strip_address_street or self.strip_address_all) | ||||
|             and 'street' in self.fields): | ||||
|             data['street'] = (data['street'] or '').strip() | ||||
|         if self.strip_address_all: | ||||
|         if self.strip_address_all and self.fields_active(['city', 'state', 'zip']): | ||||
|             data['city'] = (data['city'] or '').strip() | ||||
|             data['state'] = (data['state'] or '').strip() | ||||
|             data['zip'] = (data['zip'] or '').strip() | ||||
|  |  | |||
|  | @ -0,0 +1,34 @@ | |||
| <?php | ||||
| 
 | ||||
| $options = getopt('h', array( | ||||
|     'help', | ||||
|     'path:', | ||||
|     'setting:', | ||||
| )); | ||||
| 
 | ||||
| $help = isset($options['h']) or isset($options['help']); | ||||
| $path = isset($options['path']) ? $options['path'] : null; | ||||
| $setting = isset($options['setting']) ? $options['setting'] : null; | ||||
| 
 | ||||
| if ($help or !$path or !$setting) { | ||||
|     $script = basename($argv[0]); | ||||
|     echo "Usage:  $script --path FANNIE_CONFIG_PATH --setting NAME_OF_SETTING\n"; | ||||
|     exit($help ? 0 : 1); | ||||
| } | ||||
| 
 | ||||
| if (!is_file(realpath($path))) { | ||||
|     echo "Config file does not exist: $path\n"; | ||||
|     exit(2); | ||||
| } | ||||
| $path = realpath($path); | ||||
| include($path); | ||||
| 
 | ||||
| if (!isset($$setting)) { | ||||
|     echo "Config file does not contain setting: $setting\n"; | ||||
|     exit(3); | ||||
| } | ||||
| $value = $$setting; | ||||
| 
 | ||||
| echo json_encode($value); | ||||
| 
 | ||||
| ?>
 | ||||
							
								
								
									
										62
									
								
								rattail_corepos/corepos/office/util.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								rattail_corepos/corepos/office/util.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| # -*- coding: utf-8; -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2023 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
| #  Rattail is free software: you can redistribute it and/or modify it under the | ||||
| #  terms of the GNU General Public License as published by the Free Software | ||||
| #  Foundation, either version 3 of the License, or (at your option) any later | ||||
| #  version. | ||||
| # | ||||
| #  Rattail is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
| #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
| #  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more | ||||
| #  details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public License along with | ||||
| #  Rattail.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| ################################################################################ | ||||
| """ | ||||
| CORE Office utility logic | ||||
| """ | ||||
| 
 | ||||
| import json | ||||
| import os | ||||
| import subprocess | ||||
| 
 | ||||
| from rattail.files import resource_path | ||||
| 
 | ||||
| 
 | ||||
| def get_fannie_config_value(config, name): | ||||
|     """ | ||||
|     Retrieve a config value from `fannie/config.php` | ||||
| 
 | ||||
|     :param config: Rattail config object. | ||||
| 
 | ||||
|     :param name: Name of the config value to be returned.  This need | ||||
|        not be prefixed with ``FANNIE_`` although it can be. | ||||
| 
 | ||||
|     :returns: Config value as Python object, e.g. a string or dict. | ||||
|        This is believed to work okay but since the Fannie config file | ||||
|        represents data with PHP code, which is then converted to JSON | ||||
|        and finally to Python, some discrepancies may be possible. | ||||
|     """ | ||||
|     if not name.startswith('FANNIE_'): | ||||
|         name = f'FANNIE_{name}' | ||||
| 
 | ||||
|     is4c = config.require('corepos', 'srcdir') | ||||
|     path = os.path.join(is4c, 'fannie', 'config.php') | ||||
|     script = resource_path('rattail_corepos.corepos.office:scripts/parse-fannie-config.php') | ||||
| 
 | ||||
|     try: | ||||
|         output = subprocess.check_output(['php', script, | ||||
|                                           '--path', path, | ||||
|                                           '--setting', name]) | ||||
|     except subprocess.CalledProcessError as error: | ||||
|         raise ValueError(f"failed to read value: {error.output.decode('utf_8')}") | ||||
| 
 | ||||
|     return json.loads(output.decode('utf_8')) | ||||
|  | @ -42,6 +42,8 @@ console_scripts = | |||
| 
 | ||||
| core_office.commands = | ||||
|         export-lane-op = rattail_corepos.corepos.office.commands:ExportLaneOp | ||||
|         import-self = rattail_corepos.corepos.office.commands:ImportSelf | ||||
|         get-config-value = rattail_corepos.corepos.office.commands:GetConfigValue | ||||
| 
 | ||||
| crepes.commands = | ||||
|         export-core = rattail_corepos.corepos.commands:ExportCore | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar