def ledger_data(): from casexml.apps.stock.mock import Balance from casexml.apps.case.mock import CaseFactory from casexml.apps.stock.mock import Entry factory = CaseFactory('domain') with case_data() as case_ids: balance_blocks = [ Balance( entity_id=case_id, date=datetime.utcnow(), section_id='test', entry=Entry(id='chocolate', quantity=4), ).as_xml() for case_id in case_ids ] form, _ = factory.post_case_blocks(balance_blocks) ledgers = LedgerAccessorSQL.get_ledger_values_for_cases(case_ids) try: yield [ledger.ledger_id for ledger in ledgers] finally: form.delete() for ledger in ledgers: ledger.delete()
def case_form_data(): from casexml.apps.case.mock import CaseFactory factory = CaseFactory('domain') cases = [] forms = [] for i in range(3): case_id = uuid.uuid4().hex case_block = factory.get_case_block(case_id, case_type='case_type') form, [case] = factory.post_case_blocks([case_block]) cases.append(case) forms.append(form) case_ids = [case.case_id for case in cases]
class MockDevice(object): def __init__(self, project, user, restore_options=None, sync=False, default_case_type="case", default_owner_id=None): self.id = uuid4().hex self.project = project self.user = user self.user_id = user.user_id self.restore_options = restore_options or {} self.case_blocks = [] self.case_factory = CaseFactory( self.project.name, case_defaults={ 'user_id': self.user_id, 'owner_id': default_owner_id or self.user_id, 'case_type': default_case_type, }, ) self.last_sync = None if sync: self.sync() def change_cases(self, cases=None, **case_kwargs): """Enqueue case changes to be synced Does not post changes to HQ. Use `post_changes()` for that, possibly after enqueuing changes with this method. :param cases: A `CaseBlock` or `CaseStructure` or a list of the same (all must have same type). `CaseStructure` objects will be converted to case XML with defaults from this device's case factory. `CaseBlock` objects will be posted as is (no defaults). :param **case_kwargs: Arguments to be passed to `CaseFactory.get_case_block(...)`, which implies using defaults from this device's case factory. """ factory = self.case_factory if case_kwargs: assert cases is None, "pass one: cases or kwargs" if "case_id" not in case_kwargs: if not case_kwargs.get('create'): raise ValueError("case_id is required for update") case_kwargs["case_id"] = uuid4().hex self.case_blocks.append(factory.get_case_block(**case_kwargs)) return if isinstance(cases, (CaseStructure, CaseBlock)): cases = [cases] elif not isinstance(cases, list): raise ValueError(repr(cases)) if all(isinstance(s, CaseStructure) for s in cases): self.case_blocks.extend(factory.get_case_blocks(cases)) else: self.case_blocks.extend(b.as_xml() for b in cases) def post_changes(self, *args, **kw): """Post enqueued changes from device to HQ Calls `change_cases(*args, **kw)` with any arguments (if given) for convenience. This is the first half of a full sync. It does not affect the latest sync log on the device and can be used when the result of a restore on this device is not important. """ if args or kw: self.change_cases(*args, **kw) if self.case_blocks: # post device case changes token = self.last_sync.restore_id if self.last_sync else None form = self.case_factory.post_case_blocks( self.case_blocks, device_id=self.id, form_extras={"last_sync_token": token}, user_id=self.user_id, )[0] self.case_blocks = [] return form def get_restore_config(self, **options): for name, value in self.restore_options.items(): options.setdefault(name, value) if "device_id" in options: raise ValueError("illegal parameter: device_id") options["device_id"] = self.id options.setdefault('version', V2) if self.last_sync is not None and 'restore_id' not in options: options['restore_id'] = self.last_sync.restore_id return get_restore_config(self.project, self.user, **options) def sync(self, **config): """Synchronize device with HQ""" form = self.post_changes() # restore restore_config = self.get_restore_config(**config) payload = restore_config.get_payload().as_string() self.last_sync = SyncResult(self, restore_config, payload, form) return self.last_sync
class MockDevice(object): def __init__(self, project, user, restore_options=None, sync=False, default_case_type="case", default_owner_id=None): self.id = uuid4().hex self.project = project self.user = user self.user_id = user.user_id self.restore_options = restore_options or {} self.case_blocks = [] self.case_factory = CaseFactory( self.project.name, case_defaults={ 'user_id': self.user_id, 'owner_id': default_owner_id or self.user_id, 'case_type': default_case_type, }, ) self.last_sync = None if sync: self.sync() def change_cases(self, cases=None, **case_kwargs): """Enqueue case changes to be synced Does not post changes to HQ. Use `post_changes()` for that, possibly after enqueuing changes with this method. :param cases: A `CaseBlock` or `CaseStructure` or a list of the same (all must have same type). `CaseStructure` objects will be converted to case XML with defaults from this device's case factory. `CaseBlock` objects will be posted as is (no defaults). :param **case_kwargs: Arguments to be passed to `CaseFactory.get_case_block(...)`, which implies using defaults from this device's case factory. """ factory = self.case_factory if case_kwargs: if cases is not None: raise ValueError("pass one: cases or kwargs") if "case_id" not in case_kwargs: if not case_kwargs.get('create'): raise ValueError("case_id is required for update") case_kwargs["case_id"] = uuid4().hex self.case_blocks.append(factory.get_case_block(**case_kwargs)) return if isinstance(cases, (CaseStructure, CaseBlock)): cases = [cases] elif not isinstance(cases, list): raise ValueError(repr(cases)) if all(isinstance(s, CaseStructure) for s in cases): self.case_blocks.extend(factory.get_case_blocks(cases)) else: self.case_blocks.extend(b.as_xml() for b in cases) def post_changes(self, *args, **kw): """Post enqueued changes from device to HQ Calls `change_cases(*args, **kw)` with any arguments (if given) for convenience. This is the first half of a full sync. It does not affect the latest sync log on the device and can be used when the result of a restore on this device is not important. """ if args or kw: self.change_cases(*args, **kw) if self.case_blocks: # post device case changes token = self.last_sync.restore_id if self.last_sync else None form = self.case_factory.post_case_blocks( self.case_blocks, device_id=self.id, form_extras={"last_sync_token": token}, user_id=self.user_id, )[0] self.case_blocks = [] return form def get_restore_config(self, **options): for name, value in self.restore_options.items(): options.setdefault(name, value) if "device_id" in options: raise ValueError("illegal parameter: device_id") options["device_id"] = self.id options.setdefault('version', V2) if self.last_sync is not None and 'restore_id' not in options: options['restore_id'] = self.last_sync.restore_id return get_restore_config(self.project, self.user, **options) def sync(self, **config): """Synchronize device with HQ""" form = self.post_changes() # restore restore_config = self.get_restore_config(**config) payload = restore_config.get_payload().as_string() self.last_sync = SyncResult(self, restore_config, payload, form) return self.last_sync def restore(self, **config): """Run an initial sync to the device""" self.last_sync = None return self.sync(**config)