NewBook credentials from central Settings service

Stack-wide NewBook config lives in the Settings app (LXC 116) and is
fetched live via SETTINGS_URL/SETTINGS_SECRET — same pattern as cashup,
room-planner and maintenance. App-local system_config credentials remain
as a fallback for standalone/dev use. The app's Settings → Newbook page
no longer edits credentials; it points to the central app and keeps
Test Connection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-04 19:36:41 +00:00
parent 851747b561
commit aeb99650bd
10 changed files with 226 additions and 230 deletions

View file

@ -496,9 +496,19 @@ def _refresh_date_sync(rate_date: date):
)
config = {row.config_key: row.config_value for row in config_result.fetchall()}
if not all(k in config for k in ['newbook_api_key', 'newbook_username', 'newbook_password', 'newbook_region']):
logger.error("Newbook credentials not configured for single-date refresh")
return
# Central Settings service first, app-local config fallback
from services.central_settings import get_newbook_credentials_sync
creds = get_newbook_credentials_sync()
if not creds:
if not all(k in config for k in ['newbook_api_key', 'newbook_username', 'newbook_password', 'newbook_region']):
logger.error("Newbook credentials not configured for single-date refresh")
return
creds = {
'api_key': config['newbook_api_key'],
'username': config['newbook_username'],
'password': config['newbook_password'],
'region': config['newbook_region'],
}
vat_rate = Decimal(config.get('accommodation_vat_rate', '0.20'))
@ -509,10 +519,10 @@ def _refresh_date_sync(rate_date: date):
included_categories = set(row.site_id for row in cat_result.fetchall())
client = NewbookRatesClient(
api_key=config['newbook_api_key'],
username=config['newbook_username'],
password=config['newbook_password'],
region=config['newbook_region'],
api_key=creds['api_key'],
username=creds['username'],
password=creds['password'],
region=creds['region'],
vat_rate=vat_rate
)

View file

@ -747,10 +747,19 @@ async def _test_newbook(db: AsyncSession):
logger = logging.getLogger(__name__)
api_key = await _get_config_value(db, "newbook_api_key")
username = await _get_config_value(db, "newbook_username")
password = await _get_config_value(db, "newbook_password")
region = await _get_config_value(db, "newbook_region")
# Central Settings service first, app-local config fallback
from services.central_settings import get_newbook_credentials
central = await get_newbook_credentials()
if central:
api_key = central["api_key"]
username = central["username"]
password = central["password"]
region = central["region"]
else:
api_key = await _get_config_value(db, "newbook_api_key")
username = await _get_config_value(db, "newbook_username")
password = await _get_config_value(db, "newbook_password")
region = await _get_config_value(db, "newbook_region")
# Log what we have (masked)
logger.info(f"Testing Newbook: api_key={'set' if api_key else 'empty'}, username={username}, region={region}")

View file

@ -309,7 +309,9 @@ def run_bookings_data_sync(
return row.config_value
return None
creds = {
# Central Settings service first, app-local config fallback
from services.central_settings import get_newbook_credentials_sync
creds = get_newbook_credentials_sync() or {
'api_key': get_config('newbook_api_key'),
'username': get_config('newbook_username'),
'password': get_config('newbook_password'),