Compare commits
31 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5a6c89589e | ||
![]() |
785b32c5f0 | ||
![]() |
d1d181bb43 | ||
![]() |
253791134a | ||
![]() |
edbe306bdf | ||
![]() |
dfe820455b | ||
![]() |
69e2720e93 | ||
![]() |
d44c693080 | ||
![]() |
46c07567fe | ||
![]() |
adbf48ba57 | ||
![]() |
d503de44a2 | ||
![]() |
3216d27359 | ||
![]() |
55a7c4a9be | ||
![]() |
0e0823e043 | ||
![]() |
b04816b1ef | ||
![]() |
6612c33b9e | ||
![]() |
7e3c399788 | ||
![]() |
90efc7b945 | ||
![]() |
6cd71ea4c2 | ||
![]() |
a7071d140b | ||
![]() |
8e4b5a2971 | ||
![]() |
eb6bcf8673 | ||
![]() |
d6a0d3b090 | ||
![]() |
0d9f0d1daa | ||
![]() |
2f47bbff9b | ||
![]() |
20a16d5d9d | ||
![]() |
63286679ad | ||
![]() |
719de78413 | ||
![]() |
e46df76a42 | ||
![]() |
2cc9dd0843 | ||
![]() |
8a50e14e2c |
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1 +1,4 @@
|
|||
*~
|
||||
*.pyc
|
||||
dist/
|
||||
rattail_nationbuilder.egg-info/
|
||||
|
|
67
CHANGELOG.md
67
CHANGELOG.md
|
@ -5,6 +5,73 @@ All notable changes to rattail-nationbuilder will be documented in this file.
|
|||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## v0.3.4 (2024-08-19)
|
||||
|
||||
### Fix
|
||||
|
||||
- avoid deprecated method in app provider
|
||||
- avoid deprecated base class for config extension
|
||||
|
||||
## v0.3.3 (2024-08-19)
|
||||
|
||||
### Fix
|
||||
|
||||
- avoid deprecated import for `parse_list()`
|
||||
|
||||
## v0.3.2 (2024-08-13)
|
||||
|
||||
### Fix
|
||||
|
||||
- update app provider entry point, per wuttjamaican
|
||||
|
||||
## v0.3.1 (2024-07-01)
|
||||
|
||||
### Fix
|
||||
|
||||
- remove legacy command definitions
|
||||
|
||||
## v0.3.0 (2024-06-10)
|
||||
|
||||
### Feat
|
||||
|
||||
- switch from setup.cfg to pyproject.toml + hatchling
|
||||
|
||||
## [0.2.0] - 2024-05-29
|
||||
### Changed
|
||||
- Migrate all commands to use `typer`.
|
||||
|
||||
## [0.1.14] - 2023-12-01
|
||||
### Changed
|
||||
- Update subcommand entry point group names, per wuttjamaican.
|
||||
|
||||
## [0.1.13] - 2023-09-16
|
||||
### Changed
|
||||
- Limit page size to 100, for fetching Person records from NB API.
|
||||
|
||||
## [0.1.12] - 2023-09-15
|
||||
### Changed
|
||||
- Add rattail provider for NationBuilder integration.
|
||||
|
||||
## [0.1.11] - 2023-09-13
|
||||
### Changed
|
||||
- Fix schema inconsistencies.
|
||||
|
||||
## [0.1.10] - 2023-09-12
|
||||
### Changed
|
||||
- Assume null if NB person tags are empty.
|
||||
|
||||
## [0.1.9] - 2023-09-12
|
||||
### Changed
|
||||
- Add cache table, importer for NationBuilder donations.
|
||||
|
||||
## [0.1.8] - 2023-09-12
|
||||
### Changed
|
||||
- Fix manifest again..omg.
|
||||
|
||||
## [0.1.7] - 2023-09-12
|
||||
### Changed
|
||||
- Fix manifest...omg.
|
||||
|
||||
## [0.1.6] - 2023-09-12
|
||||
### Changed
|
||||
- Add alembic scripts to manifest.
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
include *.md
|
||||
include *.rst
|
||||
recursive-include rattail_harvest/db/alembic *.mako
|
||||
recursive-include rattail_nationbuilder/db/alembic *.py
|
||||
|
|
55
pyproject.toml
Normal file
55
pyproject.toml
Normal file
|
@ -0,0 +1,55 @@
|
|||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
|
||||
[project]
|
||||
name = "rattail-nationbuilder"
|
||||
version = "0.3.4"
|
||||
description = "Rattail integration package for NationBuilder"
|
||||
readme = "README.md"
|
||||
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
|
||||
license = {text = "GNU GPL v3+"}
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
||||
"Natural Language :: English",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Topic :: Office/Business",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
]
|
||||
dependencies = [
|
||||
"rattail",
|
||||
]
|
||||
|
||||
|
||||
[project.entry-points."rattail.typer_imports"]
|
||||
rattail_nationbuilder = "rattail_nationbuilder.commands"
|
||||
|
||||
|
||||
[project.entry-points."rattail.config.extensions"]
|
||||
rattail_nationbuilder = "rattail_nationbuilder.config:RattailNationBuilderExtension"
|
||||
|
||||
|
||||
[project.entry-points."rattail.importing"]
|
||||
"to_rattail.from_nationbuilder.import" = "rattail_nationbuilder.importing.nationbuilder:FromNationBuilderToRattail"
|
||||
|
||||
|
||||
[project.entry-points."wutta.app.providers"]
|
||||
rattail_nationbuilder = "rattail_nationbuilder.app:NationBuilderProvider"
|
||||
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://rattailproject.org"
|
||||
Repository = "https://forgejo.wuttaproject.org/rattail/rattail-nationbuilder"
|
||||
Changelog = "https://forgejo.wuttaproject.org/rattail/rattail-nationbuilder/src/branch/master/CHANGELOG.md"
|
||||
|
||||
|
||||
[tool.commitizen]
|
||||
version_provider = "pep621"
|
||||
tag_format = "v$version"
|
||||
update_changelog_on_bump = true
|
|
@ -1,3 +1,6 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
__version__ = '0.1.6'
|
||||
from importlib.metadata import version
|
||||
|
||||
|
||||
__version__ = version('rattail-nationbuilder')
|
||||
|
|
56
rattail_nationbuilder/app.py
Normal file
56
rattail_nationbuilder/app.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2024 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/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
App Handler supplement
|
||||
"""
|
||||
|
||||
from rattail.app import RattailProvider, GenericHandler
|
||||
|
||||
|
||||
class NationBuilderProvider(RattailProvider):
|
||||
"""
|
||||
App provider for NationBuilder integration.
|
||||
"""
|
||||
|
||||
def get_nationbuilder_handler(self, **kwargs):
|
||||
if 'nationbuilder' not in self.handlers:
|
||||
spec = self.config.get('rattail', 'nationbuilder.handler',
|
||||
default='rattail_nationbuilder.app:NationBuilderHandler')
|
||||
factory = self.app.load_object(spec)
|
||||
self.handlers['nationbuilder'] = factory(self.config, **kwargs)
|
||||
return self.handlers['nationbuilder']
|
||||
|
||||
|
||||
class NationBuilderHandler(GenericHandler):
|
||||
"""
|
||||
Handler for NationBuilder integration.
|
||||
"""
|
||||
|
||||
def get_url(self, require=False, **kwargs):
|
||||
"""
|
||||
Returns the base URL for the NationBuilder web app.
|
||||
"""
|
||||
getter = self.config.require if require else self.config.get
|
||||
url = getter('nationbuilder', 'url')
|
||||
if url:
|
||||
return url.rstrip('/')
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -24,13 +24,25 @@
|
|||
rattail-nationbuilder commands
|
||||
"""
|
||||
|
||||
from rattail import commands
|
||||
import typer
|
||||
|
||||
from rattail.commands import rattail_typer
|
||||
from rattail.commands.typer import importer_command, typer_get_runas_user
|
||||
from rattail.commands.importing import ImportCommandHandler
|
||||
|
||||
|
||||
class ImportNationBuilder(commands.ImportSubcommand):
|
||||
@rattail_typer.command()
|
||||
@importer_command
|
||||
def import_nationbuilder(
|
||||
ctx: typer.Context,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
Import data for NationBuilder => Rattail
|
||||
"""
|
||||
name = 'import-nationbuilder'
|
||||
description = __doc__.strip()
|
||||
handler_key = 'to_rattail.from_nationbuilder.import'
|
||||
config = ctx.parent.rattail_config
|
||||
progress = ctx.parent.rattail_progress
|
||||
handler = ImportCommandHandler(
|
||||
config, import_handler_key='to_rattail.from_nationbuilder.import')
|
||||
kwargs['user'] = typer_get_runas_user(ctx)
|
||||
handler.run(kwargs, progress=progress)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -24,10 +24,10 @@
|
|||
Config Extension
|
||||
"""
|
||||
|
||||
from rattail.config import ConfigExtension
|
||||
from wuttjamaican.conf import WuttaConfigExtension
|
||||
|
||||
|
||||
class RattailNationBuilderExtension(ConfigExtension):
|
||||
class RattailNationBuilderExtension(WuttaConfigExtension):
|
||||
"""
|
||||
Config extension for rattail-nationbuilder
|
||||
"""
|
||||
|
@ -36,7 +36,7 @@ class RattailNationBuilderExtension(ConfigExtension):
|
|||
def configure(self, config):
|
||||
|
||||
# rattail import-nationbuilder
|
||||
config.setdefault('rattail.importing', 'to_rattail.from_nationbulder.import.default_handler',
|
||||
config.setdefault('rattail.importing.to_rattail.from_nationbulder.import.default_handler',
|
||||
'rattail_nationbuilder.importing.nationbuilder:FromNationBuilderToRattail')
|
||||
config.setdefault('rattail.importing', 'to_rattail.from_nationbuilder.import.default_cmd',
|
||||
config.setdefault('rattail.importing.to_rattail.from_nationbuilder.import.default_cmd',
|
||||
'rattail import-nationbuilder')
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
"""fix nullable
|
||||
|
||||
Revision ID: 7fc3dee0e9c5
|
||||
Revises: c3cb75afcae2
|
||||
Create Date: 2023-09-13 09:12:33.740638
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '7fc3dee0e9c5'
|
||||
down_revision = 'c3cb75afcae2'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import rattail.db.types
|
||||
|
||||
|
||||
|
||||
def upgrade():
|
||||
|
||||
# nationbuilder_cache_donation
|
||||
op.alter_column('nationbuilder_cache_donation_version', 'id',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=True,
|
||||
autoincrement=False)
|
||||
|
||||
|
||||
def downgrade():
|
||||
|
||||
# nationbuilder_cache_donation
|
||||
op.alter_column('nationbuilder_cache_donation_version', 'id',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=False,
|
||||
autoincrement=False)
|
|
@ -0,0 +1,81 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
"""add donations cache table
|
||||
|
||||
Revision ID: c3cb75afcae2
|
||||
Revises: 1e17031c4b3e
|
||||
Create Date: 2023-09-12 19:30:47.583505
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c3cb75afcae2'
|
||||
down_revision = '1e17031c4b3e'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import rattail.db.types
|
||||
|
||||
|
||||
|
||||
def upgrade():
|
||||
|
||||
# nationbuilder_cache_donation
|
||||
op.create_table('nationbuilder_cache_donation',
|
||||
sa.Column('uuid', sa.String(length=32), nullable=False),
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('author_id', sa.Integer(), nullable=True),
|
||||
sa.Column('membership_id', sa.Integer(), nullable=True),
|
||||
sa.Column('donor_id', sa.Integer(), nullable=True),
|
||||
sa.Column('donor_external_id', sa.String(length=50), nullable=True),
|
||||
sa.Column('email', sa.String(length=255), nullable=True),
|
||||
sa.Column('amount', sa.Numeric(precision=10, scale=2), nullable=True),
|
||||
sa.Column('payment_type_name', sa.String(length=100), nullable=True),
|
||||
sa.Column('check_number', sa.String(length=255), nullable=True),
|
||||
sa.Column('tracking_code_slug', sa.String(length=255), nullable=True),
|
||||
sa.Column('note', sa.Text(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('succeeded_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('failed_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('canceled_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('uuid'),
|
||||
sa.UniqueConstraint('id', name='nationbuilder_cache_donation_uq_id')
|
||||
)
|
||||
op.create_table('nationbuilder_cache_donation_version',
|
||||
sa.Column('uuid', sa.String(length=32), autoincrement=False, nullable=False),
|
||||
sa.Column('id', sa.Integer(), autoincrement=False, nullable=False),
|
||||
sa.Column('author_id', sa.Integer(), nullable=True),
|
||||
sa.Column('membership_id', sa.Integer(), nullable=True),
|
||||
sa.Column('donor_id', sa.Integer(), nullable=True),
|
||||
sa.Column('donor_external_id', sa.String(length=50), nullable=True),
|
||||
sa.Column('email', sa.String(length=255), nullable=True),
|
||||
sa.Column('amount', sa.Numeric(precision=10, scale=2), nullable=True),
|
||||
sa.Column('payment_type_name', sa.String(length=100), nullable=True),
|
||||
sa.Column('check_number', sa.String(length=255), nullable=True),
|
||||
sa.Column('tracking_code_slug', sa.String(length=255), nullable=True),
|
||||
sa.Column('note', sa.Text(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('succeeded_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('failed_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('canceled_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('transaction_id', sa.BigInteger(), autoincrement=False, nullable=False),
|
||||
sa.Column('end_transaction_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('operation_type', sa.SmallInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('uuid', 'transaction_id')
|
||||
)
|
||||
op.create_index(op.f('ix_nationbuilder_cache_donation_version_end_transaction_id'), 'nationbuilder_cache_donation_version', ['end_transaction_id'], unique=False)
|
||||
op.create_index(op.f('ix_nationbuilder_cache_donation_version_operation_type'), 'nationbuilder_cache_donation_version', ['operation_type'], unique=False)
|
||||
op.create_index(op.f('ix_nationbuilder_cache_donation_version_transaction_id'), 'nationbuilder_cache_donation_version', ['transaction_id'], unique=False)
|
||||
|
||||
|
||||
def downgrade():
|
||||
|
||||
# nationbuilder_cache_donation
|
||||
op.drop_index(op.f('ix_nationbuilder_cache_donation_version_transaction_id'), table_name='nationbuilder_cache_donation_version')
|
||||
op.drop_index(op.f('ix_nationbuilder_cache_donation_version_operation_type'), table_name='nationbuilder_cache_donation_version')
|
||||
op.drop_index(op.f('ix_nationbuilder_cache_donation_version_end_transaction_id'), table_name='nationbuilder_cache_donation_version')
|
||||
op.drop_table('nationbuilder_cache_donation_version')
|
||||
op.drop_table('nationbuilder_cache_donation')
|
|
@ -24,4 +24,4 @@
|
|||
DB schema for NationBuilder integration
|
||||
"""
|
||||
|
||||
from .nationbuilder import NationBuilderCachePerson
|
||||
from .nationbuilder import NationBuilderCachePerson, NationBuilderCacheDonation
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -27,9 +27,10 @@ NationBuilder cache tables
|
|||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
|
||||
from wuttjamaican.util import parse_list
|
||||
|
||||
from rattail.db import model
|
||||
from rattail.db.util import normalize_full_name
|
||||
from rattail.config import parse_list
|
||||
|
||||
|
||||
class NationBuilderCachePerson(model.Base):
|
||||
|
@ -51,7 +52,7 @@ class NationBuilderCachePerson(model.Base):
|
|||
id = sa.Column(sa.Integer(), nullable=False)
|
||||
signup_type = sa.Column(sa.Integer(), nullable=True)
|
||||
external_id = sa.Column(sa.String(length=50), nullable=True)
|
||||
tags = sa.Column(sa.String(length=255), nullable=True)
|
||||
tags = sa.Column(sa.Text(), nullable=True)
|
||||
first_name = sa.Column(sa.String(length=100), nullable=True)
|
||||
middle_name = sa.Column(sa.String(length=100), nullable=True)
|
||||
last_name = sa.Column(sa.String(length=100), nullable=True)
|
||||
|
@ -79,3 +80,37 @@ class NationBuilderCachePerson(model.Base):
|
|||
if value == tag:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class NationBuilderCacheDonation(model.Base):
|
||||
"""
|
||||
Represents a Donation record in NationBuilder.
|
||||
|
||||
https://apiexplorer.nationbuilder.com/nationbuilder#Donations
|
||||
"""
|
||||
__tablename__ = 'nationbuilder_cache_donation'
|
||||
__table_args__ = (
|
||||
sa.UniqueConstraint('id', name='nationbuilder_cache_donation_uq_id'),
|
||||
)
|
||||
__versioned__ = {}
|
||||
model_title = "NationBuilder Donation"
|
||||
model_title_plural = "NationBuilder Donations"
|
||||
|
||||
uuid = model.uuid_column()
|
||||
|
||||
id = sa.Column(sa.Integer(), nullable=False)
|
||||
author_id = sa.Column(sa.Integer(), nullable=True)
|
||||
membership_id = sa.Column(sa.Integer(), nullable=True)
|
||||
donor_id = sa.Column(sa.Integer(), nullable=True)
|
||||
donor_external_id = sa.Column(sa.String(length=50), nullable=True)
|
||||
email = sa.Column(sa.String(length=255), nullable=True)
|
||||
amount = sa.Column(sa.Numeric(precision=10, scale=2), nullable=True)
|
||||
payment_type_name = sa.Column(sa.String(length=100), nullable=True)
|
||||
check_number = sa.Column(sa.String(length=255), nullable=True)
|
||||
tracking_code_slug = sa.Column(sa.String(length=255), nullable=True)
|
||||
note = sa.Column(sa.Text(), nullable=True)
|
||||
created_at = sa.Column(sa.DateTime(), nullable=True)
|
||||
succeeded_at = sa.Column(sa.DateTime(), nullable=True)
|
||||
failed_at = sa.Column(sa.DateTime(), nullable=True)
|
||||
canceled_at = sa.Column(sa.DateTime(), nullable=True)
|
||||
updated_at = sa.Column(sa.DateTime(), nullable=True)
|
||||
|
|
|
@ -34,3 +34,6 @@ from rattail_nationbuilder.db import model
|
|||
|
||||
class NationBuilderCachePersonImporter(ToRattail):
|
||||
model_class = model.NationBuilderCachePerson
|
||||
|
||||
class NationBuilderCacheDonationImporter(ToRattail):
|
||||
model_class = model.NationBuilderCacheDonation
|
||||
|
|
|
@ -25,6 +25,7 @@ NationBuilder -> Rattail importing
|
|||
"""
|
||||
|
||||
import datetime
|
||||
import decimal
|
||||
from collections import OrderedDict
|
||||
|
||||
from rattail import importing
|
||||
|
@ -43,6 +44,7 @@ class FromNationBuilderToRattail(importing.ToRattailHandler):
|
|||
def get_importers(self):
|
||||
importers = OrderedDict()
|
||||
importers['NationBuilderCachePerson'] = NationBuilderCachePersonImporter
|
||||
importers['NationBuilderCacheDonation'] = NationBuilderCacheDonationImporter
|
||||
return importers
|
||||
|
||||
|
||||
|
@ -58,6 +60,14 @@ class FromNationBuilder(importing.Importer):
|
|||
def setup_api(self):
|
||||
self.nationbuilder = NationBuilderWebAPI(self.config)
|
||||
|
||||
def normalize_timestamp(self, value):
|
||||
if not value:
|
||||
return
|
||||
|
||||
dt = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')
|
||||
dt = self.app.localtime(dt)
|
||||
return self.app.make_utc(dt)
|
||||
|
||||
|
||||
class NationBuilderCachePersonImporter(FromNationBuilder, nationbuilder_importing.model.NationBuilderCachePersonImporter):
|
||||
"""
|
||||
|
@ -93,15 +103,8 @@ class NationBuilderCachePersonImporter(FromNationBuilder, nationbuilder_importin
|
|||
] + primary_address_fields
|
||||
|
||||
def get_host_objects(self):
|
||||
return self.nationbuilder.get_people(page_size=500)
|
||||
|
||||
def normalize_timestamp(self, value):
|
||||
if not value:
|
||||
return
|
||||
|
||||
dt = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')
|
||||
dt = self.app.localtime(dt)
|
||||
return self.app.make_utc(dt)
|
||||
return self.nationbuilder.get_people(page_size=100,
|
||||
progress=self.progress)
|
||||
|
||||
def normalize_host_object(self, person):
|
||||
|
||||
|
@ -117,6 +120,8 @@ class NationBuilderCachePersonImporter(FromNationBuilder, nationbuilder_importin
|
|||
tags = data['tags']
|
||||
if tags:
|
||||
data['tags'] = self.config.make_list_string(tags)
|
||||
else:
|
||||
data['tags'] = None
|
||||
|
||||
if self.fields_active(self.primary_address_fields):
|
||||
address = person.get('primary_address')
|
||||
|
@ -130,3 +135,48 @@ class NationBuilderCachePersonImporter(FromNationBuilder, nationbuilder_importin
|
|||
})
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class NationBuilderCacheDonationImporter(FromNationBuilder, nationbuilder_importing.model.NationBuilderCacheDonationImporter):
|
||||
"""
|
||||
Importer for NB Donation cache
|
||||
"""
|
||||
key = 'id'
|
||||
supported_fields = [
|
||||
'id',
|
||||
'author_id',
|
||||
'membership_id',
|
||||
'donor_id',
|
||||
'donor_external_id',
|
||||
'email',
|
||||
'amount',
|
||||
'payment_type_name',
|
||||
'check_number',
|
||||
'tracking_code_slug',
|
||||
'note',
|
||||
'created_at',
|
||||
'succeeded_at',
|
||||
'failed_at',
|
||||
'canceled_at',
|
||||
'updated_at',
|
||||
]
|
||||
|
||||
def get_host_objects(self):
|
||||
return self.nationbuilder.get_donations(page_size=500)
|
||||
|
||||
def normalize_host_object(self, donation):
|
||||
|
||||
# nb. some fields may not be present in donation dict
|
||||
data = dict([(field, donation.get(field))
|
||||
for field in self.fields])
|
||||
if data:
|
||||
|
||||
donor = donation.get('donor')
|
||||
data['donor_external_id'] = donor.get('external_id') if donor else None
|
||||
|
||||
data['amount'] = decimal.Decimal('{:0.2f}'.format(donation['amount_in_cents'] / 100))
|
||||
|
||||
for field in ('created_at', 'succeeded_at', 'failed_at', 'canceled_at', 'updated_at'):
|
||||
data[field] = self.normalize_timestamp(data[field])
|
||||
|
||||
return data
|
||||
|
|
|
@ -31,6 +31,7 @@ class NationBuilderVersionMixin(object):
|
|||
|
||||
def add_nationbuilder_importers(self, importers):
|
||||
importers['NationBuilderCachePerson'] = NationBuilderCachePersonImporter
|
||||
importers['NationBuilderCacheDonation'] = NationBuilderCacheDonationImporter
|
||||
return importers
|
||||
|
||||
|
||||
|
@ -39,3 +40,10 @@ class NationBuilderCachePersonImporter(base.VersionImporter):
|
|||
@property
|
||||
def host_model_class(self):
|
||||
return self.model.NationBuilderCachePerson
|
||||
|
||||
|
||||
class NationBuilderCacheDonationImporter(base.VersionImporter):
|
||||
|
||||
@property
|
||||
def host_model_class(self):
|
||||
return self.model.NationBuilderCacheDonation
|
||||
|
|
|
@ -24,8 +24,14 @@
|
|||
NationBuilder utils
|
||||
"""
|
||||
|
||||
import warnings
|
||||
|
||||
|
||||
def get_nationbuilder_url(config):
|
||||
url = config.get('nationbuilder', 'url')
|
||||
if url:
|
||||
return url.rstrip('/')
|
||||
warnings.warn("get_nationbuilder_url() function is deprecated; "
|
||||
"please use nationbuilder_handler.get_url() instead",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
|
||||
app = config.get_app()
|
||||
nationbuilder = app.get_nationbuilder_handler()
|
||||
return nationbuilder.get_url()
|
||||
|
|
|
@ -95,6 +95,10 @@ class NationBuilderWebAPI(object):
|
|||
|
||||
https://apiexplorer.nationbuilder.com/nationbuilder#People
|
||||
"""
|
||||
# nb. found this limit in practice, but it is not documented?!
|
||||
if page_size > 100:
|
||||
raise ValueError("page_size cannot be more than 100")
|
||||
|
||||
response = self.get('/api/v1/people/count')
|
||||
count = response.json()['people_count']
|
||||
pages = count // page_size
|
||||
|
|
41
setup.cfg
41
setup.cfg
|
@ -1,41 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
[metadata]
|
||||
name = rattail-nationbuilder
|
||||
version = attr: rattail_nationbuilder.__version__
|
||||
author = Lance Edgar
|
||||
author_email = lance@edbob.org
|
||||
url = https://rattailproject.org/
|
||||
license = GNU GPL v3
|
||||
description = Rattail integration package for NationBuilder
|
||||
long_description = file: README.md
|
||||
classifiers =
|
||||
Development Status :: 4 - Beta
|
||||
Intended Audience :: Developers
|
||||
License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
||||
Natural Language :: English
|
||||
Operating System :: OS Independent
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 3
|
||||
Topic :: Office/Business
|
||||
Topic :: Software Development :: Libraries :: Python Modules
|
||||
|
||||
|
||||
[options]
|
||||
install_requires =
|
||||
rattail
|
||||
|
||||
packages = find:
|
||||
include_package_data = True
|
||||
|
||||
|
||||
[options.entry_points]
|
||||
|
||||
rattail.commands =
|
||||
import-nationbuilder = rattail_nationbuilder.commands:ImportNationBuilder
|
||||
|
||||
rattail.config.extensions =
|
||||
rattail_nationbuilder = rattail_nationbuilder.config:RattailNationBuilderExtension
|
||||
|
||||
rattail.importing =
|
||||
to_rattail.from_nationbuilder.import = rattail_nationbuilder.importing.nationbuilder:FromNationBuilderToRattail
|
29
setup.py
29
setup.py
|
@ -1,29 +0,0 @@
|
|||
# -*- 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/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
rattail-nationbuilder setup script
|
||||
"""
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup()
|
15
tasks.py
15
tasks.py
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -30,22 +30,17 @@ import shutil
|
|||
from invoke import task
|
||||
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
exec(open(os.path.join(here, 'rattail_nationbuilder', '_version.py')).read())
|
||||
|
||||
|
||||
@task
|
||||
def release(c):
|
||||
"""
|
||||
Release a new version of rattail-nationbuilder
|
||||
"""
|
||||
# rebuild local tar.gz file for distribution
|
||||
# rebuild package
|
||||
if os.path.exists('dist'):
|
||||
shutil.rmtree('dist')
|
||||
if os.path.exists('rattail_nationbuilder.egg-info'):
|
||||
shutil.rmtree('rattail_nationbuilder.egg-info')
|
||||
c.run('python -m build --sdist')
|
||||
|
||||
# filename of built package
|
||||
filename = 'rattail-nationbuilder-{}.tar.gz'.format(__version__)
|
||||
|
||||
# upload to PyPI
|
||||
c.run('twine upload dist/{}'.format(filename))
|
||||
c.run('twine upload dist/*')
|
||||
|
|
Loading…
Reference in a new issue